lkml.org 
[lkml]   [2022]   [Jun]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.18 504/879] scsi: hisi_sas: Fix rescan after deleting a disk
    Date
    From: John Garry <john.garry@huawei.com>

    [ Upstream commit e9dedc13bb11bc553754abecb322e5e41d1b4fef ]

    Removing an ATA device via sysfs means that the device may not be found
    through re-scanning:

    root@ubuntu:/home/john# lsscsi
    [0:0:0:0] disk SanDisk LT0200MO P404 /dev/sda
    [0:0:1:0] disk ATA HGST HUS724040AL A8B0 /dev/sdb
    [0:0:8:0] enclosu 12G SAS Expander RevB -
    root@ubuntu:/home/john# echo 1 > /sys/block/sdb/device/delete
    root@ubuntu:/home/john# echo "- - -" > /sys/class/scsi_host/host0/scan
    root@ubuntu:/home/john# lsscsi
    [0:0:0:0] disk SanDisk LT0200MO P404 /dev/sda
    [0:0:8:0] enclosu 12G SAS Expander RevB -
    root@ubuntu:/home/john#

    The problem is that the rescan of the device may conflict with the device
    in being re-initialized, as follows:

    - In the rescan we call hisi_sas_slave_alloc() in store_scan() ->
    sas_user_scan() -> [__]scsi_scan_target() -> scsi_probe_and_add_lunc()
    -> scsi_alloc_sdev() -> hisi_sas_slave_alloc() -> hisi_sas_init_device()
    In hisi_sas_init_device() we issue an IT nexus reset for ATA devices

    - That IT nexus causes the remote PHY to go down and this triggers a bcast
    event

    - In parallel libsas processes the bcast event, finds that the phy is down
    and marks the device as gone

    The hard reset issued in hisi_sas_init_device() is unncessary - as
    described in the code comment - so remove it. Also set dev status as
    HISI_SAS_DEV_NORMAL as the hisi_sas_init_device() call.

    Link: https://lore.kernel.org/r/1652354134-171343-4-git-send-email-john.garry@huawei.com
    Fixes: 36c6b7613ef1 ("scsi: hisi_sas: Initialise devices in .slave_alloc callback")
    Tested-by: Yihang Li <liyihang6@hisilicon.com>
    Reviewed-by: Xiang Chen <chenxiang66@hisilicon.com>
    Signed-off-by: John Garry <john.garry@huawei.com>
    Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/scsi/hisi_sas/hisi_sas_main.c | 47 ++++++++++-----------------
    1 file changed, 18 insertions(+), 29 deletions(-)

    diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
    index 4bda2f6cb352..86cbfab78dfe 100644
    --- a/drivers/scsi/hisi_sas/hisi_sas_main.c
    +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
    @@ -709,8 +709,6 @@ static int hisi_sas_init_device(struct domain_device *device)
    struct scsi_lun lun;
    int retry = HISI_SAS_DISK_RECOVER_CNT;
    struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
    - struct device *dev = hisi_hba->dev;
    - struct sas_phy *local_phy;

    switch (device->dev_type) {
    case SAS_END_DEVICE:
    @@ -729,30 +727,18 @@ static int hisi_sas_init_device(struct domain_device *device)
    case SAS_SATA_PM_PORT:
    case SAS_SATA_PENDING:
    /*
    - * send HARD RESET to clear previous affiliation of
    - * STP target port
    + * If an expander is swapped when a SATA disk is attached then
    + * we should issue a hard reset to clear previous affiliation
    + * of STP target port, see SPL (chapter 6.19.4).
    + *
    + * However we don't need to issue a hard reset here for these
    + * reasons:
    + * a. When probing the device, libsas/libata already issues a
    + * hard reset in sas_probe_sata() -> ata_sas_async_probe().
    + * Note that in hisi_sas_debug_I_T_nexus_reset() we take care
    + * to issue a hard reset by checking the dev status (== INIT).
    + * b. When resetting the controller, this is simply unnecessary.
    */
    - local_phy = sas_get_local_phy(device);
    - if (!scsi_is_sas_phy_local(local_phy) &&
    - !test_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags)) {
    - unsigned long deadline = ata_deadline(jiffies, 20000);
    - struct sata_device *sata_dev = &device->sata_dev;
    - struct ata_host *ata_host = sata_dev->ata_host;
    - struct ata_port_operations *ops = ata_host->ops;
    - struct ata_port *ap = sata_dev->ap;
    - struct ata_link *link;
    - unsigned int classes;
    -
    - ata_for_each_link(link, ap, EDGE)
    - rc = ops->hardreset(link, &classes,
    - deadline);
    - }
    - sas_put_local_phy(local_phy);
    - if (rc) {
    - dev_warn(dev, "SATA disk hardreset fail: %d\n", rc);
    - return rc;
    - }
    -
    while (retry-- > 0) {
    rc = hisi_sas_softreset_ata_disk(device);
    if (!rc)
    @@ -768,15 +754,19 @@ static int hisi_sas_init_device(struct domain_device *device)

    int hisi_sas_slave_alloc(struct scsi_device *sdev)
    {
    - struct domain_device *ddev;
    + struct domain_device *ddev = sdev_to_domain_dev(sdev);
    + struct hisi_sas_device *sas_dev = ddev->lldd_dev;
    int rc;

    rc = sas_slave_alloc(sdev);
    if (rc)
    return rc;
    - ddev = sdev_to_domain_dev(sdev);

    - return hisi_sas_init_device(ddev);
    + rc = hisi_sas_init_device(ddev);
    + if (rc)
    + return rc;
    + sas_dev->dev_status = HISI_SAS_DEV_NORMAL;
    + return 0;
    }
    EXPORT_SYMBOL_GPL(hisi_sas_slave_alloc);

    @@ -826,7 +816,6 @@ static int hisi_sas_dev_found(struct domain_device *device)
    dev_info(dev, "dev[%d:%x] found\n",
    sas_dev->device_id, sas_dev->dev_type);

    - sas_dev->dev_status = HISI_SAS_DEV_NORMAL;
    return 0;

    err_out:
    --
    2.35.1


    \
     
     \ /
      Last update: 2022-06-08 03:44    [W:2.632 / U:0.324 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site