Message ID | 20220729131627.15019-8-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, > - Add, update the host phys with STL > - Add, remove the device's sas port with STL > > Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com> > --- > drivers/scsi/mpi3mr/mpi3mr.h | 13 + > drivers/scsi/mpi3mr/mpi3mr_os.c | 2 +- > drivers/scsi/mpi3mr/mpi3mr_transport.c | 527 +++++++++++++++++++++++++ > 3 files changed, 541 insertions(+), 1 deletion(-) > > diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h > index 742caf5..8ab843a 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr.h > +++ b/drivers/scsi/mpi3mr/mpi3mr.h > @@ -570,12 +570,18 @@ struct mpi3mr_enclosure_node { > * > * @sas_address: World wide unique SAS address > * @dev_info: Device information bits > + * @sas_transport_attached: Is this device exposed to transport > + * @pend_sas_rphy_add: Flag to check device is in process of add > * @hba_port: HBA port entry > + * @rphy: SAS transport layer rphy object > */ > struct tgt_dev_sas_sata { > u64 sas_address; > u16 dev_info; > + u8 sas_transport_attached; > + u8 pend_sas_rphy_add; > struct mpi3mr_hba_port *hba_port; > + struct sas_rphy *rphy; > }; > > /** > @@ -1331,4 +1337,11 @@ int mpi3mr_cfg_get_driver_pg1(struct mpi3mr_ioc *mrioc, > 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); > +void mpi3mr_sas_host_refresh(struct mpi3mr_ioc *mrioc); > +void mpi3mr_sas_host_add(struct mpi3mr_ioc *mrioc); > +void mpi3mr_update_links(struct mpi3mr_ioc *mrioc, > + u64 sas_address_parent, u16 handle, u8 phy_number, u8 link_rate, > + struct mpi3mr_hba_port *hba_port); > +void mpi3mr_print_device_event_notice(struct mpi3mr_ioc *mrioc, > + bool device_add); > #endif /*MPI3MR_H_INCLUDED*/ > diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c > index b75ce73..905b434 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_os.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c > @@ -804,7 +804,7 @@ static void mpi3mr_set_io_divert_for_all_vd_in_tg(struct mpi3mr_ioc *mrioc, > * > * Return: None. > */ > -static void mpi3mr_print_device_event_notice(struct mpi3mr_ioc *mrioc, > +void mpi3mr_print_device_event_notice(struct mpi3mr_ioc *mrioc, > bool device_add) > { > ioc_notice(mrioc, "Device %s was in progress before the reset and\n", > diff --git a/drivers/scsi/mpi3mr/mpi3mr_transport.c b/drivers/scsi/mpi3mr/mpi3mr_transport.c > index fea3aae..b85d60f 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_transport.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_transport.c > @@ -708,3 +708,530 @@ struct mpi3mr_hba_port *mpi3mr_get_hba_port_by_id(struct mpi3mr_ioc *mrioc, > > return NULL; > } > + > +/** > + * mpi3mr_update_links - refreshing SAS phy link changes > + * @mrioc: Adapter instance reference > + * @sas_address_parent: SAS address of parent expander or host > + * @handle: Firmware device handle of attached device > + * @phy_number: Phy number > + * @link_rate: New link rate > + * @hba_port: HBA port entry > + * > + * Return: None. > + */ > +void mpi3mr_update_links(struct mpi3mr_ioc *mrioc, > + u64 sas_address_parent, u16 handle, u8 phy_number, u8 link_rate, > + struct mpi3mr_hba_port *hba_port) > +{ > + unsigned long flags; > + struct mpi3mr_sas_node *mr_sas_node; > + struct mpi3mr_sas_phy *mr_sas_phy; > + > + if (mrioc->reset_in_progress) > + return; > + > + spin_lock_irqsave(&mrioc->sas_node_lock, flags); > + mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc, > + sas_address_parent, hba_port); > + if (!mr_sas_node) { > + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); > + return; > + } > + > + mr_sas_phy = &mr_sas_node->phy[phy_number]; > + mr_sas_phy->attached_handle = handle; > + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); > + if (handle && (link_rate >= MPI3_SAS_NEG_LINK_RATE_1_5)) { > + mpi3mr_set_identify(mrioc, handle, > + &mr_sas_phy->remote_identify); > + mpi3mr_add_phy_to_an_existing_port(mrioc, mr_sas_node, > + mr_sas_phy, mr_sas_phy->remote_identify.sas_address, > + hba_port); > + } else > + memset(&mr_sas_phy->remote_identify, 0, sizeof(struct > + sas_identify)); > + > + if (mr_sas_phy->phy) > + mr_sas_phy->phy->negotiated_linkrate = > + mpi3mr_convert_phy_link_rate(link_rate); > + > + if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO)) > + dev_info(&mr_sas_phy->phy->dev, > + "refresh: parent sas_address(0x%016llx),\n" > + "\tlink_rate(0x%02x), phy(%d)\n" > + "\tattached_handle(0x%04x), sas_address(0x%016llx)\n", > + (unsigned long long)sas_address_parent, > + link_rate, phy_number, handle, (unsigned long long) > + mr_sas_phy->remote_identify.sas_address); > +} > + > +/** > + * mpi3mr_sas_host_refresh - refreshing sas host object contents > + * @mrioc: Adapter instance reference > + * > + * This function refreshes the controllers phy information and > + * updates the SAS transport layer with updated information, > + * this is executed for each device addition or device info > + * change events > + * > + * Return: None. > + */ > +void mpi3mr_sas_host_refresh(struct mpi3mr_ioc *mrioc) > +{ > + int i; > + u8 link_rate; > + u16 sz, port_id, attached_handle; > + struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL; > + > + dprint_transport_info(mrioc, > + "updating handles for sas_host(0x%016llx)\n", > + (unsigned long long)mrioc->sas_hba.sas_address); > + > + sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) + > + (mrioc->sas_hba.num_phys * > + sizeof(struct mpi3_sas_io_unit0_phy_data)); > + sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL); > + if (!sas_io_unit_pg0) > + return; > + if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) { > + ioc_err(mrioc, "failure at %s:%d/%s()!\n", > + __FILE__, __LINE__, __func__); > + goto out; > + } > + > + mrioc->sas_hba.handle = 0; > + for (i = 0; i < mrioc->sas_hba.num_phys; i++) { > + if (sas_io_unit_pg0->phy_data[i].phy_flags & > + (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY | > + MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY)) > + continue; > + link_rate = > + sas_io_unit_pg0->phy_data[i].negotiated_link_rate >> 4; > + if (!mrioc->sas_hba.handle) > + mrioc->sas_hba.handle = le16_to_cpu( > + sas_io_unit_pg0->phy_data[i].controller_dev_handle); > + port_id = sas_io_unit_pg0->phy_data[i].io_unit_port; > + if (!(mpi3mr_get_hba_port_by_id(mrioc, port_id))) > + if (!mpi3mr_alloc_hba_port(mrioc, port_id)) > + goto out; > + > + mrioc->sas_hba.phy[i].handle = mrioc->sas_hba.handle; > + attached_handle = le16_to_cpu( > + sas_io_unit_pg0->phy_data[i].attached_dev_handle); > + if (attached_handle && link_rate < MPI3_SAS_NEG_LINK_RATE_1_5) > + link_rate = MPI3_SAS_NEG_LINK_RATE_1_5; > + mrioc->sas_hba.phy[i].hba_port = > + mpi3mr_get_hba_port_by_id(mrioc, port_id); > + mpi3mr_update_links(mrioc, mrioc->sas_hba.sas_address, > + attached_handle, i, link_rate, > + mrioc->sas_hba.phy[i].hba_port); > + } > + out: > + kfree(sas_io_unit_pg0); > +} > + > +/** > + * mpi3mr_sas_host_add - create sas host object > + * @mrioc: Adapter instance reference > + * > + * This function creates the controllers phy information and > + * updates the SAS transport layer with updated information, > + * this is executed for first device addition or device info > + * change event. > + * > + * Return: None. > + */ > +void mpi3mr_sas_host_add(struct mpi3mr_ioc *mrioc) > +{ > + int i; > + u16 sz, num_phys = 1, port_id, ioc_status; > + struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL; > + struct mpi3_sas_phy_page0 phy_pg0; > + struct mpi3_device_page0 dev_pg0; > + struct mpi3_enclosure_page0 encl_pg0; > + struct mpi3_device0_sas_sata_format *sasinf; > + > + remove extra newline > + sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) + > + (num_phys * sizeof(struct mpi3_sas_io_unit0_phy_data)); > + sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL); > + if (!sas_io_unit_pg0) > + return; > + > + if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) { > + ioc_err(mrioc, "failure at %s:%d/%s()!\n", > + __FILE__, __LINE__, __func__); > + goto out; > + } > + num_phys = sas_io_unit_pg0->num_phys; > + kfree(sas_io_unit_pg0); > + > + mrioc->sas_hba.host_node = 1; > + INIT_LIST_HEAD(&mrioc->sas_hba.sas_port_list); > + mrioc->sas_hba.parent_dev = &mrioc->shost->shost_gendev; > + mrioc->sas_hba.phy = kcalloc(num_phys, > + sizeof(struct mpi3mr_sas_phy), GFP_KERNEL); > + if (!mrioc->sas_hba.phy) > + return; > + > + mrioc->sas_hba.num_phys = num_phys; > + > + sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) + > + (num_phys * sizeof(struct mpi3_sas_io_unit0_phy_data)); > + sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL); > + if (!sas_io_unit_pg0) > + return; > + > + if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) { > + ioc_err(mrioc, "failure at %s:%d/%s()!\n", > + __FILE__, __LINE__, __func__); > + goto out; > + } > + > + mrioc->sas_hba.handle = 0; > + for (i = 0; i < mrioc->sas_hba.num_phys; i++) { > + if (sas_io_unit_pg0->phy_data[i].phy_flags & > + (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY | > + MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY)) > + continue; > + if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0, > + sizeof(struct mpi3_sas_phy_page0), > + MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, i)) { > + ioc_err(mrioc, "failure at %s:%d/%s()!\n", > + __FILE__, __LINE__, __func__); > + goto out; > + } > + if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { > + ioc_err(mrioc, "failure at %s:%d/%s()!\n", > + __FILE__, __LINE__, __func__); > + goto out; > + } > + > + if (!mrioc->sas_hba.handle) > + mrioc->sas_hba.handle = le16_to_cpu( > + sas_io_unit_pg0->phy_data[i].controller_dev_handle); > + port_id = sas_io_unit_pg0->phy_data[i].io_unit_port; > + > + if (!(mpi3mr_get_hba_port_by_id(mrioc, port_id))) > + if (!mpi3mr_alloc_hba_port(mrioc, port_id)) > + goto out; > + > + mrioc->sas_hba.phy[i].handle = mrioc->sas_hba.handle; > + mrioc->sas_hba.phy[i].phy_id = i; > + mrioc->sas_hba.phy[i].hba_port = > + mpi3mr_get_hba_port_by_id(mrioc, port_id); > + mpi3mr_add_host_phy(mrioc, &mrioc->sas_hba.phy[i], > + phy_pg0, mrioc->sas_hba.parent_dev); > + } > + if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0, > + sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE, > + mrioc->sas_hba.handle))) { > + ioc_err(mrioc, "%s: device page0 read failed\n", __func__); > + goto out; > + } > + 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", > + mrioc->sas_hba.handle, ioc_status, __FILE__, __LINE__, > + __func__); > + goto out; > + } > + mrioc->sas_hba.enclosure_handle = > + le16_to_cpu(dev_pg0.enclosure_handle); > + sasinf = &dev_pg0.device_specific.sas_sata_format; > + mrioc->sas_hba.sas_address = > + le64_to_cpu(sasinf->sas_address); > + ioc_info(mrioc, > + "host_add: handle(0x%04x), sas_addr(0x%016llx), phys(%d)\n", > + mrioc->sas_hba.handle, > + (unsigned long long) mrioc->sas_hba.sas_address, > + mrioc->sas_hba.num_phys); > + > + if (mrioc->sas_hba.enclosure_handle) { > + if (!(mpi3mr_cfg_get_enclosure_pg0(mrioc, &ioc_status, > + &encl_pg0, sizeof(dev_pg0), > + MPI3_ENCLOS_PGAD_FORM_HANDLE, > + mrioc->sas_hba.enclosure_handle)) && > + (ioc_status == MPI3_IOCSTATUS_SUCCESS)) > + mrioc->sas_hba.enclosure_logical_id = > + le64_to_cpu(encl_pg0.enclosure_logical_id); > + } > + > +out: > + kfree(sas_io_unit_pg0); > +} > + > +/** > + * mpi3mr_sas_port_add - Expose the SAS device to the SAS TL > + * @mrioc: Adapter instance reference > + * @handle: Firmware device handle of the attached device > + * @sas_address_parent: sas address of parent expander or host > + * @hba_port: HBA port entry > + * > + * This function creates a new sas port object for the given end > + * device matching sas address and hba_port and adds it to the > + * sas_node's sas_port_list and expose the attached sas device > + * to the SAS transport layer through sas_rphy_add. > + * > + * Returns a valid mpi3mr_sas_port reference or NULL. > + */ > +static struct mpi3mr_sas_port *mpi3mr_sas_port_add(struct mpi3mr_ioc *mrioc, > + u16 handle, u64 sas_address_parent, struct mpi3mr_hba_port *hba_port) > +{ > + remove newline > + struct mpi3mr_sas_phy *mr_sas_phy, *next; > + struct mpi3mr_sas_port *mr_sas_port; > + unsigned long flags; > + struct mpi3mr_sas_node *mr_sas_node; > + struct sas_rphy *rphy; > + struct mpi3mr_tgt_dev *tgtdev = NULL; > + int i; > + struct sas_port *port; > + > + if (!hba_port) { > + ioc_err(mrioc, "failure at %s:%d/%s()!\n", > + __FILE__, __LINE__, __func__); > + return NULL; > + } > + > + mr_sas_port = kzalloc(sizeof(struct mpi3mr_sas_port), GFP_KERNEL); > + if (!mr_sas_port) > + return NULL; > + > + INIT_LIST_HEAD(&mr_sas_port->port_list); > + INIT_LIST_HEAD(&mr_sas_port->phy_list); > + spin_lock_irqsave(&mrioc->sas_node_lock, flags); > + mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc, > + sas_address_parent, hba_port); > + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); > + > + if (!mr_sas_node) { > + ioc_err(mrioc, "%s:could not find parent sas_address(0x%016llx)!\n", > + __func__, (unsigned long long)sas_address_parent); > + goto out_fail; > + } > + > + if ((mpi3mr_set_identify(mrioc, handle, > + &mr_sas_port->remote_identify))) { > + ioc_err(mrioc, "failure at %s:%d/%s()!\n", > + __FILE__, __LINE__, __func__); > + goto out_fail; > + } > + > + if (mr_sas_port->remote_identify.device_type == SAS_PHY_UNUSED) { > + ioc_err(mrioc, "failure at %s:%d/%s()!\n", > + __FILE__, __LINE__, __func__); > + goto out_fail; > + } > + > + mr_sas_port->hba_port = hba_port; > + mpi3mr_sas_port_sanity_check(mrioc, mr_sas_node, > + mr_sas_port->remote_identify.sas_address, hba_port); > + > + for (i = 0; i < mr_sas_node->num_phys; i++) { > + if ((mr_sas_node->phy[i].remote_identify.sas_address != > + mr_sas_port->remote_identify.sas_address) || > + (mr_sas_node->phy[i].hba_port != hba_port)) > + continue; > + list_add_tail(&mr_sas_node->phy[i].port_siblings, > + &mr_sas_port->phy_list); > + mr_sas_port->num_phys++; > + } > + > + if (!mr_sas_port->num_phys) { > + ioc_err(mrioc, "failure at %s:%d/%s()!\n", > + __FILE__, __LINE__, __func__); > + goto out_fail; > + } > + > + if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) { > + tgtdev = mpi3mr_get_tgtdev_by_addr(mrioc, > + mr_sas_port->remote_identify.sas_address, > + mr_sas_port->hba_port); > + > + if (!tgtdev) { > + ioc_err(mrioc, "failure at %s:%d/%s()!\n", > + __FILE__, __LINE__, __func__); > + goto out_fail; > + } > + tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 1; > + } > + > + if (!mr_sas_node->parent_dev) { > + ioc_err(mrioc, "failure at %s:%d/%s()!\n", > + __FILE__, __LINE__, __func__); > + goto out_fail; > + } > + > + port = sas_port_alloc_num(mr_sas_node->parent_dev); > + if ((sas_port_add(port))) { > + ioc_err(mrioc, "failure at %s:%d/%s()!\n", > + __FILE__, __LINE__, __func__); > + goto out_fail; > + } > + > + list_for_each_entry(mr_sas_phy, &mr_sas_port->phy_list, > + port_siblings) { > + if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO)) > + dev_info(&port->dev, > + "add: handle(0x%04x), sas_address(0x%016llx), phy(%d)\n", > + handle, (unsigned long long) > + mr_sas_port->remote_identify.sas_address, > + mr_sas_phy->phy_id); > + sas_port_add_phy(port, mr_sas_phy->phy); > + mr_sas_phy->phy_belongs_to_port = 1; > + mr_sas_phy->hba_port = hba_port; > + } > + > + mr_sas_port->port = port; > + if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) { > + rphy = sas_end_device_alloc(port); > + tgtdev->dev_spec.sas_sata_inf.rphy = rphy; > + } else { > + rphy = sas_expander_alloc(port, > + mr_sas_port->remote_identify.device_type); > + } > + rphy->identify = mr_sas_port->remote_identify; > + > + if (mrioc->current_event) > + mrioc->current_event->pending_at_sml = 1; > + > + if ((sas_rphy_add(rphy))) { > + ioc_err(mrioc, "failure at %s:%d/%s()!\n", > + __FILE__, __LINE__, __func__); > + } > + if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) { > + tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 0; > + tgtdev->dev_spec.sas_sata_inf.sas_transport_attached = 1; > + mpi3mr_tgtdev_put(tgtdev); > + } > + > + dev_info(&rphy->dev, > + "%s: added: handle(0x%04x), sas_address(0x%016llx)\n", > + __func__, handle, (unsigned long long) > + mr_sas_port->remote_identify.sas_address); > + > + mr_sas_port->rphy = rphy; > + spin_lock_irqsave(&mrioc->sas_node_lock, flags); > + list_add_tail(&mr_sas_port->port_list, &mr_sas_node->sas_port_list); > + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); > + > + if (mrioc->current_event) { > + mrioc->current_event->pending_at_sml = 0; > + if (mrioc->current_event->discard) > + mpi3mr_print_device_event_notice(mrioc, true); > + } > + > + return mr_sas_port; > + > + out_fail: > + list_for_each_entry_safe(mr_sas_phy, next, &mr_sas_port->phy_list, > + port_siblings) > + list_del(&mr_sas_phy->port_siblings); > + kfree(mr_sas_port); > + return NULL; > +} > + > +/** > + * mpi3mr_sas_port_remove - remove port from the list > + * @mrioc: Adapter instance reference > + * @sas_address: SAS address of attached device > + * @sas_address_parent: SAS address of parent expander or host > + * @hba_port: HBA port entry > + * > + * Removing object and freeing associated memory from the > + * sas_port_list. > + * > + * Return: None > + */ > +static void mpi3mr_sas_port_remove(struct mpi3mr_ioc *mrioc, u64 sas_address, > + u64 sas_address_parent, struct mpi3mr_hba_port *hba_port) > +{ > + int i; > + unsigned long flags; > + struct mpi3mr_sas_port *mr_sas_port, *next; > + struct mpi3mr_sas_node *mr_sas_node; > + u8 found = 0; > + struct mpi3mr_sas_phy *mr_sas_phy, *next_phy; > + struct mpi3mr_hba_port *srch_port, *hba_port_next = NULL; > + > + if (!hba_port) > + return; > + > + spin_lock_irqsave(&mrioc->sas_node_lock, flags); > + mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc, > + sas_address_parent, hba_port); > + if (!mr_sas_node) { > + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); > + return; > + } > + list_for_each_entry_safe(mr_sas_port, next, &mr_sas_node->sas_port_list, > + port_list) { > + if (mr_sas_port->remote_identify.sas_address != sas_address) > + continue; > + if (mr_sas_port->hba_port != hba_port) > + continue; > + found = 1; > + list_del(&mr_sas_port->port_list); > + goto out; > + } > + > + out: > + if (!found) { > + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); > + return; > + } > + > + if (mr_sas_node->host_node) { > + list_for_each_entry_safe(srch_port, hba_port_next, > + &mrioc->hba_port_table_list, list) { > + if (srch_port != hba_port) > + continue; > + ioc_info(mrioc, > + "removing hba_port entry: %p port: %d from hba_port list\n", > + srch_port, srch_port->port_id); > + list_del(&hba_port->list); > + kfree(hba_port); > + break; > + } > + } > + > + for (i = 0; i < mr_sas_node->num_phys; i++) { > + if (mr_sas_node->phy[i].remote_identify.sas_address == > + sas_address) > + memset(&mr_sas_node->phy[i].remote_identify, 0, > + sizeof(struct sas_identify)); > + } > + > + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); > + > + if (mrioc->current_event) > + mrioc->current_event->pending_at_sml = 1; > + > + list_for_each_entry_safe(mr_sas_phy, next_phy, > + &mr_sas_port->phy_list, port_siblings) { > + if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO)) > + dev_info(&mr_sas_port->port->dev, > + "remove: sas_address(0x%016llx), phy(%d)\n", > + (unsigned long long) > + mr_sas_port->remote_identify.sas_address, > + mr_sas_phy->phy_id); > + mr_sas_phy->phy_belongs_to_port = 0; > + if (!mrioc->stop_drv_processing) > + sas_port_delete_phy(mr_sas_port->port, > + mr_sas_phy->phy); > + list_del(&mr_sas_phy->port_siblings); > + } > + if (!mrioc->stop_drv_processing) > + sas_port_delete(mr_sas_port->port); > + ioc_info(mrioc, "%s: removed sas_address(0x%016llx)\n", > + __func__, (unsigned long long)sas_address); > + > + if (mrioc->current_event) { > + mrioc->current_event->pending_at_sml = 0; > + if (mrioc->current_event->discard) > + mpi3mr_print_device_event_notice(mrioc, false); > + } > + > + kfree(mr_sas_port); > +} > -- > 2.27.0 > Looks good. When you fix the small nit above, you can add Reviewed-by: Himanshu Madhani <himanshu.madani@oracle.com> -- Himanshu Madhani Oracle Linux Engineering
diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 742caf5..8ab843a 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -570,12 +570,18 @@ struct mpi3mr_enclosure_node { * * @sas_address: World wide unique SAS address * @dev_info: Device information bits + * @sas_transport_attached: Is this device exposed to transport + * @pend_sas_rphy_add: Flag to check device is in process of add * @hba_port: HBA port entry + * @rphy: SAS transport layer rphy object */ struct tgt_dev_sas_sata { u64 sas_address; u16 dev_info; + u8 sas_transport_attached; + u8 pend_sas_rphy_add; struct mpi3mr_hba_port *hba_port; + struct sas_rphy *rphy; }; /** @@ -1331,4 +1337,11 @@ int mpi3mr_cfg_get_driver_pg1(struct mpi3mr_ioc *mrioc, 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); +void mpi3mr_sas_host_refresh(struct mpi3mr_ioc *mrioc); +void mpi3mr_sas_host_add(struct mpi3mr_ioc *mrioc); +void mpi3mr_update_links(struct mpi3mr_ioc *mrioc, + u64 sas_address_parent, u16 handle, u8 phy_number, u8 link_rate, + struct mpi3mr_hba_port *hba_port); +void mpi3mr_print_device_event_notice(struct mpi3mr_ioc *mrioc, + bool device_add); #endif /*MPI3MR_H_INCLUDED*/ diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index b75ce73..905b434 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -804,7 +804,7 @@ static void mpi3mr_set_io_divert_for_all_vd_in_tg(struct mpi3mr_ioc *mrioc, * * Return: None. */ -static void mpi3mr_print_device_event_notice(struct mpi3mr_ioc *mrioc, +void mpi3mr_print_device_event_notice(struct mpi3mr_ioc *mrioc, bool device_add) { ioc_notice(mrioc, "Device %s was in progress before the reset and\n", diff --git a/drivers/scsi/mpi3mr/mpi3mr_transport.c b/drivers/scsi/mpi3mr/mpi3mr_transport.c index fea3aae..b85d60f 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_transport.c +++ b/drivers/scsi/mpi3mr/mpi3mr_transport.c @@ -708,3 +708,530 @@ struct mpi3mr_hba_port *mpi3mr_get_hba_port_by_id(struct mpi3mr_ioc *mrioc, return NULL; } + +/** + * mpi3mr_update_links - refreshing SAS phy link changes + * @mrioc: Adapter instance reference + * @sas_address_parent: SAS address of parent expander or host + * @handle: Firmware device handle of attached device + * @phy_number: Phy number + * @link_rate: New link rate + * @hba_port: HBA port entry + * + * Return: None. + */ +void mpi3mr_update_links(struct mpi3mr_ioc *mrioc, + u64 sas_address_parent, u16 handle, u8 phy_number, u8 link_rate, + struct mpi3mr_hba_port *hba_port) +{ + unsigned long flags; + struct mpi3mr_sas_node *mr_sas_node; + struct mpi3mr_sas_phy *mr_sas_phy; + + if (mrioc->reset_in_progress) + return; + + spin_lock_irqsave(&mrioc->sas_node_lock, flags); + mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc, + sas_address_parent, hba_port); + if (!mr_sas_node) { + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); + return; + } + + mr_sas_phy = &mr_sas_node->phy[phy_number]; + mr_sas_phy->attached_handle = handle; + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); + if (handle && (link_rate >= MPI3_SAS_NEG_LINK_RATE_1_5)) { + mpi3mr_set_identify(mrioc, handle, + &mr_sas_phy->remote_identify); + mpi3mr_add_phy_to_an_existing_port(mrioc, mr_sas_node, + mr_sas_phy, mr_sas_phy->remote_identify.sas_address, + hba_port); + } else + memset(&mr_sas_phy->remote_identify, 0, sizeof(struct + sas_identify)); + + if (mr_sas_phy->phy) + mr_sas_phy->phy->negotiated_linkrate = + mpi3mr_convert_phy_link_rate(link_rate); + + if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO)) + dev_info(&mr_sas_phy->phy->dev, + "refresh: parent sas_address(0x%016llx),\n" + "\tlink_rate(0x%02x), phy(%d)\n" + "\tattached_handle(0x%04x), sas_address(0x%016llx)\n", + (unsigned long long)sas_address_parent, + link_rate, phy_number, handle, (unsigned long long) + mr_sas_phy->remote_identify.sas_address); +} + +/** + * mpi3mr_sas_host_refresh - refreshing sas host object contents + * @mrioc: Adapter instance reference + * + * This function refreshes the controllers phy information and + * updates the SAS transport layer with updated information, + * this is executed for each device addition or device info + * change events + * + * Return: None. + */ +void mpi3mr_sas_host_refresh(struct mpi3mr_ioc *mrioc) +{ + int i; + u8 link_rate; + u16 sz, port_id, attached_handle; + struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL; + + dprint_transport_info(mrioc, + "updating handles for sas_host(0x%016llx)\n", + (unsigned long long)mrioc->sas_hba.sas_address); + + sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) + + (mrioc->sas_hba.num_phys * + sizeof(struct mpi3_sas_io_unit0_phy_data)); + sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL); + if (!sas_io_unit_pg0) + return; + if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) { + ioc_err(mrioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + goto out; + } + + mrioc->sas_hba.handle = 0; + for (i = 0; i < mrioc->sas_hba.num_phys; i++) { + if (sas_io_unit_pg0->phy_data[i].phy_flags & + (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY | + MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY)) + continue; + link_rate = + sas_io_unit_pg0->phy_data[i].negotiated_link_rate >> 4; + if (!mrioc->sas_hba.handle) + mrioc->sas_hba.handle = le16_to_cpu( + sas_io_unit_pg0->phy_data[i].controller_dev_handle); + port_id = sas_io_unit_pg0->phy_data[i].io_unit_port; + if (!(mpi3mr_get_hba_port_by_id(mrioc, port_id))) + if (!mpi3mr_alloc_hba_port(mrioc, port_id)) + goto out; + + mrioc->sas_hba.phy[i].handle = mrioc->sas_hba.handle; + attached_handle = le16_to_cpu( + sas_io_unit_pg0->phy_data[i].attached_dev_handle); + if (attached_handle && link_rate < MPI3_SAS_NEG_LINK_RATE_1_5) + link_rate = MPI3_SAS_NEG_LINK_RATE_1_5; + mrioc->sas_hba.phy[i].hba_port = + mpi3mr_get_hba_port_by_id(mrioc, port_id); + mpi3mr_update_links(mrioc, mrioc->sas_hba.sas_address, + attached_handle, i, link_rate, + mrioc->sas_hba.phy[i].hba_port); + } + out: + kfree(sas_io_unit_pg0); +} + +/** + * mpi3mr_sas_host_add - create sas host object + * @mrioc: Adapter instance reference + * + * This function creates the controllers phy information and + * updates the SAS transport layer with updated information, + * this is executed for first device addition or device info + * change event. + * + * Return: None. + */ +void mpi3mr_sas_host_add(struct mpi3mr_ioc *mrioc) +{ + int i; + u16 sz, num_phys = 1, port_id, ioc_status; + struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL; + struct mpi3_sas_phy_page0 phy_pg0; + struct mpi3_device_page0 dev_pg0; + struct mpi3_enclosure_page0 encl_pg0; + struct mpi3_device0_sas_sata_format *sasinf; + + + sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) + + (num_phys * sizeof(struct mpi3_sas_io_unit0_phy_data)); + sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL); + if (!sas_io_unit_pg0) + return; + + if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) { + ioc_err(mrioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + goto out; + } + num_phys = sas_io_unit_pg0->num_phys; + kfree(sas_io_unit_pg0); + + mrioc->sas_hba.host_node = 1; + INIT_LIST_HEAD(&mrioc->sas_hba.sas_port_list); + mrioc->sas_hba.parent_dev = &mrioc->shost->shost_gendev; + mrioc->sas_hba.phy = kcalloc(num_phys, + sizeof(struct mpi3mr_sas_phy), GFP_KERNEL); + if (!mrioc->sas_hba.phy) + return; + + mrioc->sas_hba.num_phys = num_phys; + + sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) + + (num_phys * sizeof(struct mpi3_sas_io_unit0_phy_data)); + sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL); + if (!sas_io_unit_pg0) + return; + + if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) { + ioc_err(mrioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + goto out; + } + + mrioc->sas_hba.handle = 0; + for (i = 0; i < mrioc->sas_hba.num_phys; i++) { + if (sas_io_unit_pg0->phy_data[i].phy_flags & + (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY | + MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY)) + continue; + if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0, + sizeof(struct mpi3_sas_phy_page0), + MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, i)) { + ioc_err(mrioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + goto out; + } + if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { + ioc_err(mrioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + goto out; + } + + if (!mrioc->sas_hba.handle) + mrioc->sas_hba.handle = le16_to_cpu( + sas_io_unit_pg0->phy_data[i].controller_dev_handle); + port_id = sas_io_unit_pg0->phy_data[i].io_unit_port; + + if (!(mpi3mr_get_hba_port_by_id(mrioc, port_id))) + if (!mpi3mr_alloc_hba_port(mrioc, port_id)) + goto out; + + mrioc->sas_hba.phy[i].handle = mrioc->sas_hba.handle; + mrioc->sas_hba.phy[i].phy_id = i; + mrioc->sas_hba.phy[i].hba_port = + mpi3mr_get_hba_port_by_id(mrioc, port_id); + mpi3mr_add_host_phy(mrioc, &mrioc->sas_hba.phy[i], + phy_pg0, mrioc->sas_hba.parent_dev); + } + if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0, + sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE, + mrioc->sas_hba.handle))) { + ioc_err(mrioc, "%s: device page0 read failed\n", __func__); + goto out; + } + 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", + mrioc->sas_hba.handle, ioc_status, __FILE__, __LINE__, + __func__); + goto out; + } + mrioc->sas_hba.enclosure_handle = + le16_to_cpu(dev_pg0.enclosure_handle); + sasinf = &dev_pg0.device_specific.sas_sata_format; + mrioc->sas_hba.sas_address = + le64_to_cpu(sasinf->sas_address); + ioc_info(mrioc, + "host_add: handle(0x%04x), sas_addr(0x%016llx), phys(%d)\n", + mrioc->sas_hba.handle, + (unsigned long long) mrioc->sas_hba.sas_address, + mrioc->sas_hba.num_phys); + + if (mrioc->sas_hba.enclosure_handle) { + if (!(mpi3mr_cfg_get_enclosure_pg0(mrioc, &ioc_status, + &encl_pg0, sizeof(dev_pg0), + MPI3_ENCLOS_PGAD_FORM_HANDLE, + mrioc->sas_hba.enclosure_handle)) && + (ioc_status == MPI3_IOCSTATUS_SUCCESS)) + mrioc->sas_hba.enclosure_logical_id = + le64_to_cpu(encl_pg0.enclosure_logical_id); + } + +out: + kfree(sas_io_unit_pg0); +} + +/** + * mpi3mr_sas_port_add - Expose the SAS device to the SAS TL + * @mrioc: Adapter instance reference + * @handle: Firmware device handle of the attached device + * @sas_address_parent: sas address of parent expander or host + * @hba_port: HBA port entry + * + * This function creates a new sas port object for the given end + * device matching sas address and hba_port and adds it to the + * sas_node's sas_port_list and expose the attached sas device + * to the SAS transport layer through sas_rphy_add. + * + * Returns a valid mpi3mr_sas_port reference or NULL. + */ +static struct mpi3mr_sas_port *mpi3mr_sas_port_add(struct mpi3mr_ioc *mrioc, + u16 handle, u64 sas_address_parent, struct mpi3mr_hba_port *hba_port) +{ + + struct mpi3mr_sas_phy *mr_sas_phy, *next; + struct mpi3mr_sas_port *mr_sas_port; + unsigned long flags; + struct mpi3mr_sas_node *mr_sas_node; + struct sas_rphy *rphy; + struct mpi3mr_tgt_dev *tgtdev = NULL; + int i; + struct sas_port *port; + + if (!hba_port) { + ioc_err(mrioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return NULL; + } + + mr_sas_port = kzalloc(sizeof(struct mpi3mr_sas_port), GFP_KERNEL); + if (!mr_sas_port) + return NULL; + + INIT_LIST_HEAD(&mr_sas_port->port_list); + INIT_LIST_HEAD(&mr_sas_port->phy_list); + spin_lock_irqsave(&mrioc->sas_node_lock, flags); + mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc, + sas_address_parent, hba_port); + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); + + if (!mr_sas_node) { + ioc_err(mrioc, "%s:could not find parent sas_address(0x%016llx)!\n", + __func__, (unsigned long long)sas_address_parent); + goto out_fail; + } + + if ((mpi3mr_set_identify(mrioc, handle, + &mr_sas_port->remote_identify))) { + ioc_err(mrioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + goto out_fail; + } + + if (mr_sas_port->remote_identify.device_type == SAS_PHY_UNUSED) { + ioc_err(mrioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + goto out_fail; + } + + mr_sas_port->hba_port = hba_port; + mpi3mr_sas_port_sanity_check(mrioc, mr_sas_node, + mr_sas_port->remote_identify.sas_address, hba_port); + + for (i = 0; i < mr_sas_node->num_phys; i++) { + if ((mr_sas_node->phy[i].remote_identify.sas_address != + mr_sas_port->remote_identify.sas_address) || + (mr_sas_node->phy[i].hba_port != hba_port)) + continue; + list_add_tail(&mr_sas_node->phy[i].port_siblings, + &mr_sas_port->phy_list); + mr_sas_port->num_phys++; + } + + if (!mr_sas_port->num_phys) { + ioc_err(mrioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + goto out_fail; + } + + if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) { + tgtdev = mpi3mr_get_tgtdev_by_addr(mrioc, + mr_sas_port->remote_identify.sas_address, + mr_sas_port->hba_port); + + if (!tgtdev) { + ioc_err(mrioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + goto out_fail; + } + tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 1; + } + + if (!mr_sas_node->parent_dev) { + ioc_err(mrioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + goto out_fail; + } + + port = sas_port_alloc_num(mr_sas_node->parent_dev); + if ((sas_port_add(port))) { + ioc_err(mrioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + goto out_fail; + } + + list_for_each_entry(mr_sas_phy, &mr_sas_port->phy_list, + port_siblings) { + if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO)) + dev_info(&port->dev, + "add: handle(0x%04x), sas_address(0x%016llx), phy(%d)\n", + handle, (unsigned long long) + mr_sas_port->remote_identify.sas_address, + mr_sas_phy->phy_id); + sas_port_add_phy(port, mr_sas_phy->phy); + mr_sas_phy->phy_belongs_to_port = 1; + mr_sas_phy->hba_port = hba_port; + } + + mr_sas_port->port = port; + if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) { + rphy = sas_end_device_alloc(port); + tgtdev->dev_spec.sas_sata_inf.rphy = rphy; + } else { + rphy = sas_expander_alloc(port, + mr_sas_port->remote_identify.device_type); + } + rphy->identify = mr_sas_port->remote_identify; + + if (mrioc->current_event) + mrioc->current_event->pending_at_sml = 1; + + if ((sas_rphy_add(rphy))) { + ioc_err(mrioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + } + if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) { + tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 0; + tgtdev->dev_spec.sas_sata_inf.sas_transport_attached = 1; + mpi3mr_tgtdev_put(tgtdev); + } + + dev_info(&rphy->dev, + "%s: added: handle(0x%04x), sas_address(0x%016llx)\n", + __func__, handle, (unsigned long long) + mr_sas_port->remote_identify.sas_address); + + mr_sas_port->rphy = rphy; + spin_lock_irqsave(&mrioc->sas_node_lock, flags); + list_add_tail(&mr_sas_port->port_list, &mr_sas_node->sas_port_list); + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); + + if (mrioc->current_event) { + mrioc->current_event->pending_at_sml = 0; + if (mrioc->current_event->discard) + mpi3mr_print_device_event_notice(mrioc, true); + } + + return mr_sas_port; + + out_fail: + list_for_each_entry_safe(mr_sas_phy, next, &mr_sas_port->phy_list, + port_siblings) + list_del(&mr_sas_phy->port_siblings); + kfree(mr_sas_port); + return NULL; +} + +/** + * mpi3mr_sas_port_remove - remove port from the list + * @mrioc: Adapter instance reference + * @sas_address: SAS address of attached device + * @sas_address_parent: SAS address of parent expander or host + * @hba_port: HBA port entry + * + * Removing object and freeing associated memory from the + * sas_port_list. + * + * Return: None + */ +static void mpi3mr_sas_port_remove(struct mpi3mr_ioc *mrioc, u64 sas_address, + u64 sas_address_parent, struct mpi3mr_hba_port *hba_port) +{ + int i; + unsigned long flags; + struct mpi3mr_sas_port *mr_sas_port, *next; + struct mpi3mr_sas_node *mr_sas_node; + u8 found = 0; + struct mpi3mr_sas_phy *mr_sas_phy, *next_phy; + struct mpi3mr_hba_port *srch_port, *hba_port_next = NULL; + + if (!hba_port) + return; + + spin_lock_irqsave(&mrioc->sas_node_lock, flags); + mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc, + sas_address_parent, hba_port); + if (!mr_sas_node) { + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); + return; + } + list_for_each_entry_safe(mr_sas_port, next, &mr_sas_node->sas_port_list, + port_list) { + if (mr_sas_port->remote_identify.sas_address != sas_address) + continue; + if (mr_sas_port->hba_port != hba_port) + continue; + found = 1; + list_del(&mr_sas_port->port_list); + goto out; + } + + out: + if (!found) { + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); + return; + } + + if (mr_sas_node->host_node) { + list_for_each_entry_safe(srch_port, hba_port_next, + &mrioc->hba_port_table_list, list) { + if (srch_port != hba_port) + continue; + ioc_info(mrioc, + "removing hba_port entry: %p port: %d from hba_port list\n", + srch_port, srch_port->port_id); + list_del(&hba_port->list); + kfree(hba_port); + break; + } + } + + for (i = 0; i < mr_sas_node->num_phys; i++) { + if (mr_sas_node->phy[i].remote_identify.sas_address == + sas_address) + memset(&mr_sas_node->phy[i].remote_identify, 0, + sizeof(struct sas_identify)); + } + + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); + + if (mrioc->current_event) + mrioc->current_event->pending_at_sml = 1; + + list_for_each_entry_safe(mr_sas_phy, next_phy, + &mr_sas_port->phy_list, port_siblings) { + if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO)) + dev_info(&mr_sas_port->port->dev, + "remove: sas_address(0x%016llx), phy(%d)\n", + (unsigned long long) + mr_sas_port->remote_identify.sas_address, + mr_sas_phy->phy_id); + mr_sas_phy->phy_belongs_to_port = 0; + if (!mrioc->stop_drv_processing) + sas_port_delete_phy(mr_sas_port->port, + mr_sas_phy->phy); + list_del(&mr_sas_phy->port_siblings); + } + if (!mrioc->stop_drv_processing) + sas_port_delete(mr_sas_port->port); + ioc_info(mrioc, "%s: removed sas_address(0x%016llx)\n", + __func__, (unsigned long long)sas_address); + + if (mrioc->current_event) { + mrioc->current_event->pending_at_sml = 0; + if (mrioc->current_event->discard) + mpi3mr_print_device_event_notice(mrioc, false); + } + + kfree(mr_sas_port); +}
Added below helper functions, - Add, update the host phys with STL - Add, remove the device's sas port with STL Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com> --- drivers/scsi/mpi3mr/mpi3mr.h | 13 + drivers/scsi/mpi3mr/mpi3mr_os.c | 2 +- drivers/scsi/mpi3mr/mpi3mr_transport.c | 527 +++++++++++++++++++++++++ 3 files changed, 541 insertions(+), 1 deletion(-)