> On Jul 29, 2022, at 6:16 AM, Sreekanth Reddy <sreekanth.reddy@xxxxxxxxxxxx> wrote: > > Enable and process the Enclosure device add event. > > Signed-off-by: Sreekanth Reddy <sreekanth.reddy@xxxxxxxxxxxx> > --- > drivers/scsi/mpi3mr/mpi3mr.h | 19 +++++ > drivers/scsi/mpi3mr/mpi3mr_fw.c | 4 + > drivers/scsi/mpi3mr/mpi3mr_os.c | 133 +++++++++++++++++++++++++++++++- > 3 files changed, 154 insertions(+), 2 deletions(-) > > diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h > index 8af94d3..542b462 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr.h > +++ b/drivers/scsi/mpi3mr/mpi3mr.h > @@ -461,6 +461,16 @@ struct mpi3mr_throttle_group_info { > atomic_t pend_large_data_sz; > }; > > +/** > + * struct mpi3mr_enclosure_node - enclosure information > + * @list: List of enclosures > + * @pg0: Enclosure page 0; > + */ > +struct mpi3mr_enclosure_node { > + struct list_head list; > + struct mpi3_enclosure_page0 pg0; > +}; > + > /** > * struct tgt_dev_sas_sata - SAS/SATA device specific > * information cached from firmware given data > @@ -535,12 +545,14 @@ union _form_spec_inf { > * @slot: Slot number > * @encl_handle: FW enclosure handle > * @perst_id: FW assigned Persistent ID > + * @devpg0_flag: Device Page0 flag > * @dev_type: SAS/SATA/PCIE device type > * @is_hidden: Should be exposed to upper layers or not > * @host_exposed: Already exposed to host or not > * @io_throttle_enabled: I/O throttling needed or not > * @q_depth: Device specific Queue Depth > * @wwid: World wide ID > + * @enclosure_logical_id: Enclosure logical identifier > * @dev_spec: Device type specific information > * @ref_count: Reference count > */ > @@ -552,12 +564,14 @@ struct mpi3mr_tgt_dev { > u16 slot; > u16 encl_handle; > u16 perst_id; > + u16 devpg0_flag; > u8 dev_type; > u8 is_hidden; > u8 host_exposed; > u8 io_throttle_enabled; > u16 q_depth; > u64 wwid; > + u64 enclosure_logical_id; > union _form_spec_inf dev_spec; > struct kref ref_count; > }; > @@ -877,6 +891,7 @@ 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 > + * @enclosure_list: List of Enclosure objects > */ > struct mpi3mr_ioc { > struct list_head list; > @@ -1053,6 +1068,8 @@ struct mpi3mr_ioc { > void *cfg_page; > dma_addr_t cfg_page_dma; > u16 cfg_page_sz; > + > + struct list_head enclosure_list; > }; > > /** > @@ -1177,6 +1194,8 @@ int mpi3mr_pel_get_seqnum_post(struct mpi3mr_ioc *mrioc, > struct mpi3mr_drv_cmd *drv_cmd); > void mpi3mr_app_save_logdata(struct mpi3mr_ioc *mrioc, char *event_data, > u16 event_data_size); > +struct mpi3mr_enclosure_node *mpi3mr_enclosure_find_by_handle( > + struct mpi3mr_ioc *mrioc, u16 handle); > extern const struct attribute_group *mpi3mr_host_groups[]; > extern const struct attribute_group *mpi3mr_dev_groups[]; > > diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c > index 50e88d4..9c36f52 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c > @@ -244,6 +244,9 @@ static void mpi3mr_print_event_data(struct mpi3mr_ioc *mrioc, > case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE: > desc = "Enclosure Device Status Change"; > break; > + case MPI3_EVENT_ENCL_DEVICE_ADDED: > + desc = "Enclosure Added"; > + break; > case MPI3_EVENT_HARD_RESET_RECEIVED: > desc = "Hard Reset Received"; > break; > @@ -3660,6 +3663,7 @@ static int mpi3mr_enable_events(struct mpi3mr_ioc *mrioc) > mpi3mr_unmask_events(mrioc, MPI3_EVENT_DEVICE_INFO_CHANGED); > mpi3mr_unmask_events(mrioc, MPI3_EVENT_DEVICE_STATUS_CHANGE); > mpi3mr_unmask_events(mrioc, MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE); > + mpi3mr_unmask_events(mrioc, MPI3_EVENT_ENCL_DEVICE_ADDED); > mpi3mr_unmask_events(mrioc, MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST); > mpi3mr_unmask_events(mrioc, MPI3_EVENT_SAS_DISCOVERY); > mpi3mr_unmask_events(mrioc, MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR); > diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c > index 40bed22..ca718cb 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_os.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c > @@ -1026,6 +1026,7 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc, > { > u16 flags = 0; > struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data = NULL; > + struct mpi3mr_enclosure_node *enclosure_dev = NULL; > u8 prot_mask = 0; > > tgtdev->perst_id = le16_to_cpu(dev_pg0->persistent_id); > @@ -1036,8 +1037,17 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc, > tgtdev->slot = le16_to_cpu(dev_pg0->slot); > tgtdev->q_depth = le16_to_cpu(dev_pg0->queue_depth); > tgtdev->wwid = le64_to_cpu(dev_pg0->wwid); > + tgtdev->devpg0_flag = le16_to_cpu(dev_pg0->flags); > + > + if (tgtdev->encl_handle) > + enclosure_dev = mpi3mr_enclosure_find_by_handle(mrioc, > + tgtdev->encl_handle); > + if (enclosure_dev) > + tgtdev->enclosure_logical_id = le64_to_cpu( > + enclosure_dev->pg0.enclosure_logical_id); > + > + flags = tgtdev->devpg0_flag; > > - flags = le16_to_cpu(dev_pg0->flags); > tgtdev->is_hidden = (flags & MPI3_DEVICE0_FLAGS_HIDDEN); > > if (is_added == true) > @@ -1265,6 +1275,116 @@ out: > mpi3mr_tgtdev_put(tgtdev); > } > > +/** > + * mpi3mr_enclosure_find_by_handle - enclosure search by handle > + * @mrioc: Adapter instance reference > + * @handle: Firmware device handle of the enclosure > + * > + * This searches for enclosure device based on handle, then returns the > + * enclosure object. > + * > + * Return: Enclosure object reference or NULL > + */ > +struct mpi3mr_enclosure_node *mpi3mr_enclosure_find_by_handle( > + struct mpi3mr_ioc *mrioc, u16 handle) > +{ > + struct mpi3mr_enclosure_node *enclosure_dev, *r = NULL; > + > + list_for_each_entry(enclosure_dev, &mrioc->enclosure_list, list) { > + if (le16_to_cpu(enclosure_dev->pg0.enclosure_handle) != handle) > + continue; > + r = enclosure_dev; > + goto out; > + } > +out: > + return r; > +} > + > +/** > + * mpi3mr_encldev_add_chg_evt_debug - debug for enclosure event > + * @mrioc: Adapter instance reference > + * @encl_pg0: Enclosure page 0. > + * @is_added: Added event or not > + * > + * Return nothing. > + */ > +static void mpi3mr_encldev_add_chg_evt_debug(struct mpi3mr_ioc *mrioc, > + struct mpi3_enclosure_page0 *encl_pg0, u8 is_added) > +{ > + char *reason_str = NULL; > + > + if (!(mrioc->logging_level & MPI3_DEBUG_EVENT_WORK_TASK)) > + return; > + > + if (is_added) > + reason_str = "enclosure added"; > + else > + reason_str = "enclosure dev status changed"; > + > + ioc_info(mrioc, > + "%s: handle(0x%04x), enclosure logical id(0x%016llx)\n", > + reason_str, le16_to_cpu(encl_pg0->enclosure_handle), > + (unsigned long long)le64_to_cpu(encl_pg0->enclosure_logical_id)); > + ioc_info(mrioc, > + "number of slots(%d), port(%d), flags(0x%04x), present(%d)\n", > + le16_to_cpu(encl_pg0->num_slots), encl_pg0->io_unit_port, > + le16_to_cpu(encl_pg0->flags), > + ((le16_to_cpu(encl_pg0->flags) & > + MPI3_ENCLS0_FLAGS_ENCL_DEV_PRESENT_MASK) >> 4)); > +} > + > +/** > + * mpi3mr_encldev_add_chg_evt_bh - Enclosure evt bottomhalf > + * @mrioc: Adapter instance reference > + * @fwevt: Firmware event reference > + * > + * Prints information about the Enclosure device status or > + * Enclosure add events if logging is enabled and add or remove > + * the enclosure from the controller's internal list of > + * enclosures. > + * > + * Return: Nothing. > + */ > +static void mpi3mr_encldev_add_chg_evt_bh(struct mpi3mr_ioc *mrioc, > + struct mpi3mr_fwevt *fwevt) > +{ > + struct mpi3mr_enclosure_node *enclosure_dev = NULL; > + struct mpi3_enclosure_page0 *encl_pg0; > + u16 encl_handle; > + u8 added, present; > + > + encl_pg0 = (struct mpi3_enclosure_page0 *) fwevt->event_data; > + added = (fwevt->event_id == MPI3_EVENT_ENCL_DEVICE_ADDED) ? 1 : 0; > + mpi3mr_encldev_add_chg_evt_debug(mrioc, encl_pg0, added); > + > + > + encl_handle = le16_to_cpu(encl_pg0->enclosure_handle); > + present = ((le16_to_cpu(encl_pg0->flags) & > + MPI3_ENCLS0_FLAGS_ENCL_DEV_PRESENT_MASK) >> 4); > + > + if (encl_handle) > + enclosure_dev = mpi3mr_enclosure_find_by_handle(mrioc, > + encl_handle); > + if (!enclosure_dev && present) { > + enclosure_dev = > + kzalloc(sizeof(struct mpi3mr_enclosure_node), > + GFP_KERNEL); > + if (!enclosure_dev) > + return; > + list_add_tail(&enclosure_dev->list, > + &mrioc->enclosure_list); > + } > + if (enclosure_dev) { > + if (!present) { > + list_del(&enclosure_dev->list); > + kfree(enclosure_dev); > + } else > + memcpy(&enclosure_dev->pg0, encl_pg0, > + sizeof(enclosure_dev->pg0)); > + > + } > +} > + > /** > * mpi3mr_sastopochg_evt_debug - SASTopoChange details > * @mrioc: Adapter instance reference > @@ -1641,6 +1761,13 @@ static void mpi3mr_fwevt_bh(struct mpi3mr_ioc *mrioc, > mpi3mr_devstatuschg_evt_bh(mrioc, fwevt); > break; > } > + case MPI3_EVENT_ENCL_DEVICE_ADDED: > + case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE: > + { > + mpi3mr_encldev_add_chg_evt_bh(mrioc, fwevt); > + break; > + } > + > case MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST: > { > mpi3mr_sastopochg_evt_bh(mrioc, fwevt); > @@ -2502,6 +2629,8 @@ void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc, > } > case MPI3_EVENT_DEVICE_INFO_CHANGED: > case MPI3_EVENT_LOG_DATA: > + case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE: > + case MPI3_EVENT_ENCL_DEVICE_ADDED: > { > process_evt_bh = 1; > break; > @@ -2516,7 +2645,6 @@ void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc, > mpi3mr_cablemgmt_evt_th(mrioc, event_reply); > break; > } > - case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE: > case MPI3_EVENT_SAS_DISCOVERY: > case MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR: > case MPI3_EVENT_SAS_BROADCAST_PRIMITIVE: > @@ -4569,6 +4697,7 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) > 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->enclosure_list); > > mutex_init(&mrioc->reset_mutex); > mpi3mr_init_drv_cmd(&mrioc->init_cmds, MPI3MR_HOSTTAG_INITCMDS); > -- > 2.27.0 > Reviewed-by: Himanshu Madhani <himanshu.madhani@xxxxxxxxxx> -- Himanshu Madhani Oracle Linux Engineering