]> git.baikalelectronics.ru Git - kernel.git/commitdiff
scsi: pm80xx: Fix incorrect port value when registering a device
authorAjish Koshy <Ajish.Koshy@microchip.com>
Mon, 6 Sep 2021 17:04:01 +0000 (22:34 +0530)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 15 Sep 2021 02:29:11 +0000 (22:29 -0400)
During phyup event, the firmware provides the phy_id and port_id and driver
is supposed to use these during device handle registration. Previously the
driver was using the port id value from libsas during device handle
registration. Since id can be different from the one assigned by firmware,
this can lead to wrong device registration and drives not showing up.

Use firmware assigned port id during device registration.

Link: https://lore.kernel.org/r/20210906170404.5682-2-Ajish.Koshy@microchip.com
Acked-by: Jack Wang <jinpu.wang@ionos.com>
Signed-off-by: Ajish Koshy <Ajish.Koshy@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/pm8001/pm8001_hwi.c
drivers/scsi/pm8001/pm8001_init.c
drivers/scsi/pm8001/pm8001_sas.c
drivers/scsi/pm8001/pm8001_sas.h
drivers/scsi/pm8001/pm80xx_hwi.c

index 63690508313b76d43df04fd8cff6c44539d226a5..c9ecddd0d719c94209e1445fd21f386ab8bfc7e3 100644 (file)
@@ -3358,6 +3358,8 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
        struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
        unsigned long flags;
        u8 deviceType = pPayload->sas_identify.dev_type;
+       phy->port = port;
+       port->port_id = port_id;
        port->port_state =  portstate;
        phy->phy_state = PHY_STATE_LINK_UP_SPC;
        pm8001_dbg(pm8001_ha, MSG,
@@ -3434,6 +3436,8 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
        unsigned long flags;
        pm8001_dbg(pm8001_ha, DEVIO, "HW_EVENT_SATA_PHY_UP port id = %d, phy id = %d\n",
                   port_id, phy_id);
+       phy->port = port;
+       port->port_id = port_id;
        port->port_state =  portstate;
        phy->phy_state = PHY_STATE_LINK_UP_SPC;
        port->port_attached = 1;
@@ -4460,6 +4464,7 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
        u16 ITNT = 2000;
        struct domain_device *dev = pm8001_dev->sas_device;
        struct domain_device *parent_dev = dev->parent;
+       struct pm8001_port *port = dev->port->lldd_port;
        circularQ = &pm8001_ha->inbnd_q_tbl[0];
 
        memset(&payload, 0, sizeof(payload));
@@ -4488,7 +4493,7 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
        linkrate = (pm8001_dev->sas_device->linkrate < dev->port->linkrate) ?
                        pm8001_dev->sas_device->linkrate : dev->port->linkrate;
        payload.phyid_portid =
-               cpu_to_le32(((pm8001_dev->sas_device->port->id) & 0x0F) |
+               cpu_to_le32(((port->port_id) & 0x0F) |
                ((phy_id & 0x0F) << 4));
        payload.dtype_dlr_retry = cpu_to_le32((retryFlag & 0x01) |
                ((linkrate & 0x0F) * 0x1000000) |
index 47db7e0beae6f6043f7bc4d7e703eb0f1bcbab37..613455a3e686d88b1ca54aedf121a284699e7fb4 100644 (file)
@@ -128,6 +128,7 @@ static struct sas_domain_function_template pm8001_transport_ops = {
        .lldd_I_T_nexus_reset   = pm8001_I_T_nexus_reset,
        .lldd_lu_reset          = pm8001_lu_reset,
        .lldd_query_task        = pm8001_query_task,
+       .lldd_port_formed       = pm8001_port_formed,
 };
 
 /**
index 32e60f0c3b1483bdeb2f6aba6015ef7506a25387..83e73009db5cd35c6053cf46210cad14a56042ab 100644 (file)
@@ -1355,3 +1355,18 @@ int pm8001_clear_task_set(struct domain_device *dev, u8 *lun)
        tmf_task.tmf = TMF_CLEAR_TASK_SET;
        return pm8001_issue_ssp_tmf(dev, lun, &tmf_task);
 }
+
+void pm8001_port_formed(struct asd_sas_phy *sas_phy)
+{
+       struct sas_ha_struct *sas_ha = sas_phy->ha;
+       struct pm8001_hba_info *pm8001_ha = sas_ha->lldd_ha;
+       struct pm8001_phy *phy = sas_phy->lldd_phy;
+       struct asd_sas_port *sas_port = sas_phy->port;
+       struct pm8001_port *port = phy->port;
+
+       if (!sas_port) {
+               pm8001_dbg(pm8001_ha, FAIL, "Received null port\n");
+               return;
+       }
+       sas_port->lldd_port = port;
+}
index 62d08b535a4b6c4191ede9332ff07d663aa609a1..1a016a421280fef2b31fc225384e67a4d21fcb4a 100644 (file)
@@ -230,6 +230,7 @@ struct pm8001_port {
        u8                      port_attached;
        u16                     wide_port_phymap;
        u8                      port_state;
+       u8                      port_id;
        struct list_head        list;
 };
 
@@ -651,6 +652,7 @@ int pm8001_lu_reset(struct domain_device *dev, u8 *lun);
 int pm8001_I_T_nexus_reset(struct domain_device *dev);
 int pm8001_I_T_nexus_event_handler(struct domain_device *dev);
 int pm8001_query_task(struct sas_task *task);
+void pm8001_port_formed(struct asd_sas_phy *sas_phy);
 void pm8001_open_reject_retry(
        struct pm8001_hba_info *pm8001_ha,
        struct sas_task *task_to_close,
index 6ffe17b849ae84d2a31795075216a2f54d0d18b7..cec932f830b8c1a99ebfee047675152673ecf9a7 100644 (file)
@@ -3299,6 +3299,8 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
        struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
        unsigned long flags;
        u8 deviceType = pPayload->sas_identify.dev_type;
+       phy->port = port;
+       port->port_id = port_id;
        port->port_state = portstate;
        port->wide_port_phymap |= (1U << phy_id);
        phy->phy_state = PHY_STATE_LINK_UP_SPCV;
@@ -3380,6 +3382,8 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
                   "port id %d, phy id %d link_rate %d portstate 0x%x\n",
                   port_id, phy_id, link_rate, portstate);
 
+       phy->port = port;
+       port->port_id = port_id;
        port->port_state = portstate;
        phy->phy_state = PHY_STATE_LINK_UP_SPCV;
        port->port_attached = 1;
@@ -4808,6 +4812,7 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
        u16 ITNT = 2000;
        struct domain_device *dev = pm8001_dev->sas_device;
        struct domain_device *parent_dev = dev->parent;
+       struct pm8001_port *port = dev->port->lldd_port;
        circularQ = &pm8001_ha->inbnd_q_tbl[0];
 
        memset(&payload, 0, sizeof(payload));
@@ -4840,7 +4845,7 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
                        pm8001_dev->sas_device->linkrate : dev->port->linkrate;
 
        payload.phyid_portid =
-               cpu_to_le32(((pm8001_dev->sas_device->port->id) & 0xFF) |
+               cpu_to_le32(((port->port_id) & 0xFF) |
                ((phy_id & 0xFF) << 8));
 
        payload.dtype_dlr_mcn_ir_retry = cpu_to_le32((retryFlag & 0x01) |