diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-12 15:43:02 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-12 15:43:02 -0800 |
| commit | d4a379a52c3c2dc44366c4f6722c063a7d0de179 (patch) | |
| tree | 3b705036e2c5d2135f2b51ec43404da288c0db77 /drivers/target | |
| parent | 041c16acbafbdd8c089cc077c78e060322dde18c (diff) | |
| parent | 1982257570b84dc33753d536dd969fd357a014e9 (diff) | |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"Usual driver updates (qla2xxx, mpi3mr, mpt3sas, ufs) plus assorted
cleanups and fixes.
The biggest core change is the massive code motion in the sd driver to
remove forward declarations and the most significant change is to
enumify the queuecommand return"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (78 commits)
scsi: csiostor: Fix dereference of null pointer rn
scsi: buslogic: Reduce stack usage
scsi: ufs: host: mediatek: Require CONFIG_PM
scsi: ufs: mediatek: Fix page faults in ufs_mtk_clk_scale() trace event
scsi: smartpqi: Fix memory leak in pqi_report_phys_luns()
scsi: mpi3mr: Make driver probing asynchronous
scsi: ufs: core: Flush exception handling work when RPM level is zero
scsi: efct: Use IRQF_ONESHOT and default primary handler
scsi: ufs: core: Use a host-wide tagset in SDB mode
scsi: qla2xxx: target: Add WQ_PERCPU to alloc_workqueue() users
scsi: qla2xxx: Add WQ_PERCPU to alloc_workqueue() users
scsi: qla4xxx: Add WQ_PERCPU to alloc_workqueue() users
scsi: mpi3mr: Driver version update to 8.17.0.3.50
scsi: mpi3mr: Fixed the W=1 compilation warning
scsi: mpi3mr: Record and report controller firmware faults
scsi: mpi3mr: Update MPI Headers to revision 39
scsi: mpi3mr: Use negotiated link rate from DevicePage0
scsi: mpi3mr: Avoid redundant diag-fault resets
scsi: mpi3mr: Rename log data save helper to reflect threaded/BH context
scsi: mpi3mr: Add module parameter to control threaded IRQ polling
...
Diffstat (limited to 'drivers/target')
| -rw-r--r-- | drivers/target/loopback/tcm_loop.c | 3 | ||||
| -rw-r--r-- | drivers/target/target_core_configfs.c | 68 | ||||
| -rw-r--r-- | drivers/target/target_core_fabric_configfs.c | 30 | ||||
| -rw-r--r-- | drivers/target/target_core_spc.c | 86 |
4 files changed, 162 insertions, 25 deletions
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index 01a8e349dc4d..0821a149573e 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c @@ -165,7 +165,8 @@ out_done: * ->queuecommand can be and usually is called from interrupt context, so * defer the actual submission to a workqueue. */ -static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc) +static enum scsi_qc_status tcm_loop_queuecommand(struct Scsi_Host *sh, + struct scsi_cmnd *sc) { struct tcm_loop_cmd *tl_cmd = scsi_cmd_priv(sc); diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index f7868b41c5e6..b27a3b8dd767 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -288,7 +288,7 @@ static void target_core_deregister_fabric( config_item_put(item); } -static struct configfs_group_operations target_core_fabric_group_ops = { +static const struct configfs_group_operations target_core_fabric_group_ops = { .make_group = &target_core_register_fabric, .drop_item = &target_core_deregister_fabric, }; @@ -1741,6 +1741,54 @@ static ssize_t target_wwn_vpd_protocol_identifier_show(struct config_item *item, return len; } +static ssize_t target_wwn_pd_text_id_info_show(struct config_item *item, + char *page) +{ + return sysfs_emit(page, "%s\n", &to_t10_wwn(item)->pd_text_id_info[0]); +} + +static ssize_t target_wwn_pd_text_id_info_store(struct config_item *item, + const char *page, size_t count) +{ + struct t10_wwn *t10_wwn = to_t10_wwn(item); + struct se_device *dev = t10_wwn->t10_dev; + + /* +2 to allow for a trailing (stripped) '\n' and null-terminator */ + unsigned char buf[PD_TEXT_ID_INFO_LEN + 2]; + char *stripped; + + /* + * Check to see if any active exports exist. If they do exist, fail + * here as changing this information on the fly (underneath the + * initiator side OS dependent multipath code) could cause negative + * effects. + */ + if (dev->export_count) { + pr_err("Unable to set the peripheral device text id info while active %d exports exist\n", + dev->export_count); + return -EINVAL; + } + + if (strscpy(buf, page, sizeof(buf)) < 0) + return -EOVERFLOW; + + /* Strip any newline added from userspace. */ + stripped = strstrip(buf); + if (strlen(stripped) >= PD_TEXT_ID_INFO_LEN) { + pr_err("Emulated peripheral device text id info exceeds PD_TEXT_ID_INFO_LEN: " __stringify(PD_TEXT_ID_INFO_LEN "\n")); + return -EOVERFLOW; + } + + BUILD_BUG_ON(sizeof(dev->t10_wwn.pd_text_id_info) != PD_TEXT_ID_INFO_LEN); + strscpy(dev->t10_wwn.pd_text_id_info, stripped, + sizeof(dev->t10_wwn.pd_text_id_info)); + + pr_debug("Target_Core_ConfigFS: Set emulated peripheral dev text id info:" + " %s\n", dev->t10_wwn.pd_text_id_info); + + return count; +} + /* * Generic wrapper for dumping VPD identifiers by association. */ @@ -1797,6 +1845,7 @@ CONFIGFS_ATTR_RO(target_wwn_, vpd_protocol_identifier); CONFIGFS_ATTR_RO(target_wwn_, vpd_assoc_logical_unit); CONFIGFS_ATTR_RO(target_wwn_, vpd_assoc_target_port); CONFIGFS_ATTR_RO(target_wwn_, vpd_assoc_scsi_target_device); +CONFIGFS_ATTR(target_wwn_, pd_text_id_info); static struct configfs_attribute *target_core_dev_wwn_attrs[] = { &target_wwn_attr_vendor_id, @@ -1808,6 +1857,7 @@ static struct configfs_attribute *target_core_dev_wwn_attrs[] = { &target_wwn_attr_vpd_assoc_logical_unit, &target_wwn_attr_vpd_assoc_target_port, &target_wwn_attr_vpd_assoc_scsi_target_device, + &target_wwn_attr_pd_text_id_info, NULL, }; @@ -2810,7 +2860,7 @@ static void target_core_alua_lu_gp_release(struct config_item *item) core_alua_free_lu_gp(lu_gp); } -static struct configfs_item_operations target_core_alua_lu_gp_ops = { +static const struct configfs_item_operations target_core_alua_lu_gp_ops = { .release = target_core_alua_lu_gp_release, }; @@ -2867,7 +2917,7 @@ static void target_core_alua_drop_lu_gp( config_item_put(item); } -static struct configfs_group_operations target_core_alua_lu_gps_group_ops = { +static const struct configfs_group_operations target_core_alua_lu_gps_group_ops = { .make_group = &target_core_alua_create_lu_gp, .drop_item = &target_core_alua_drop_lu_gp, }; @@ -3240,7 +3290,7 @@ static void target_core_alua_tg_pt_gp_release(struct config_item *item) core_alua_free_tg_pt_gp(tg_pt_gp); } -static struct configfs_item_operations target_core_alua_tg_pt_gp_ops = { +static const struct configfs_item_operations target_core_alua_tg_pt_gp_ops = { .release = target_core_alua_tg_pt_gp_release, }; @@ -3298,7 +3348,7 @@ static void target_core_alua_drop_tg_pt_gp( config_item_put(item); } -static struct configfs_group_operations target_core_alua_tg_pt_gps_group_ops = { +static const struct configfs_group_operations target_core_alua_tg_pt_gps_group_ops = { .make_group = &target_core_alua_create_tg_pt_gp, .drop_item = &target_core_alua_drop_tg_pt_gp, }; @@ -3339,7 +3389,7 @@ static void target_core_stat_rmdir( return; } -static struct configfs_group_operations target_core_stat_group_ops = { +static const struct configfs_group_operations target_core_stat_group_ops = { .make_group = &target_core_stat_mkdir, .drop_item = &target_core_stat_rmdir, }; @@ -3466,7 +3516,7 @@ static void target_core_drop_subdev( mutex_unlock(&hba->hba_access_mutex); } -static struct configfs_group_operations target_core_hba_group_ops = { +static const struct configfs_group_operations target_core_hba_group_ops = { .make_group = target_core_make_subdev, .drop_item = target_core_drop_subdev, }; @@ -3545,7 +3595,7 @@ static struct configfs_attribute *target_core_hba_attrs[] = { NULL, }; -static struct configfs_item_operations target_core_hba_item_ops = { +static const struct configfs_item_operations target_core_hba_item_ops = { .release = target_core_hba_release, }; @@ -3626,7 +3676,7 @@ static void target_core_call_delhbafromtarget( config_item_put(item); } -static struct configfs_group_operations target_core_group_ops = { +static const struct configfs_group_operations target_core_group_ops = { .make_group = target_core_call_addhbatotarget, .drop_item = target_core_call_delhbafromtarget, }; diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 13159928e365..59713e9be10a 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -59,7 +59,7 @@ static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) pr_debug("Setup generic %s\n", __stringify(_name)); \ } -static struct configfs_item_operations target_fabric_port_item_ops; +static const struct configfs_item_operations target_fabric_port_item_ops; /* Start of tfc_tpg_mappedlun_cit */ @@ -219,7 +219,7 @@ static void target_fabric_mappedlun_release(struct config_item *item) core_dev_free_initiator_node_lun_acl(se_tpg, lacl); } -static struct configfs_item_operations target_fabric_mappedlun_item_ops = { +static const struct configfs_item_operations target_fabric_mappedlun_item_ops = { .release = target_fabric_mappedlun_release, .allow_link = target_fabric_mappedlun_link, .drop_link = target_fabric_mappedlun_unlink, @@ -246,7 +246,7 @@ static void target_core_mappedlun_stat_rmdir( return; } -static struct configfs_group_operations target_fabric_mappedlun_stat_group_ops = { +static const struct configfs_group_operations target_fabric_mappedlun_stat_group_ops = { .make_group = target_core_mappedlun_stat_mkdir, .drop_item = target_core_mappedlun_stat_rmdir, }; @@ -345,11 +345,11 @@ static void target_fabric_nacl_base_release(struct config_item *item) core_tpg_del_initiator_node_acl(se_nacl); } -static struct configfs_item_operations target_fabric_nacl_base_item_ops = { +static const struct configfs_item_operations target_fabric_nacl_base_item_ops = { .release = target_fabric_nacl_base_release, }; -static struct configfs_group_operations target_fabric_nacl_base_group_ops = { +static const struct configfs_group_operations target_fabric_nacl_base_group_ops = { .make_group = target_fabric_make_mappedlun, .drop_item = target_fabric_drop_mappedlun, }; @@ -433,7 +433,7 @@ static void target_fabric_drop_nodeacl( config_item_put(item); } -static struct configfs_group_operations target_fabric_nacl_group_ops = { +static const struct configfs_group_operations target_fabric_nacl_group_ops = { .make_group = target_fabric_make_nodeacl, .drop_item = target_fabric_drop_nodeacl, }; @@ -454,7 +454,7 @@ static void target_fabric_np_base_release(struct config_item *item) tf->tf_ops->fabric_drop_np(se_tpg_np); } -static struct configfs_item_operations target_fabric_np_base_item_ops = { +static const struct configfs_item_operations target_fabric_np_base_item_ops = { .release = target_fabric_np_base_release, }; @@ -499,7 +499,7 @@ static void target_fabric_drop_np( config_item_put(item); } -static struct configfs_group_operations target_fabric_np_group_ops = { +static const struct configfs_group_operations target_fabric_np_group_ops = { .make_group = &target_fabric_make_np, .drop_item = &target_fabric_drop_np, }; @@ -700,7 +700,7 @@ static void target_fabric_port_release(struct config_item *item) call_rcu(&lun->rcu_head, target_tpg_free_lun); } -static struct configfs_item_operations target_fabric_port_item_ops = { +static const struct configfs_item_operations target_fabric_port_item_ops = { .release = target_fabric_port_release, .allow_link = target_fabric_port_link, .drop_link = target_fabric_port_unlink, @@ -726,7 +726,7 @@ static void target_core_port_stat_rmdir( return; } -static struct configfs_group_operations target_fabric_port_stat_group_ops = { +static const struct configfs_group_operations target_fabric_port_stat_group_ops = { .make_group = target_core_port_stat_mkdir, .drop_item = target_core_port_stat_rmdir, }; @@ -787,7 +787,7 @@ static void target_fabric_drop_lun( config_item_put(item); } -static struct configfs_group_operations target_fabric_lun_group_ops = { +static const struct configfs_group_operations target_fabric_lun_group_ops = { .make_group = &target_fabric_make_lun, .drop_item = &target_fabric_drop_lun, }; @@ -812,7 +812,7 @@ static void target_fabric_tpg_release(struct config_item *item) tf->tf_ops->fabric_drop_tpg(se_tpg); } -static struct configfs_item_operations target_fabric_tpg_base_item_ops = { +static const struct configfs_item_operations target_fabric_tpg_base_item_ops = { .release = target_fabric_tpg_release, }; @@ -998,11 +998,11 @@ static void target_fabric_release_wwn(struct config_item *item) tf->tf_ops->fabric_drop_wwn(wwn); } -static struct configfs_item_operations target_fabric_tpg_item_ops = { +static const struct configfs_item_operations target_fabric_tpg_item_ops = { .release = target_fabric_release_wwn, }; -static struct configfs_group_operations target_fabric_tpg_group_ops = { +static const struct configfs_group_operations target_fabric_tpg_group_ops = { .make_group = target_fabric_make_tpg, .drop_item = target_fabric_drop_tpg, }; @@ -1144,7 +1144,7 @@ static void target_fabric_drop_wwn( config_item_put(item); } -static struct configfs_group_operations target_fabric_wwn_group_ops = { +static const struct configfs_group_operations target_fabric_wwn_group_ops = { .make_group = target_fabric_make_wwn, .drop_item = target_fabric_drop_wwn, }; diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 6360b66c7445..f964a531e053 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -26,6 +26,8 @@ #include "target_core_ua.h" #include "target_core_xcopy.h" +#define PD_TEXT_ID_INFO_HDR_LEN 4 + static void spc_fill_alua_data(struct se_lun *lun, unsigned char *buf) { struct t10_alua_tg_pt_gp *tg_pt_gp; @@ -2000,6 +2002,18 @@ static const struct target_opcode_descriptor tcm_opcode_report_supp_opcodes = { .enabled = spc_rsoc_enabled, }; +static struct target_opcode_descriptor tcm_opcode_report_identifying_information = { + .support = SCSI_SUPPORT_FULL, + .serv_action_valid = 1, + .opcode = MAINTENANCE_IN, + .service_action = MI_REPORT_IDENTIFYING_INFORMATION, + .cdb_size = 12, + .usage_bits = {MAINTENANCE_IN, MI_REPORT_IDENTIFYING_INFORMATION, + 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, SCSI_CONTROL_MASK}, +}; + static bool tcm_is_set_tpg_enabled(const struct target_opcode_descriptor *descr, struct se_cmd *cmd) { @@ -2087,6 +2101,7 @@ static const struct target_opcode_descriptor *tcm_supported_opcodes[] = { &tcm_opcode_report_target_pgs, &tcm_opcode_report_supp_opcodes, &tcm_opcode_set_tpg, + &tcm_opcode_report_identifying_information, }; static int @@ -2304,6 +2319,72 @@ out: return ret; } +static sense_reason_t +spc_fill_pd_text_id_info(struct se_cmd *cmd, u8 *cdb) +{ + struct se_device *dev = cmd->se_dev; + unsigned char *buf; + unsigned char *rbuf; + u32 buf_len; + u16 data_len; + + buf_len = get_unaligned_be32(&cdb[6]); + if (buf_len < PD_TEXT_ID_INFO_HDR_LEN) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + + data_len = strlen(dev->t10_wwn.pd_text_id_info); + if (data_len > 0) + /* trailing null */ + data_len += 1; + + data_len = data_len + PD_TEXT_ID_INFO_HDR_LEN; + + if (data_len < buf_len) + buf_len = data_len; + + buf = kzalloc(buf_len, GFP_KERNEL); + if (!buf) { + pr_err("Unable to allocate response buffer for IDENTITY INFO\n"); + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + } + + scnprintf(&buf[PD_TEXT_ID_INFO_HDR_LEN], buf_len - PD_TEXT_ID_INFO_HDR_LEN, "%s", + dev->t10_wwn.pd_text_id_info); + + put_unaligned_be16(data_len, &buf[2]); + + rbuf = transport_kmap_data_sg(cmd); + if (!rbuf) { + pr_err("transport_kmap_data_sg() failed in %s\n", __func__); + kfree(buf); + return TCM_OUT_OF_RESOURCES; + } + + memcpy(rbuf, buf, buf_len); + transport_kunmap_data_sg(cmd); + kfree(buf); + + target_complete_cmd_with_length(cmd, SAM_STAT_GOOD, buf_len); + return TCM_NO_SENSE; +} + +static sense_reason_t +spc_emulate_report_id_info(struct se_cmd *cmd) +{ + u8 *cdb = cmd->t_task_cdb; + sense_reason_t rc; + + switch ((cdb[10] >> 1)) { + case 2: + rc = spc_fill_pd_text_id_info(cmd, cdb); + break; + default: + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + return rc; +} + sense_reason_t spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) { @@ -2443,6 +2524,11 @@ spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) MI_REPORT_SUPPORTED_OPERATION_CODES) cmd->execute_cmd = spc_emulate_report_supp_op_codes; + if ((cdb[1] & 0x1f) == + MI_REPORT_IDENTIFYING_INFORMATION) { + cmd->execute_cmd = + spc_emulate_report_id_info; + } *size = get_unaligned_be32(&cdb[6]); } else { /* |
