diff mbox series

[1/4] scsi: pm80xx: fix incorrect port value when registering a device

Message ID 20210823082338.67309-2-Ajish.Koshy@microchip.com
State Superseded
Headers show
Series [1/4] scsi: pm80xx: fix incorrect port value when registering a device | expand

Commit Message

Ajish Koshy Aug. 23, 2021, 8:23 a.m. UTC
Sometime we observe there is mismatch between portid & phyid
received during phyup event and device registration. Later this
will cause drive missing issue.

Signed-off-by: Ajish Koshy <Ajish.Koshy@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c  |  7 ++++++-
 drivers/scsi/pm8001/pm8001_init.c |  1 +
 drivers/scsi/pm8001/pm8001_sas.c  | 15 +++++++++++++++
 drivers/scsi/pm8001/pm8001_sas.h  |  2 ++
 drivers/scsi/pm8001/pm80xx_hwi.c  |  7 ++++++-
 5 files changed, 30 insertions(+), 2 deletions(-)

Comments

Jinpu Wang Aug. 30, 2021, 7:58 a.m. UTC | #1
Hi Ajish,
On Mon, Aug 23, 2021 at 9:28 AM Ajish Koshy <Ajish.Koshy@microchip.com> wrote:
>

> Sometime we observe there is mismatch between portid & phyid

> received during phyup event and device registration. Later this

> will cause drive missing issue.

Thanks for the patch.
Could you explain a bit more, what was the problem, and how you fix it
in the commit message?
>

> Signed-off-by: Ajish Koshy <Ajish.Koshy@microchip.com>

> Signed-off-by: Viswas G <Viswas.G@microchip.com>

> ---

>  drivers/scsi/pm8001/pm8001_hwi.c  |  7 ++++++-

>  drivers/scsi/pm8001/pm8001_init.c |  1 +

>  drivers/scsi/pm8001/pm8001_sas.c  | 15 +++++++++++++++

>  drivers/scsi/pm8001/pm8001_sas.h  |  2 ++

>  drivers/scsi/pm8001/pm80xx_hwi.c  |  7 ++++++-

>  5 files changed, 30 insertions(+), 2 deletions(-)

>

> diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c

> index 63690508313b..c9ecddd0d719 100644

> --- a/drivers/scsi/pm8001/pm8001_hwi.c

> +++ b/drivers/scsi/pm8001/pm8001_hwi.c

> @@ -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) |

> diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c

> index 47db7e0beae6..613455a3e686 100644

> --- a/drivers/scsi/pm8001/pm8001_init.c

> +++ b/drivers/scsi/pm8001/pm8001_init.c

> @@ -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,

>  };

>

