Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi: Fix sas_user_scan() to handle wildcard and multi-channel scans

sas_user_scan() did not fully process wildcard channel scans
(SCAN_WILD_CARD) when a transport-specific user_scan() callback was
present. Only channel 0 would be scanned via user_scan(), while the
remaining channels were skipped, potentially missing devices.

user_scan() invokes updated sas_user_scan() for channel 0, and if
successful, iteratively scans remaining channels (1 to
shost->max_channel) via scsi_scan_host_selected(). This ensures complete
wildcard scanning without affecting transport-specific scanning behavior.

Signed-off-by: Ranjan Kumar <ranjan.kumar@broadcom.com>
Link: https://lore.kernel.org/r/20250624061649.17990-1-ranjan.kumar@broadcom.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Ranjan Kumar and committed by
Martin K. Petersen
37c4e72b 6e0f6aa4

+50 -14
+1 -1
drivers/scsi/scsi_scan.c
··· 1900 1900 1901 1901 return 0; 1902 1902 } 1903 - 1903 + EXPORT_SYMBOL(scsi_scan_host_selected); 1904 1904 static void scsi_sysfs_add_devices(struct Scsi_Host *shost) 1905 1905 { 1906 1906 struct scsi_device *sdev;
+49 -13
drivers/scsi/scsi_transport_sas.c
··· 40 40 #include <scsi/scsi_transport_sas.h> 41 41 42 42 #include "scsi_sas_internal.h" 43 + #include "scsi_priv.h" 44 + 43 45 struct sas_host_attrs { 44 46 struct list_head rphy_list; 45 47 struct mutex lock; ··· 1685 1683 } 1686 1684 EXPORT_SYMBOL(scsi_is_sas_rphy); 1687 1685 1686 + static void scan_channel_zero(struct Scsi_Host *shost, uint id, u64 lun) 1687 + { 1688 + struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1689 + struct sas_rphy *rphy; 1690 + 1691 + list_for_each_entry(rphy, &sas_host->rphy_list, list) { 1692 + if (rphy->identify.device_type != SAS_END_DEVICE || 1693 + rphy->scsi_target_id == -1) 1694 + continue; 1695 + 1696 + if (id == SCAN_WILD_CARD || id == rphy->scsi_target_id) { 1697 + scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id, 1698 + lun, SCSI_SCAN_MANUAL); 1699 + } 1700 + } 1701 + } 1688 1702 1689 1703 /* 1690 1704 * SCSI scan helper ··· 1710 1692 uint id, u64 lun) 1711 1693 { 1712 1694 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1713 - struct sas_rphy *rphy; 1695 + int res = 0; 1696 + int i; 1714 1697 1715 - mutex_lock(&sas_host->lock); 1716 - list_for_each_entry(rphy, &sas_host->rphy_list, list) { 1717 - if (rphy->identify.device_type != SAS_END_DEVICE || 1718 - rphy->scsi_target_id == -1) 1719 - continue; 1698 + switch (channel) { 1699 + case 0: 1700 + mutex_lock(&sas_host->lock); 1701 + scan_channel_zero(shost, id, lun); 1702 + mutex_unlock(&sas_host->lock); 1703 + break; 1720 1704 1721 - if ((channel == SCAN_WILD_CARD || channel == 0) && 1722 - (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) { 1723 - scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id, 1724 - lun, SCSI_SCAN_MANUAL); 1705 + case SCAN_WILD_CARD: 1706 + mutex_lock(&sas_host->lock); 1707 + scan_channel_zero(shost, id, lun); 1708 + mutex_unlock(&sas_host->lock); 1709 + 1710 + for (i = 1; i <= shost->max_channel; i++) { 1711 + res = scsi_scan_host_selected(shost, i, id, lun, 1712 + SCSI_SCAN_MANUAL); 1713 + if (res) 1714 + goto exit_scan; 1725 1715 } 1726 - } 1727 - mutex_unlock(&sas_host->lock); 1716 + break; 1728 1717 1729 - return 0; 1718 + default: 1719 + if (channel < shost->max_channel) { 1720 + res = scsi_scan_host_selected(shost, channel, id, lun, 1721 + SCSI_SCAN_MANUAL); 1722 + } else { 1723 + res = -EINVAL; 1724 + } 1725 + break; 1726 + } 1727 + 1728 + exit_scan: 1729 + return res; 1730 1730 } 1731 1731 1732 1732