> On Jul 29, 2022, at 6:16 AM, Sreekanth Reddy <sreekanth.reddy@xxxxxxxxxxxx> 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@xxxxxxxxxxxx> > --- > 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