Message ID | 20220729131627.15019-7-sreekanth.reddy@broadcom.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | mpi3mr: Added Support for SAS Transport | expand |
> On Jul 29, 2022, at 6:16 AM, Sreekanth Reddy <sreekanth.reddy@broadcom.com> wrote: > > Added below helper functions, > - Get the device's sas address by reading > correspond device's Device page0, > - Get the expander object from expander list based > on expander's handle, > - Get the target device object from target device list > based on device's sas address, > - Get the expander device object from expander list > based on expanders's sas address, > - Get hba port object from hba port table list > based on port's port id > > Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com> > --- > drivers/scsi/mpi3mr/mpi3mr.h | 14 ++ > drivers/scsi/mpi3mr/mpi3mr_os.c | 3 + > drivers/scsi/mpi3mr/mpi3mr_transport.c | 280 +++++++++++++++++++++++++ > 3 files changed, 297 insertions(+) > > diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h > index 006bc5d..742caf5 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr.h > +++ b/drivers/scsi/mpi3mr/mpi3mr.h > @@ -570,10 +570,12 @@ struct mpi3mr_enclosure_node { > * > * @sas_address: World wide unique SAS address > * @dev_info: Device information bits > + * @hba_port: HBA port entry > */ > struct tgt_dev_sas_sata { > u64 sas_address; > u16 dev_info; > + struct mpi3mr_hba_port *hba_port; > }; > > /** > @@ -984,6 +986,10 @@ struct scmd_priv { > * @cfg_page: Default memory for configuration pages > * @cfg_page_dma: Configuration page DMA address > * @cfg_page_sz: Default configuration page memory size > + * @sas_hba: SAS node for the controller > + * @sas_expander_list: SAS node list of expanders > + * @sas_node_lock: Lock to protect SAS node list > + * @hba_port_table_list: List of HBA Ports > * @enclosure_list: List of Enclosure objects > */ > struct mpi3mr_ioc { > @@ -1162,6 +1168,10 @@ struct mpi3mr_ioc { > dma_addr_t cfg_page_dma; > u16 cfg_page_sz; > > + struct mpi3mr_sas_node sas_hba; > + struct list_head sas_expander_list; > + spinlock_t sas_node_lock; > + struct list_head hba_port_table_list; > struct list_head enclosure_list; > }; > > @@ -1317,4 +1327,8 @@ int mpi3mr_cfg_set_sas_io_unit_pg1(struct mpi3mr_ioc *mrioc, > struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1, u16 pg_sz); > int mpi3mr_cfg_get_driver_pg1(struct mpi3mr_ioc *mrioc, > struct mpi3_driver_page1 *driver_pg1, u16 pg_sz); > + > +u8 mpi3mr_is_expander_device(u16 device_info); > +struct mpi3mr_hba_port *mpi3mr_get_hba_port_by_id(struct mpi3mr_ioc *mrioc, > + u8 port_id); > #endif /*MPI3MR_H_INCLUDED*/ > diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c > index ca718cb..b75ce73 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_os.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c > @@ -4692,11 +4692,14 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) > spin_lock_init(&mrioc->tgtdev_lock); > spin_lock_init(&mrioc->watchdog_lock); > spin_lock_init(&mrioc->chain_buf_lock); > + spin_lock_init(&mrioc->sas_node_lock); > > INIT_LIST_HEAD(&mrioc->fwevt_list); > INIT_LIST_HEAD(&mrioc->tgtdev_list); > INIT_LIST_HEAD(&mrioc->delayed_rmhs_list); > INIT_LIST_HEAD(&mrioc->delayed_evtack_cmds_list); > + INIT_LIST_HEAD(&mrioc->sas_expander_list); > + INIT_LIST_HEAD(&mrioc->hba_port_table_list); > INIT_LIST_HEAD(&mrioc->enclosure_list); > > mutex_init(&mrioc->reset_mutex); > diff --git a/drivers/scsi/mpi3mr/mpi3mr_transport.c b/drivers/scsi/mpi3mr/mpi3mr_transport.c > index 989bf63..fea3aae 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_transport.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_transport.c > @@ -9,6 +9,237 @@ > > #include "mpi3mr.h" > > +/** > + * __mpi3mr_expander_find_by_handle - expander search by handle > + * @mrioc: Adapter instance reference > + * @handle: Firmware device handle of the expander > + * > + * Context: The caller should acquire sas_node_lock > + * > + * This searches for expander device based on handle, then > + * returns the sas_node object. > + * > + * Return: Expander sas_node object reference or NULL > + */ > +static struct mpi3mr_sas_node *__mpi3mr_expander_find_by_handle(struct mpi3mr_ioc > + *mrioc, u16 handle) > +{ > + struct mpi3mr_sas_node *sas_expander, *r; > + > + r = NULL; > + list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) { > + if (sas_expander->handle != handle) > + continue; > + r = sas_expander; > + goto out; > + } > + out: > + return r; > +} > + > +/** > + * mpi3mr_is_expander_device - if device is an expander > + * @device_info: Bitfield providing information about the device > + * > + * Return: 1 if the device is expander device, else 0. > + */ > +u8 mpi3mr_is_expander_device(u16 device_info) > +{ > + if ((device_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) == > + MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER) > + return 1; > + else > + return 0; > +} > + > +/** > + * mpi3mr_get_sas_address - retrieve sas_address for handle > + * @mrioc: Adapter instance reference > + * @handle: Firmware device handle > + * @sas_address: Address to hold sas address > + * > + * This function issues device page0 read for a given device > + * handle and gets the SAS address and return it back > + * > + * Return: 0 for success, non-zero for failure > + */ > +static int mpi3mr_get_sas_address(struct mpi3mr_ioc *mrioc, u16 handle, > + u64 *sas_address) > +{ > + struct mpi3_device_page0 dev_pg0; > + u16 ioc_status; > + struct mpi3_device0_sas_sata_format *sasinf; > + > + *sas_address = 0; > + > + if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0, > + sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE, > + handle))) { > + ioc_err(mrioc, "%s: device page0 read failed\n", __func__); > + return -ENXIO; > + } > + > + if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { > + ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n", > + handle, ioc_status, __FILE__, __LINE__, __func__); > + return -ENXIO; > + } > + > + if (le16_to_cpu(dev_pg0.flags) & > + MPI3_DEVICE0_FLAGS_CONTROLLER_DEV_HANDLE) > + *sas_address = mrioc->sas_hba.sas_address; > + else if (dev_pg0.device_form == MPI3_DEVICE_DEVFORM_SAS_SATA) { > + sasinf = &dev_pg0.device_specific.sas_sata_format; > + *sas_address = le64_to_cpu(sasinf->sas_address); > + } else { > + ioc_err(mrioc, "%s: device_form(%d) is not SAS_SATA\n", > + __func__, dev_pg0.device_form); > + return -ENXIO; > + } > + return 0; > +} > + > +/** > + * __mpi3mr_get_tgtdev_by_addr - target device search > + * @mrioc: Adapter instance reference > + * @sas_address: SAS address of the device > + * @hba_port: HBA port entry > + * > + * This searches for target device from sas address and hba port > + * pointer then return mpi3mr_tgt_dev object. > + * > + * Return: Valid tget_dev or NULL > + */ > +static struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_addr(struct mpi3mr_ioc *mrioc, > + u64 sas_address, struct mpi3mr_hba_port *hba_port) > +{ > + struct mpi3mr_tgt_dev *tgtdev; > + > + assert_spin_locked(&mrioc->tgtdev_lock); > + > + list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list) > + if ((tgtdev->dev_type == MPI3_DEVICE_DEVFORM_SAS_SATA) && > + (tgtdev->dev_spec.sas_sata_inf.sas_address == sas_address) > + && (tgtdev->dev_spec.sas_sata_inf.hba_port == hba_port)) > + goto found_device; > + return NULL; > +found_device: > + mpi3mr_tgtdev_get(tgtdev); > + return tgtdev; > +} > + > +/** > + * mpi3mr_get_tgtdev_by_addr - target device search > + * @mrioc: Adapter instance reference > + * @sas_address: SAS address of the device > + * @hba_port: HBA port entry > + * > + * This searches for target device from sas address and hba port > + * pointer then return mpi3mr_tgt_dev object. > + * > + * Context: This function will acquire tgtdev_lock and will > + * release before returning the mpi3mr_tgt_dev object. > + * > + * Return: Valid tget_dev or NULL > + */ > +static struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_by_addr(struct mpi3mr_ioc *mrioc, > + u64 sas_address, struct mpi3mr_hba_port *hba_port) > +{ > + struct mpi3mr_tgt_dev *tgtdev = NULL; > + unsigned long flags; > + > + if (!hba_port) > + goto out; > + > + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); > + tgtdev = __mpi3mr_get_tgtdev_by_addr(mrioc, sas_address, hba_port); > + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); > + > +out: > + return tgtdev; > +} > + > +/** > + * mpi3mr_expander_find_by_sas_address - sas expander search > + * @mrioc: Adapter instance reference > + * @sas_address: SAS address of expander > + * @hba_port: HBA port entry > + * > + * Return: A valid SAS expander node or NULL. > + * > + */ > +static struct mpi3mr_sas_node *mpi3mr_expander_find_by_sas_address( > + struct mpi3mr_ioc *mrioc, u64 sas_address, > + struct mpi3mr_hba_port *hba_port) > +{ > + struct mpi3mr_sas_node *sas_expander, *r = NULL; > + > + if (!hba_port) > + goto out; > + > + list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) { > + if ((sas_expander->sas_address != sas_address) || > + (sas_expander->hba_port != hba_port)) > + continue; > + r = sas_expander; > + goto out; > + } > +out: > + return r; > +} > + > +/** > + * __mpi3mr_sas_node_find_by_sas_address - sas node search > + * @mrioc: Adapter instance reference > + * @sas_address: SAS address of expander or sas host > + * @hba_port: HBA port entry > + * Context: Caller should acquire mrioc->sas_node_lock. > + * > + * If the SAS address indicates the device is direct attached to > + * the controller (controller's SAS address) then the SAS node > + * associated with the controller is returned back else the SAS > + * address and hba port are used to identify the exact expander > + * and the associated sas_node object is returned. If there is > + * no match NULL is returned. > + * > + * Return: A valid SAS node or NULL. > + * > + */ > +static struct mpi3mr_sas_node *__mpi3mr_sas_node_find_by_sas_address( > + struct mpi3mr_ioc *mrioc, u64 sas_address, > + struct mpi3mr_hba_port *hba_port) > +{ > + Remove new line here > + if (mrioc->sas_hba.sas_address == sas_address) > + return &mrioc->sas_hba; > + return mpi3mr_expander_find_by_sas_address(mrioc, sas_address, > + hba_port); > +} > + > +/** > + * mpi3mr_parent_present - Is parent present for a phy > + * @mrioc: Adapter instance reference > + * @phy: SAS transport layer phy object > + * > + * Return: 0 if parent is present else non-zero > + */ > +static int mpi3mr_parent_present(struct mpi3mr_ioc *mrioc, struct sas_phy *phy) > +{ > + remove new line > + unsigned long flags; > + struct mpi3mr_hba_port *hba_port = phy->hostdata; > + > + spin_lock_irqsave(&mrioc->sas_node_lock, flags); > + if (__mpi3mr_sas_node_find_by_sas_address(mrioc, > + phy->identify.sas_address, > + hba_port) == NULL) { > + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); > + return -1; > + } > + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); > + return 0; > +} > + > /** > * mpi3mr_convert_phy_link_rate - > * @link_rate: link rate as defined in the MPI header > @@ -428,3 +659,52 @@ static int mpi3mr_add_expander_phy(struct mpi3mr_ioc *mrioc, > mr_sas_phy->phy = phy; > return 0; > } > + > +/** > + * mpi3mr_alloc_hba_port - alloc hba port object > + * @mrioc: Adapter instance reference > + * @port_id: Port number > + * > + * Alloc memory for hba port object. > + */ > +static struct mpi3mr_hba_port * > +mpi3mr_alloc_hba_port(struct mpi3mr_ioc *mrioc, u16 port_id) > +{ > + struct mpi3mr_hba_port *hba_port; > + > + hba_port = kzalloc(sizeof(struct mpi3mr_hba_port), > + GFP_KERNEL); > + if (!hba_port) > + return NULL; > + hba_port->port_id = port_id; > + ioc_info(mrioc, "hba_port entry: %p, port: %d is added to hba_port list\n", > + hba_port, hba_port->port_id); > + list_add_tail(&hba_port->list, &mrioc->hba_port_table_list); > + return hba_port; > +} > + > +/** > + * mpi3mr_get_hba_port_by_id - find hba port by id > + * @mrioc: Adapter instance reference > + * @port_id - Port ID to search > + * > + * Return: mpi3mr_hba_port reference for the matched port > + */ > + > +struct mpi3mr_hba_port *mpi3mr_get_hba_port_by_id(struct mpi3mr_ioc *mrioc, > + u8 port_id) > +{ > + Ditto remove newline > + struct mpi3mr_hba_port *port, *port_next; > + > + list_for_each_entry_safe(port, port_next, > + &mrioc->hba_port_table_list, list) { > + if (port->port_id != port_id) > + continue; > + if (port->flags & MPI3MR_HBA_PORT_FLAG_DIRTY) > + continue; > + return port; > + } > + > + return NULL; > +} > -- > 2.27.0 > -- Himanshu Madhani Oracle Linux Engineering
On Sat, Jul 30, 2022 at 1:41 AM Himanshu Madhani <himanshu.madhani@oracle.com> wrote: > > > > > On Jul 29, 2022, at 6:16 AM, Sreekanth Reddy <sreekanth.reddy@broadcom.com> wrote: > > > > Added below helper functions, > > - Get the device's sas address by reading > > correspond device's Device page0, > > - Get the expander object from expander list based > > on expander's handle, > > - Get the target device object from target device list > > based on device's sas address, > > - Get the expander device object from expander list > > based on expanders's sas address, > > - Get hba port object from hba port table list > > based on port's port id > > > > Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com> > > --- > > drivers/scsi/mpi3mr/mpi3mr.h | 14 ++ > > drivers/scsi/mpi3mr/mpi3mr_os.c | 3 + > > drivers/scsi/mpi3mr/mpi3mr_transport.c | 280 +++++++++++++++++++++++++ > > 3 files changed, 297 insertions(+) > > > > diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h > > index 006bc5d..742caf5 100644 > > --- a/drivers/scsi/mpi3mr/mpi3mr.h > > +++ b/drivers/scsi/mpi3mr/mpi3mr.h > > @@ -570,10 +570,12 @@ struct mpi3mr_enclosure_node { > > * > > * @sas_address: World wide unique SAS address > > * @dev_info: Device information bits > > + * @hba_port: HBA port entry > > */ > > struct tgt_dev_sas_sata { > > u64 sas_address; > > u16 dev_info; > > + struct mpi3mr_hba_port *hba_port; > > }; > > > > /** > > @@ -984,6 +986,10 @@ struct scmd_priv { > > * @cfg_page: Default memory for configuration pages > > * @cfg_page_dma: Configuration page DMA address > > * @cfg_page_sz: Default configuration page memory size > > + * @sas_hba: SAS node for the controller > > + * @sas_expander_list: SAS node list of expanders > > + * @sas_node_lock: Lock to protect SAS node list > > + * @hba_port_table_list: List of HBA Ports > > * @enclosure_list: List of Enclosure objects > > */ > > struct mpi3mr_ioc { > > @@ -1162,6 +1168,10 @@ struct mpi3mr_ioc { > > dma_addr_t cfg_page_dma; > > u16 cfg_page_sz; > > > > + struct mpi3mr_sas_node sas_hba; > > + struct list_head sas_expander_list; > > + spinlock_t sas_node_lock; > > + struct list_head hba_port_table_list; > > struct list_head enclosure_list; > > }; > > > > @@ -1317,4 +1327,8 @@ int mpi3mr_cfg_set_sas_io_unit_pg1(struct mpi3mr_ioc *mrioc, > > struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1, u16 pg_sz); > > int mpi3mr_cfg_get_driver_pg1(struct mpi3mr_ioc *mrioc, > > struct mpi3_driver_page1 *driver_pg1, u16 pg_sz); > > + > > +u8 mpi3mr_is_expander_device(u16 device_info); > > +struct mpi3mr_hba_port *mpi3mr_get_hba_port_by_id(struct mpi3mr_ioc *mrioc, > > + u8 port_id); > > #endif /*MPI3MR_H_INCLUDED*/ > > diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c > > index ca718cb..b75ce73 100644 > > --- a/drivers/scsi/mpi3mr/mpi3mr_os.c > > +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c > > @@ -4692,11 +4692,14 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) > > spin_lock_init(&mrioc->tgtdev_lock); > > spin_lock_init(&mrioc->watchdog_lock); > > spin_lock_init(&mrioc->chain_buf_lock); > > + spin_lock_init(&mrioc->sas_node_lock); > > > > INIT_LIST_HEAD(&mrioc->fwevt_list); > > INIT_LIST_HEAD(&mrioc->tgtdev_list); > > INIT_LIST_HEAD(&mrioc->delayed_rmhs_list); > > INIT_LIST_HEAD(&mrioc->delayed_evtack_cmds_list); > > + INIT_LIST_HEAD(&mrioc->sas_expander_list); > > + INIT_LIST_HEAD(&mrioc->hba_port_table_list); > > INIT_LIST_HEAD(&mrioc->enclosure_list); > > > > mutex_init(&mrioc->reset_mutex); > > diff --git a/drivers/scsi/mpi3mr/mpi3mr_transport.c b/drivers/scsi/mpi3mr/mpi3mr_transport.c > > index 989bf63..fea3aae 100644 > > --- a/drivers/scsi/mpi3mr/mpi3mr_transport.c > > +++ b/drivers/scsi/mpi3mr/mpi3mr_transport.c > > @@ -9,6 +9,237 @@ > > > > #include "mpi3mr.h" > > > > +/** > > + * __mpi3mr_expander_find_by_handle - expander search by handle > > + * @mrioc: Adapter instance reference > > + * @handle: Firmware device handle of the expander > > + * > > + * Context: The caller should acquire sas_node_lock > > + * > > + * This searches for expander device based on handle, then > > + * returns the sas_node object. > > + * > > + * Return: Expander sas_node object reference or NULL > > + */ > > +static struct mpi3mr_sas_node *__mpi3mr_expander_find_by_handle(struct mpi3mr_ioc > > + *mrioc, u16 handle) > > +{ > > + struct mpi3mr_sas_node *sas_expander, *r; > > + > > + r = NULL; > > + list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) { > > + if (sas_expander->handle != handle) > > + continue; > > + r = sas_expander; > > + goto out; > > + } > > + out: > > + return r; > > +} > > + > > +/** > > + * mpi3mr_is_expander_device - if device is an expander > > + * @device_info: Bitfield providing information about the device > > + * > > + * Return: 1 if the device is expander device, else 0. > > + */ > > +u8 mpi3mr_is_expander_device(u16 device_info) > > +{ > > + if ((device_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) == > > + MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER) > > + return 1; > > + else > > + return 0; > > +} > > + > > +/** > > + * mpi3mr_get_sas_address - retrieve sas_address for handle > > + * @mrioc: Adapter instance reference > > + * @handle: Firmware device handle > > + * @sas_address: Address to hold sas address > > + * > > + * This function issues device page0 read for a given device > > + * handle and gets the SAS address and return it back > > + * > > + * Return: 0 for success, non-zero for failure > > + */ > > +static int mpi3mr_get_sas_address(struct mpi3mr_ioc *mrioc, u16 handle, > > + u64 *sas_address) > > +{ > > + struct mpi3_device_page0 dev_pg0; > > + u16 ioc_status; > > + struct mpi3_device0_sas_sata_format *sasinf; > > + > > + *sas_address = 0; > > + > > + if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0, > > + sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE, > > + handle))) { > > + ioc_err(mrioc, "%s: device page0 read failed\n", __func__); > > + return -ENXIO; > > + } > > + > > + if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { > > + ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n", > > + handle, ioc_status, __FILE__, __LINE__, __func__); > > + return -ENXIO; > > + } > > + > > + if (le16_to_cpu(dev_pg0.flags) & > > + MPI3_DEVICE0_FLAGS_CONTROLLER_DEV_HANDLE) > > + *sas_address = mrioc->sas_hba.sas_address; > > + else if (dev_pg0.device_form == MPI3_DEVICE_DEVFORM_SAS_SATA) { > > + sasinf = &dev_pg0.device_specific.sas_sata_format; > > + *sas_address = le64_to_cpu(sasinf->sas_address); > > + } else { > > + ioc_err(mrioc, "%s: device_form(%d) is not SAS_SATA\n", > > + __func__, dev_pg0.device_form); > > + return -ENXIO; > > + } > > + return 0; > > +} > > + > > +/** > > + * __mpi3mr_get_tgtdev_by_addr - target device search > > + * @mrioc: Adapter instance reference > > + * @sas_address: SAS address of the device > > + * @hba_port: HBA port entry > > + * > > + * This searches for target device from sas address and hba port > > + * pointer then return mpi3mr_tgt_dev object. > > + * > > + * Return: Valid tget_dev or NULL > > + */ > > +static struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_addr(struct mpi3mr_ioc *mrioc, > > + u64 sas_address, struct mpi3mr_hba_port *hba_port) > > +{ > > + struct mpi3mr_tgt_dev *tgtdev; > > + > > + assert_spin_locked(&mrioc->tgtdev_lock); > > + > > + list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list) > > + if ((tgtdev->dev_type == MPI3_DEVICE_DEVFORM_SAS_SATA) && > > + (tgtdev->dev_spec.sas_sata_inf.sas_address == sas_address) > > + && (tgtdev->dev_spec.sas_sata_inf.hba_port == hba_port)) > > + goto found_device; > > + return NULL; > > +found_device: > > + mpi3mr_tgtdev_get(tgtdev); > > + return tgtdev; > > +} > > + > > +/** > > + * mpi3mr_get_tgtdev_by_addr - target device search > > + * @mrioc: Adapter instance reference > > + * @sas_address: SAS address of the device > > + * @hba_port: HBA port entry > > + * > > + * This searches for target device from sas address and hba port > > + * pointer then return mpi3mr_tgt_dev object. > > + * > > + * Context: This function will acquire tgtdev_lock and will > > + * release before returning the mpi3mr_tgt_dev object. > > + * > > + * Return: Valid tget_dev or NULL > > + */ > > +static struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_by_addr(struct mpi3mr_ioc *mrioc, > > + u64 sas_address, struct mpi3mr_hba_port *hba_port) > > +{ > > + struct mpi3mr_tgt_dev *tgtdev = NULL; > > + unsigned long flags; > > + > > + if (!hba_port) > > + goto out; > > + > > + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); > > + tgtdev = __mpi3mr_get_tgtdev_by_addr(mrioc, sas_address, hba_port); > > + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); > > + > > +out: > > + return tgtdev; > > +} > > + > > +/** > > + * mpi3mr_expander_find_by_sas_address - sas expander search > > + * @mrioc: Adapter instance reference > > + * @sas_address: SAS address of expander > > + * @hba_port: HBA port entry > > + * > > + * Return: A valid SAS expander node or NULL. > > + * > > + */ > > +static struct mpi3mr_sas_node *mpi3mr_expander_find_by_sas_address( > > + struct mpi3mr_ioc *mrioc, u64 sas_address, > > + struct mpi3mr_hba_port *hba_port) > > +{ > > + struct mpi3mr_sas_node *sas_expander, *r = NULL; > > + > > + if (!hba_port) > > + goto out; > > + > > + list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) { > > + if ((sas_expander->sas_address != sas_address) || > > + (sas_expander->hba_port != hba_port)) > > + continue; > > + r = sas_expander; > > + goto out; > > + } > > +out: > > + return r; > > +} > > + > > +/** > > + * __mpi3mr_sas_node_find_by_sas_address - sas node search > > + * @mrioc: Adapter instance reference > > + * @sas_address: SAS address of expander or sas host > > + * @hba_port: HBA port entry > > + * Context: Caller should acquire mrioc->sas_node_lock. > > + * > > + * If the SAS address indicates the device is direct attached to > > + * the controller (controller's SAS address) then the SAS node > > + * associated with the controller is returned back else the SAS > > + * address and hba port are used to identify the exact expander > > + * and the associated sas_node object is returned. If there is > > + * no match NULL is returned. > > + * > > + * Return: A valid SAS node or NULL. > > + * > > + */ > > +static struct mpi3mr_sas_node *__mpi3mr_sas_node_find_by_sas_address( > > + struct mpi3mr_ioc *mrioc, u64 sas_address, > > + struct mpi3mr_hba_port *hba_port) > > +{ > > + > Remove new line here > > + if (mrioc->sas_hba.sas_address == sas_address) > > + return &mrioc->sas_hba; > > + return mpi3mr_expander_find_by_sas_address(mrioc, sas_address, > > + hba_port); > > +} > > + > > +/** > > + * mpi3mr_parent_present - Is parent present for a phy > > + * @mrioc: Adapter instance reference > > + * @phy: SAS transport layer phy object > > + * > > + * Return: 0 if parent is present else non-zero > > + */ > > +static int mpi3mr_parent_present(struct mpi3mr_ioc *mrioc, struct sas_phy *phy) > > +{ > > + > remove new line Agree. Will remove it next version patch set. > > + unsigned long flags; > > + struct mpi3mr_hba_port *hba_port = phy->hostdata; > > + > > + spin_lock_irqsave(&mrioc->sas_node_lock, flags); > > + if (__mpi3mr_sas_node_find_by_sas_address(mrioc, > > + phy->identify.sas_address, > > + hba_port) == NULL) { > > + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); > > + return -1; > > + } > > + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); > > + return 0; > > +} > > + > > /** > > * mpi3mr_convert_phy_link_rate - > > * @link_rate: link rate as defined in the MPI header > > @@ -428,3 +659,52 @@ static int mpi3mr_add_expander_phy(struct mpi3mr_ioc *mrioc, > > mr_sas_phy->phy = phy; > > return 0; > > } > > + > > +/** > > + * mpi3mr_alloc_hba_port - alloc hba port object > > + * @mrioc: Adapter instance reference > > + * @port_id: Port number > > + * > > + * Alloc memory for hba port object. > > + */ > > +static struct mpi3mr_hba_port * > > +mpi3mr_alloc_hba_port(struct mpi3mr_ioc *mrioc, u16 port_id) > > +{ > > + struct mpi3mr_hba_port *hba_port; > > + > > + hba_port = kzalloc(sizeof(struct mpi3mr_hba_port), > > + GFP_KERNEL); > > + if (!hba_port) > > + return NULL; > > + hba_port->port_id = port_id; > > + ioc_info(mrioc, "hba_port entry: %p, port: %d is added to hba_port list\n", > > + hba_port, hba_port->port_id); > > + list_add_tail(&hba_port->list, &mrioc->hba_port_table_list); > > + return hba_port; > > +} > > + > > +/** > > + * mpi3mr_get_hba_port_by_id - find hba port by id > > + * @mrioc: Adapter instance reference > > + * @port_id - Port ID to search > > + * > > + * Return: mpi3mr_hba_port reference for the matched port > > + */ > > + > > +struct mpi3mr_hba_port *mpi3mr_get_hba_port_by_id(struct mpi3mr_ioc *mrioc, > > + u8 port_id) > > +{ > > + > Ditto remove newline Agree. Will remove it next version patch set. > > + struct mpi3mr_hba_port *port, *port_next; > > + > > + list_for_each_entry_safe(port, port_next, > > + &mrioc->hba_port_table_list, list) { > > + if (port->port_id != port_id) > > + continue; > > + if (port->flags & MPI3MR_HBA_PORT_FLAG_DIRTY) > > + continue; > > + return port; > > + } > > + > > + return NULL; > > +} > > -- > > 2.27.0 > > > > -- > Himanshu Madhani Oracle Linux Engineering >
diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 006bc5d..742caf5 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -570,10 +570,12 @@ struct mpi3mr_enclosure_node { * * @sas_address: World wide unique SAS address * @dev_info: Device information bits + * @hba_port: HBA port entry */ struct tgt_dev_sas_sata { u64 sas_address; u16 dev_info; + struct mpi3mr_hba_port *hba_port; }; /** @@ -984,6 +986,10 @@ struct scmd_priv { * @cfg_page: Default memory for configuration pages * @cfg_page_dma: Configuration page DMA address * @cfg_page_sz: Default configuration page memory size + * @sas_hba: SAS node for the controller + * @sas_expander_list: SAS node list of expanders + * @sas_node_lock: Lock to protect SAS node list + * @hba_port_table_list: List of HBA Ports * @enclosure_list: List of Enclosure objects */ struct mpi3mr_ioc { @@ -1162,6 +1168,10 @@ struct mpi3mr_ioc { dma_addr_t cfg_page_dma; u16 cfg_page_sz; + struct mpi3mr_sas_node sas_hba; + struct list_head sas_expander_list; + spinlock_t sas_node_lock; + struct list_head hba_port_table_list; struct list_head enclosure_list; }; @@ -1317,4 +1327,8 @@ int mpi3mr_cfg_set_sas_io_unit_pg1(struct mpi3mr_ioc *mrioc, struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1, u16 pg_sz); int mpi3mr_cfg_get_driver_pg1(struct mpi3mr_ioc *mrioc, struct mpi3_driver_page1 *driver_pg1, u16 pg_sz); + +u8 mpi3mr_is_expander_device(u16 device_info); +struct mpi3mr_hba_port *mpi3mr_get_hba_port_by_id(struct mpi3mr_ioc *mrioc, + u8 port_id); #endif /*MPI3MR_H_INCLUDED*/ diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index ca718cb..b75ce73 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -4692,11 +4692,14 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) spin_lock_init(&mrioc->tgtdev_lock); spin_lock_init(&mrioc->watchdog_lock); spin_lock_init(&mrioc->chain_buf_lock); + spin_lock_init(&mrioc->sas_node_lock); INIT_LIST_HEAD(&mrioc->fwevt_list); INIT_LIST_HEAD(&mrioc->tgtdev_list); INIT_LIST_HEAD(&mrioc->delayed_rmhs_list); INIT_LIST_HEAD(&mrioc->delayed_evtack_cmds_list); + INIT_LIST_HEAD(&mrioc->sas_expander_list); + INIT_LIST_HEAD(&mrioc->hba_port_table_list); INIT_LIST_HEAD(&mrioc->enclosure_list); mutex_init(&mrioc->reset_mutex); diff --git a/drivers/scsi/mpi3mr/mpi3mr_transport.c b/drivers/scsi/mpi3mr/mpi3mr_transport.c index 989bf63..fea3aae 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_transport.c +++ b/drivers/scsi/mpi3mr/mpi3mr_transport.c @@ -9,6 +9,237 @@ #include "mpi3mr.h" +/** + * __mpi3mr_expander_find_by_handle - expander search by handle + * @mrioc: Adapter instance reference + * @handle: Firmware device handle of the expander + * + * Context: The caller should acquire sas_node_lock + * + * This searches for expander device based on handle, then + * returns the sas_node object. + * + * Return: Expander sas_node object reference or NULL + */ +static struct mpi3mr_sas_node *__mpi3mr_expander_find_by_handle(struct mpi3mr_ioc + *mrioc, u16 handle) +{ + struct mpi3mr_sas_node *sas_expander, *r; + + r = NULL; + list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) { + if (sas_expander->handle != handle) + continue; + r = sas_expander; + goto out; + } + out: + return r; +} + +/** + * mpi3mr_is_expander_device - if device is an expander + * @device_info: Bitfield providing information about the device + * + * Return: 1 if the device is expander device, else 0. + */ +u8 mpi3mr_is_expander_device(u16 device_info) +{ + if ((device_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) == + MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER) + return 1; + else + return 0; +} + +/** + * mpi3mr_get_sas_address - retrieve sas_address for handle + * @mrioc: Adapter instance reference + * @handle: Firmware device handle + * @sas_address: Address to hold sas address + * + * This function issues device page0 read for a given device + * handle and gets the SAS address and return it back + * + * Return: 0 for success, non-zero for failure + */ +static int mpi3mr_get_sas_address(struct mpi3mr_ioc *mrioc, u16 handle, + u64 *sas_address) +{ + struct mpi3_device_page0 dev_pg0; + u16 ioc_status; + struct mpi3_device0_sas_sata_format *sasinf; + + *sas_address = 0; + + if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0, + sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE, + handle))) { + ioc_err(mrioc, "%s: device page0 read failed\n", __func__); + return -ENXIO; + } + + if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { + ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n", + handle, ioc_status, __FILE__, __LINE__, __func__); + return -ENXIO; + } + + if (le16_to_cpu(dev_pg0.flags) & + MPI3_DEVICE0_FLAGS_CONTROLLER_DEV_HANDLE) + *sas_address = mrioc->sas_hba.sas_address; + else if (dev_pg0.device_form == MPI3_DEVICE_DEVFORM_SAS_SATA) { + sasinf = &dev_pg0.device_specific.sas_sata_format; + *sas_address = le64_to_cpu(sasinf->sas_address); + } else { + ioc_err(mrioc, "%s: device_form(%d) is not SAS_SATA\n", + __func__, dev_pg0.device_form); + return -ENXIO; + } + return 0; +} + +/** + * __mpi3mr_get_tgtdev_by_addr - target device search + * @mrioc: Adapter instance reference + * @sas_address: SAS address of the device + * @hba_port: HBA port entry + * + * This searches for target device from sas address and hba port + * pointer then return mpi3mr_tgt_dev object. + * + * Return: Valid tget_dev or NULL + */ +static struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_addr(struct mpi3mr_ioc *mrioc, + u64 sas_address, struct mpi3mr_hba_port *hba_port) +{ + struct mpi3mr_tgt_dev *tgtdev; + + assert_spin_locked(&mrioc->tgtdev_lock); + + list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list) + if ((tgtdev->dev_type == MPI3_DEVICE_DEVFORM_SAS_SATA) && + (tgtdev->dev_spec.sas_sata_inf.sas_address == sas_address) + && (tgtdev->dev_spec.sas_sata_inf.hba_port == hba_port)) + goto found_device; + return NULL; +found_device: + mpi3mr_tgtdev_get(tgtdev); + return tgtdev; +} + +/** + * mpi3mr_get_tgtdev_by_addr - target device search + * @mrioc: Adapter instance reference + * @sas_address: SAS address of the device + * @hba_port: HBA port entry + * + * This searches for target device from sas address and hba port + * pointer then return mpi3mr_tgt_dev object. + * + * Context: This function will acquire tgtdev_lock and will + * release before returning the mpi3mr_tgt_dev object. + * + * Return: Valid tget_dev or NULL + */ +static struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_by_addr(struct mpi3mr_ioc *mrioc, + u64 sas_address, struct mpi3mr_hba_port *hba_port) +{ + struct mpi3mr_tgt_dev *tgtdev = NULL; + unsigned long flags; + + if (!hba_port) + goto out; + + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); + tgtdev = __mpi3mr_get_tgtdev_by_addr(mrioc, sas_address, hba_port); + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); + +out: + return tgtdev; +} + +/** + * mpi3mr_expander_find_by_sas_address - sas expander search + * @mrioc: Adapter instance reference + * @sas_address: SAS address of expander + * @hba_port: HBA port entry + * + * Return: A valid SAS expander node or NULL. + * + */ +static struct mpi3mr_sas_node *mpi3mr_expander_find_by_sas_address( + struct mpi3mr_ioc *mrioc, u64 sas_address, + struct mpi3mr_hba_port *hba_port) +{ + struct mpi3mr_sas_node *sas_expander, *r = NULL; + + if (!hba_port) + goto out; + + list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) { + if ((sas_expander->sas_address != sas_address) || + (sas_expander->hba_port != hba_port)) + continue; + r = sas_expander; + goto out; + } +out: + return r; +} + +/** + * __mpi3mr_sas_node_find_by_sas_address - sas node search + * @mrioc: Adapter instance reference + * @sas_address: SAS address of expander or sas host + * @hba_port: HBA port entry + * Context: Caller should acquire mrioc->sas_node_lock. + * + * If the SAS address indicates the device is direct attached to + * the controller (controller's SAS address) then the SAS node + * associated with the controller is returned back else the SAS + * address and hba port are used to identify the exact expander + * and the associated sas_node object is returned. If there is + * no match NULL is returned. + * + * Return: A valid SAS node or NULL. + * + */ +static struct mpi3mr_sas_node *__mpi3mr_sas_node_find_by_sas_address( + struct mpi3mr_ioc *mrioc, u64 sas_address, + struct mpi3mr_hba_port *hba_port) +{ + + if (mrioc->sas_hba.sas_address == sas_address) + return &mrioc->sas_hba; + return mpi3mr_expander_find_by_sas_address(mrioc, sas_address, + hba_port); +} + +/** + * mpi3mr_parent_present - Is parent present for a phy + * @mrioc: Adapter instance reference + * @phy: SAS transport layer phy object + * + * Return: 0 if parent is present else non-zero + */ +static int mpi3mr_parent_present(struct mpi3mr_ioc *mrioc, struct sas_phy *phy) +{ + + unsigned long flags; + struct mpi3mr_hba_port *hba_port = phy->hostdata; + + spin_lock_irqsave(&mrioc->sas_node_lock, flags); + if (__mpi3mr_sas_node_find_by_sas_address(mrioc, + phy->identify.sas_address, + hba_port) == NULL) { + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); + return -1; + } + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); + return 0; +} + /** * mpi3mr_convert_phy_link_rate - * @link_rate: link rate as defined in the MPI header @@ -428,3 +659,52 @@ static int mpi3mr_add_expander_phy(struct mpi3mr_ioc *mrioc, mr_sas_phy->phy = phy; return 0; } + +/** + * mpi3mr_alloc_hba_port - alloc hba port object + * @mrioc: Adapter instance reference + * @port_id: Port number + * + * Alloc memory for hba port object. + */ +static struct mpi3mr_hba_port * +mpi3mr_alloc_hba_port(struct mpi3mr_ioc *mrioc, u16 port_id) +{ + struct mpi3mr_hba_port *hba_port; + + hba_port = kzalloc(sizeof(struct mpi3mr_hba_port), + GFP_KERNEL); + if (!hba_port) + return NULL; + hba_port->port_id = port_id; + ioc_info(mrioc, "hba_port entry: %p, port: %d is added to hba_port list\n", + hba_port, hba_port->port_id); + list_add_tail(&hba_port->list, &mrioc->hba_port_table_list); + return hba_port; +} + +/** + * mpi3mr_get_hba_port_by_id - find hba port by id + * @mrioc: Adapter instance reference + * @port_id - Port ID to search + * + * Return: mpi3mr_hba_port reference for the matched port + */ + +struct mpi3mr_hba_port *mpi3mr_get_hba_port_by_id(struct mpi3mr_ioc *mrioc, + u8 port_id) +{ + + struct mpi3mr_hba_port *port, *port_next; + + list_for_each_entry_safe(port, port_next, + &mrioc->hba_port_table_list, list) { + if (port->port_id != port_id) + continue; + if (port->flags & MPI3MR_HBA_PORT_FLAG_DIRTY) + continue; + return port; + } + + return NULL; +}
Added below helper functions, - Get the device's sas address by reading correspond device's Device page0, - Get the expander object from expander list based on expander's handle, - Get the target device object from target device list based on device's sas address, - Get the expander device object from expander list based on expanders's sas address, - Get hba port object from hba port table list based on port's port id Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com> --- drivers/scsi/mpi3mr/mpi3mr.h | 14 ++ drivers/scsi/mpi3mr/mpi3mr_os.c | 3 + drivers/scsi/mpi3mr/mpi3mr_transport.c | 280 +++++++++++++++++++++++++ 3 files changed, 297 insertions(+)