>  /**

> diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c

> index 32e60f0c3b14..83e73009db5c 100644

> --- a/drivers/scsi/pm8001/pm8001_sas.c

> +++ b/drivers/scsi/pm8001/pm8001_sas.c

> @@ -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;

> +}

> diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h

> index 62d08b535a4b..1a016a421280 100644

> --- a/drivers/scsi/pm8001/pm8001_sas.h

> +++ b/drivers/scsi/pm8001/pm8001_sas.h

> @@ -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,

> diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c

> index 6ffe17b849ae..cec932f830b8 100644

> --- a/drivers/scsi/pm8001/pm80xx_hwi.c

> +++ b/drivers/scsi/pm8001/pm80xx_hwi.c

> @@ -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) |

> --

> 2.27.0

>
Ajish Koshy Sept. 1, 2021, 11:44 a.m. UTC | #2
Hi Jinpu,

Thanks for your review.

During "phy up" event, firmware gives the phy_id and port_id 
and driver is supposed to use the same during device handle 
registration. Earlier, driver was using port id value from libsas
during device handle registration and at times, it is different from
firmware assigned port id. This will lead to wrong device registration 
and eventually we won’t see those drives.

We will add these details in V2 patch set commit message.

Thanks,
Ajish
-----Original Message-----
From: Jinpu Wang <jinpu.wang@ionos.com> 

Sent: Monday, August 30, 2021 01:29 PM
To: Ajish Koshy - I30923 <Ajish.Koshy@microchip.com>
Cc: Linux SCSI Mailinglist <linux-scsi@vger.kernel.org>; Vasanthalakshmi Tharmarajan - I30664 <Vasanthalakshmi.Tharmarajan@microchip.com>; Viswas G - I30667 <Viswas.G@microchip.com>; Ruksar Devadi - I52327 <Ruksar.devadi@microchip.com>; Ashokkumar N - X53535 <Ashokkumar.N@microchip.com>; Jinpu Wang <jinpu.wang@cloud.ionos.com>
Subject: Re: [PATCH 1/4] scsi: pm80xx: fix incorrect port value when registering a device

[You don't often get email from jinpu.wang@ionos.com. Learn why this is important at http://aka.ms/LearnAboutSenderIdentification.]

EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe

Hi Ajish,
On Mon, Aug 23, 2021 at 9:28 AM Ajish Koshy <Ajish.Koshy@microchip.com> wrote:
>

> Sometime we observe there is mismatch between portid & phyid received 

> during phyup event and device registration. Later this will cause 

> drive missing issue.

Thanks for the patch.
Could you explain a bit more, what was the problem, and how you fix it in the commit message?
>

> Signed-off-by: Ajish Koshy <Ajish.Koshy@microchip.com>

> Signed-off-by: Viswas G <Viswas.G@microchip.com>

> ---

>  drivers/scsi/pm8001/pm8001_hwi.c  |  7 ++++++-  

> drivers/scsi/pm8001/pm8001_init.c |  1 +  

> drivers/scsi/pm8001/pm8001_sas.c  | 15 +++++++++++++++  

> drivers/scsi/pm8001/pm8001_sas.h  |  2 ++  

> drivers/scsi/pm8001/pm80xx_hwi.c  |  7 ++++++-

>  5 files changed, 30 insertions(+), 2 deletions(-)

>

> diff --git a/drivers/scsi/pm8001/pm8001_hwi.c 

> b/drivers/scsi/pm8001/pm8001_hwi.c

> index 63690508313b..c9ecddd0d719 100644

> --- a/drivers/scsi/pm8001/pm8001_hwi.c

> +++ b/drivers/scsi/pm8001/pm8001_hwi.c

> @@ -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) | diff --git 

> a/drivers/scsi/pm8001/pm8001_init.c 

> b/drivers/scsi/pm8001/pm8001_init.c

> index 47db7e0beae6..613455a3e686 100644

> --- a/drivers/scsi/pm8001/pm8001_init.c

> +++ b/drivers/scsi/pm8001/pm8001_init.c

> @@ -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,

>  };

>

>  /**

> diff --git a/drivers/scsi/pm8001/pm8001_sas.c 

> b/drivers/scsi/pm8001/pm8001_sas.c

> index 32e60f0c3b14..83e73009db5c 100644

> --- a/drivers/scsi/pm8001/pm8001_sas.c

> +++ b/drivers/scsi/pm8001/pm8001_sas.c

> @@ -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;

> +}

> diff --git a/drivers/scsi/pm8001/pm8001_sas.h 

> b/drivers/scsi/pm8001/pm8001_sas.h

> index 62d08b535a4b..1a016a421280 100644

> --- a/drivers/scsi/pm8001/pm8001_sas.h

> +++ b/drivers/scsi/pm8001/pm8001_sas.h

> @@ -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, diff --git 

> a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c

> index 6ffe17b849ae..cec932f830b8 100644

> --- a/drivers/scsi/pm8001/pm80xx_hwi.c

> +++ b/drivers/scsi/pm8001/pm80xx_hwi.c

> @@ -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) |

> --

> 2.27.0

>
diff mbox series

Patch

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 63690508313b..c9ecddd0d719 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -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) |
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 47db7e0beae6..613455a3e686 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -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,
 };
 
 /**
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 32e60f0c3b14..83e73009db5c 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -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;
+}
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 62d08b535a4b..1a016a421280 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -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,
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 6ffe17b849ae..cec932f830b8 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -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) |