|
@@ -918,6 +918,90 @@ int se_dev_set_emulate_3pc(struct se_device *dev, int flag)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+int se_dev_set_pi_prot_type(struct se_device *dev, int flag)
|
|
|
+{
|
|
|
+ int rc, old_prot = dev->dev_attrib.pi_prot_type;
|
|
|
+
|
|
|
+ if (flag != 0 && flag != 1 && flag != 2 && flag != 3) {
|
|
|
+ pr_err("Illegal value %d for pi_prot_type\n", flag);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ if (flag == 2) {
|
|
|
+ pr_err("DIF TYPE2 protection currently not supported\n");
|
|
|
+ return -ENOSYS;
|
|
|
+ }
|
|
|
+ if (dev->dev_attrib.hw_pi_prot_type) {
|
|
|
+ pr_warn("DIF protection enabled on underlying hardware,"
|
|
|
+ " ignoring\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if (!dev->transport->init_prot || !dev->transport->free_prot) {
|
|
|
+ pr_err("DIF protection not supported by backend: %s\n",
|
|
|
+ dev->transport->name);
|
|
|
+ return -ENOSYS;
|
|
|
+ }
|
|
|
+ if (!(dev->dev_flags & DF_CONFIGURED)) {
|
|
|
+ pr_err("DIF protection requires device to be configured\n");
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
+ if (dev->export_count) {
|
|
|
+ pr_err("dev[%p]: Unable to change SE Device PROT type while"
|
|
|
+ " export_count is %d\n", dev, dev->export_count);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ dev->dev_attrib.pi_prot_type = flag;
|
|
|
+
|
|
|
+ if (flag && !old_prot) {
|
|
|
+ rc = dev->transport->init_prot(dev);
|
|
|
+ if (rc) {
|
|
|
+ dev->dev_attrib.pi_prot_type = old_prot;
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
+
|
|
|
+ } else if (!flag && old_prot) {
|
|
|
+ dev->transport->free_prot(dev);
|
|
|
+ }
|
|
|
+ pr_debug("dev[%p]: SE Device Protection Type: %d\n", dev, flag);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int se_dev_set_pi_prot_format(struct se_device *dev, int flag)
|
|
|
+{
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ if (!flag)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (flag != 1) {
|
|
|
+ pr_err("Illegal value %d for pi_prot_format\n", flag);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ if (!dev->transport->format_prot) {
|
|
|
+ pr_err("DIF protection format not supported by backend %s\n",
|
|
|
+ dev->transport->name);
|
|
|
+ return -ENOSYS;
|
|
|
+ }
|
|
|
+ if (!(dev->dev_flags & DF_CONFIGURED)) {
|
|
|
+ pr_err("DIF protection format requires device to be configured\n");
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
+ if (dev->export_count) {
|
|
|
+ pr_err("dev[%p]: Unable to format SE Device PROT type while"
|
|
|
+ " export_count is %d\n", dev, dev->export_count);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ rc = dev->transport->format_prot(dev);
|
|
|
+ if (rc)
|
|
|
+ return rc;
|
|
|
+
|
|
|
+ pr_debug("dev[%p]: SE Device Protection Format complete\n", dev);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
int se_dev_set_enforce_pr_isids(struct se_device *dev, int flag)
|
|
|
{
|
|
|
if ((flag != 0) && (flag != 1)) {
|
|
@@ -1415,6 +1499,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
|
|
|
dev->dev_link_magic = SE_DEV_LINK_MAGIC;
|
|
|
dev->se_hba = hba;
|
|
|
dev->transport = hba->transport;
|
|
|
+ dev->prot_length = sizeof(struct se_dif_v1_tuple);
|
|
|
|
|
|
INIT_LIST_HEAD(&dev->dev_list);
|
|
|
INIT_LIST_HEAD(&dev->dev_sep_list);
|
|
@@ -1457,6 +1542,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
|
|
|
dev->dev_attrib.emulate_tpws = DA_EMULATE_TPWS;
|
|
|
dev->dev_attrib.emulate_caw = DA_EMULATE_CAW;
|
|
|
dev->dev_attrib.emulate_3pc = DA_EMULATE_3PC;
|
|
|
+ dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE0_PROT;
|
|
|
dev->dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS;
|
|
|
dev->dev_attrib.is_nonrot = DA_IS_NONROT;
|
|
|
dev->dev_attrib.emulate_rest_reord = DA_EMULATE_REST_REORD;
|
|
@@ -1589,6 +1675,9 @@ void target_free_device(struct se_device *dev)
|
|
|
core_scsi3_free_all_registrations(dev);
|
|
|
se_release_vpd_for_dev(dev);
|
|
|
|
|
|
+ if (dev->transport->free_prot)
|
|
|
+ dev->transport->free_prot(dev);
|
|
|
+
|
|
|
dev->transport->free_device(dev);
|
|
|
}
|
|
|
|