diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/mpi3mr/mpi3mr.h | 8 | ||||
-rw-r--r-- | drivers/scsi/mpi3mr/mpi3mr_os.c | 48 |
2 files changed, 41 insertions, 15 deletions
diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 23de2603e71f..4cb00bdb0039 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -652,7 +652,11 @@ union _form_spec_inf { struct tgt_dev_vd vd_inf; }; - +enum mpi3mr_dev_state { + MPI3MR_DEV_CREATED = 1, + MPI3MR_DEV_REMOVE_HS_STARTED = 2, + MPI3MR_DEV_DELETED = 3, +}; /** * struct mpi3mr_tgt_dev - target device data structure @@ -676,6 +680,7 @@ union _form_spec_inf { * @enclosure_logical_id: Enclosure logical identifier * @dev_spec: Device type specific information * @ref_count: Reference count + * @state: device state */ struct mpi3mr_tgt_dev { struct list_head list; @@ -697,6 +702,7 @@ struct mpi3mr_tgt_dev { u64 enclosure_logical_id; union _form_spec_inf dev_spec; struct kref ref_count; + enum mpi3mr_dev_state state; }; /** diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index 6eaeba41072c..7ebd00dfd396 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -652,6 +652,7 @@ static void mpi3mr_tgtdev_add_to_list(struct mpi3mr_ioc *mrioc, mpi3mr_tgtdev_get(tgtdev); INIT_LIST_HEAD(&tgtdev->list); list_add_tail(&tgtdev->list, &mrioc->tgtdev_list); + tgtdev->state = MPI3MR_DEV_CREATED; spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); } @@ -659,20 +660,25 @@ static void mpi3mr_tgtdev_add_to_list(struct mpi3mr_ioc *mrioc, * mpi3mr_tgtdev_del_from_list -Delete tgtdevice from the list * @mrioc: Adapter instance reference * @tgtdev: Target device + * @must_delete: Must delete the target device from the list irrespective + * of the device state. * * Remove the target device from the target device list * * Return: Nothing. */ static void mpi3mr_tgtdev_del_from_list(struct mpi3mr_ioc *mrioc, - struct mpi3mr_tgt_dev *tgtdev) + struct mpi3mr_tgt_dev *tgtdev, bool must_delete) { unsigned long flags; spin_lock_irqsave(&mrioc->tgtdev_lock, flags); - if (!list_empty(&tgtdev->list)) { - list_del_init(&tgtdev->list); - mpi3mr_tgtdev_put(tgtdev); + if ((tgtdev->state == MPI3MR_DEV_REMOVE_HS_STARTED) || (must_delete == true)) { + if (!list_empty(&tgtdev->list)) { + list_del_init(&tgtdev->list); + tgtdev->state = MPI3MR_DEV_DELETED; + mpi3mr_tgtdev_put(tgtdev); + } } spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); } @@ -1036,7 +1042,7 @@ void mpi3mr_rfresh_tgtdevs(struct mpi3mr_ioc *mrioc) tgtdev->perst_id); if (tgtdev->host_exposed) mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev); - mpi3mr_tgtdev_del_from_list(mrioc, tgtdev); + mpi3mr_tgtdev_del_from_list(mrioc, tgtdev, true); mpi3mr_tgtdev_put(tgtdev); } } @@ -1281,12 +1287,12 @@ static void mpi3mr_devstatuschg_evt_bh(struct mpi3mr_ioc *mrioc, if (!tgtdev->host_exposed) mpi3mr_report_tgtdev_to_host(mrioc, tgtdev->perst_id); } - if (tgtdev->starget && tgtdev->starget->hostdata) { - if (delete) - mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev); - } + + if (delete) + mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev); + if (cleanup) { - mpi3mr_tgtdev_del_from_list(mrioc, tgtdev); + mpi3mr_tgtdev_del_from_list(mrioc, tgtdev, false); mpi3mr_tgtdev_put(tgtdev); } @@ -1604,7 +1610,7 @@ static void mpi3mr_sastopochg_evt_bh(struct mpi3mr_ioc *mrioc, case MPI3_EVENT_SAS_TOPO_PHY_RC_TARG_NOT_RESPONDING: if (tgtdev->host_exposed) mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev); - mpi3mr_tgtdev_del_from_list(mrioc, tgtdev); + mpi3mr_tgtdev_del_from_list(mrioc, tgtdev, false); mpi3mr_tgtdev_put(tgtdev); break; case MPI3_EVENT_SAS_TOPO_PHY_RC_RESPONDING: @@ -1762,7 +1768,7 @@ static void mpi3mr_pcietopochg_evt_bh(struct mpi3mr_ioc *mrioc, case MPI3_EVENT_PCIE_TOPO_PS_NOT_RESPONDING: if (tgtdev->host_exposed) mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev); - mpi3mr_tgtdev_del_from_list(mrioc, tgtdev); + mpi3mr_tgtdev_del_from_list(mrioc, tgtdev, false); mpi3mr_tgtdev_put(tgtdev); break; default: @@ -2016,12 +2022,18 @@ static int mpi3mr_create_tgtdev(struct mpi3mr_ioc *mrioc, int retval = 0; struct mpi3mr_tgt_dev *tgtdev = NULL; u16 perst_id = 0; + unsigned long flags; perst_id = le16_to_cpu(dev_pg0->persistent_id); if (perst_id == MPI3_DEVICE0_PERSISTENTID_INVALID) return retval; - tgtdev = mpi3mr_get_tgtdev_by_perst_id(mrioc, perst_id); + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); + tgtdev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, perst_id); + if (tgtdev) + tgtdev->state = MPI3MR_DEV_CREATED; + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); + if (tgtdev) { mpi3mr_update_tgtdev(mrioc, tgtdev, dev_pg0, true); mpi3mr_tgtdev_put(tgtdev); @@ -2219,6 +2231,14 @@ static void mpi3mr_dev_rmhs_send_tm(struct mpi3mr_ioc *mrioc, u16 handle, u8 retrycount = 5; struct mpi3mr_drv_cmd *drv_cmd = cmdparam; struct delayed_dev_rmhs_node *delayed_dev_rmhs = NULL; + struct mpi3mr_tgt_dev *tgtdev = NULL; + unsigned long flags; + + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); + tgtdev = __mpi3mr_get_tgtdev_by_handle(mrioc, handle); + if (tgtdev && (iou_rc == MPI3_CTRL_OP_REMOVE_DEVICE)) + tgtdev->state = MPI3MR_DEV_REMOVE_HS_STARTED; + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); if (drv_cmd) goto issue_cmd; @@ -5108,7 +5128,7 @@ static void mpi3mr_remove(struct pci_dev *pdev) list_for_each_entry_safe(tgtdev, tgtdev_next, &mrioc->tgtdev_list, list) { mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev); - mpi3mr_tgtdev_del_from_list(mrioc, tgtdev); + mpi3mr_tgtdev_del_from_list(mrioc, tgtdev, true); mpi3mr_tgtdev_put(tgtdev); } mpi3mr_stop_watchdog(mrioc); |