diff options
Diffstat (limited to 'drivers/scsi/mpt2sas')
| -rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.c | 6 | ||||
| -rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.h | 41 | ||||
| -rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_ctl.c | 38 | ||||
| -rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_scsih.c | 605 | ||||
| -rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_transport.c | 12 |
5 files changed, 518 insertions, 184 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 6dec7cff316f..c167911221e9 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c | |||
| @@ -112,9 +112,12 @@ _scsih_set_fwfault_debug(const char *val, struct kernel_param *kp) | |||
| 112 | if (ret) | 112 | if (ret) |
| 113 | return ret; | 113 | return ret; |
| 114 | 114 | ||
| 115 | /* global ioc spinlock to protect controller list on list operations */ | ||
| 115 | printk(KERN_INFO "setting fwfault_debug(%d)\n", mpt2sas_fwfault_debug); | 116 | printk(KERN_INFO "setting fwfault_debug(%d)\n", mpt2sas_fwfault_debug); |
| 117 | spin_lock(&gioc_lock); | ||
| 116 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) | 118 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) |
| 117 | ioc->fwfault_debug = mpt2sas_fwfault_debug; | 119 | ioc->fwfault_debug = mpt2sas_fwfault_debug; |
| 120 | spin_unlock(&gioc_lock); | ||
| 118 | return 0; | 121 | return 0; |
| 119 | } | 122 | } |
| 120 | 123 | ||
| @@ -4437,6 +4440,8 @@ mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc) | |||
| 4437 | dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | 4440 | dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, |
| 4438 | __func__)); | 4441 | __func__)); |
| 4439 | 4442 | ||
| 4443 | /* synchronizing freeing resource with pci_access_mutex lock */ | ||
| 4444 | mutex_lock(&ioc->pci_access_mutex); | ||
| 4440 | if (ioc->chip_phys && ioc->chip) { | 4445 | if (ioc->chip_phys && ioc->chip) { |
| 4441 | _base_mask_interrupts(ioc); | 4446 | _base_mask_interrupts(ioc); |
| 4442 | ioc->shost_recovery = 1; | 4447 | ioc->shost_recovery = 1; |
| @@ -4456,6 +4461,7 @@ mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc) | |||
| 4456 | pci_disable_pcie_error_reporting(pdev); | 4461 | pci_disable_pcie_error_reporting(pdev); |
| 4457 | pci_disable_device(pdev); | 4462 | pci_disable_device(pdev); |
| 4458 | } | 4463 | } |
| 4464 | mutex_unlock(&ioc->pci_access_mutex); | ||
| 4459 | return; | 4465 | return; |
| 4460 | } | 4466 | } |
| 4461 | 4467 | ||
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index caff8d10cca4..97ea360c6920 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h | |||
| @@ -238,6 +238,7 @@ | |||
| 238 | * @flags: MPT_TARGET_FLAGS_XXX flags | 238 | * @flags: MPT_TARGET_FLAGS_XXX flags |
| 239 | * @deleted: target flaged for deletion | 239 | * @deleted: target flaged for deletion |
| 240 | * @tm_busy: target is busy with TM request. | 240 | * @tm_busy: target is busy with TM request. |
| 241 | * @sdev: The sas_device associated with this target | ||
| 241 | */ | 242 | */ |
| 242 | struct MPT2SAS_TARGET { | 243 | struct MPT2SAS_TARGET { |
| 243 | struct scsi_target *starget; | 244 | struct scsi_target *starget; |
| @@ -248,6 +249,7 @@ struct MPT2SAS_TARGET { | |||
| 248 | u32 flags; | 249 | u32 flags; |
| 249 | u8 deleted; | 250 | u8 deleted; |
| 250 | u8 tm_busy; | 251 | u8 tm_busy; |
| 252 | struct _sas_device *sdev; | ||
| 251 | }; | 253 | }; |
| 252 | 254 | ||
| 253 | 255 | ||
| @@ -376,8 +378,24 @@ struct _sas_device { | |||
| 376 | u8 phy; | 378 | u8 phy; |
| 377 | u8 responding; | 379 | u8 responding; |
| 378 | u8 pfa_led_on; | 380 | u8 pfa_led_on; |
| 381 | struct kref refcount; | ||
| 379 | }; | 382 | }; |
| 380 | 383 | ||
| 384 | static inline void sas_device_get(struct _sas_device *s) | ||
| 385 | { | ||
| 386 | kref_get(&s->refcount); | ||
| 387 | } | ||
| 388 | |||
| 389 | static inline void sas_device_free(struct kref *r) | ||
| 390 | { | ||
| 391 | kfree(container_of(r, struct _sas_device, refcount)); | ||
| 392 | } | ||
| 393 | |||
| 394 | static inline void sas_device_put(struct _sas_device *s) | ||
| 395 | { | ||
| 396 | kref_put(&s->refcount, sas_device_free); | ||
| 397 | } | ||
| 398 | |||
| 381 | /** | 399 | /** |
| 382 | * struct _raid_device - raid volume link list | 400 | * struct _raid_device - raid volume link list |
| 383 | * @list: sas device list | 401 | * @list: sas device list |
| @@ -799,6 +817,12 @@ typedef void (*MPT2SAS_FLUSH_RUNNING_CMDS)(struct MPT2SAS_ADAPTER *ioc); | |||
| 799 | * @delayed_tr_list: target reset link list | 817 | * @delayed_tr_list: target reset link list |
| 800 | * @delayed_tr_volume_list: volume target reset link list | 818 | * @delayed_tr_volume_list: volume target reset link list |
| 801 | * @@temp_sensors_count: flag to carry the number of temperature sensors | 819 | * @@temp_sensors_count: flag to carry the number of temperature sensors |
| 820 | * @pci_access_mutex: Mutex to synchronize ioctl,sysfs show path and | ||
| 821 | * pci resource handling. PCI resource freeing will lead to free | ||
| 822 | * vital hardware/memory resource, which might be in use by cli/sysfs | ||
| 823 | * path functions resulting in Null pointer reference followed by kernel | ||
| 824 | * crash. To avoid the above race condition we use mutex syncrhonization | ||
| 825 | * which ensures the syncrhonization between cli/sysfs_show path | ||
| 802 | */ | 826 | */ |
| 803 | struct MPT2SAS_ADAPTER { | 827 | struct MPT2SAS_ADAPTER { |
| 804 | struct list_head list; | 828 | struct list_head list; |
| @@ -1015,6 +1039,7 @@ struct MPT2SAS_ADAPTER { | |||
| 1015 | u8 mfg_pg10_hide_flag; | 1039 | u8 mfg_pg10_hide_flag; |
| 1016 | u8 hide_drives; | 1040 | u8 hide_drives; |
| 1017 | 1041 | ||
| 1042 | struct mutex pci_access_mutex; | ||
| 1018 | }; | 1043 | }; |
| 1019 | 1044 | ||
| 1020 | typedef u8 (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | 1045 | typedef u8 (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
| @@ -1023,6 +1048,17 @@ typedef u8 (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
| 1023 | 1048 | ||
| 1024 | /* base shared API */ | 1049 | /* base shared API */ |
| 1025 | extern struct list_head mpt2sas_ioc_list; | 1050 | extern struct list_head mpt2sas_ioc_list; |
| 1051 | /* spinlock on list operations over IOCs | ||
| 1052 | * Case: when multiple warpdrive cards(IOCs) are in use | ||
| 1053 | * Each IOC will added to the ioc list stucture on initialization. | ||
| 1054 | * Watchdog threads run at regular intervals to check IOC for any | ||
| 1055 | * fault conditions which will trigger the dead_ioc thread to | ||
| 1056 | * deallocate pci resource, resulting deleting the IOC netry from list, | ||
| 1057 | * this deletion need to protected by spinlock to enusre that | ||
| 1058 | * ioc removal is syncrhonized, if not synchronized it might lead to | ||
| 1059 | * list_del corruption as the ioc list is traversed in cli path | ||
| 1060 | */ | ||
| 1061 | extern spinlock_t gioc_lock; | ||
| 1026 | void mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc); | 1062 | void mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc); |
| 1027 | void mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc); | 1063 | void mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc); |
| 1028 | 1064 | ||
| @@ -1095,11 +1131,12 @@ struct _sas_node *mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER * | |||
| 1095 | u16 handle); | 1131 | u16 handle); |
| 1096 | struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER | 1132 | struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER |
| 1097 | *ioc, u64 sas_address); | 1133 | *ioc, u64 sas_address); |
| 1098 | struct _sas_device *mpt2sas_scsih_sas_device_find_by_sas_address( | 1134 | struct _sas_device *mpt2sas_get_sdev_by_addr( |
| 1135 | struct MPT2SAS_ADAPTER *ioc, u64 sas_address); | ||
| 1136 | struct _sas_device *__mpt2sas_get_sdev_by_addr( | ||
| 1099 | struct MPT2SAS_ADAPTER *ioc, u64 sas_address); | 1137 | struct MPT2SAS_ADAPTER *ioc, u64 sas_address); |
| 1100 | 1138 | ||
| 1101 | void mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc); | 1139 | void mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc); |
| 1102 | |||
| 1103 | void mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase); | 1140 | void mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase); |
| 1104 | 1141 | ||
| 1105 | /* config shared API */ | 1142 | /* config shared API */ |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index 4e509604b571..3694b63bd993 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c | |||
| @@ -427,13 +427,16 @@ static int | |||
| 427 | _ctl_verify_adapter(int ioc_number, struct MPT2SAS_ADAPTER **iocpp) | 427 | _ctl_verify_adapter(int ioc_number, struct MPT2SAS_ADAPTER **iocpp) |
| 428 | { | 428 | { |
| 429 | struct MPT2SAS_ADAPTER *ioc; | 429 | struct MPT2SAS_ADAPTER *ioc; |
| 430 | 430 | /* global ioc lock to protect controller on list operations */ | |
| 431 | spin_lock(&gioc_lock); | ||
| 431 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) { | 432 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) { |
| 432 | if (ioc->id != ioc_number) | 433 | if (ioc->id != ioc_number) |
| 433 | continue; | 434 | continue; |
| 435 | spin_unlock(&gioc_lock); | ||
| 434 | *iocpp = ioc; | 436 | *iocpp = ioc; |
| 435 | return ioc_number; | 437 | return ioc_number; |
| 436 | } | 438 | } |
| 439 | spin_unlock(&gioc_lock); | ||
| 437 | *iocpp = NULL; | 440 | *iocpp = NULL; |
| 438 | return -1; | 441 | return -1; |
| 439 | } | 442 | } |
| @@ -522,10 +525,15 @@ _ctl_poll(struct file *filep, poll_table *wait) | |||
| 522 | 525 | ||
| 523 | poll_wait(filep, &ctl_poll_wait, wait); | 526 | poll_wait(filep, &ctl_poll_wait, wait); |
| 524 | 527 | ||
| 528 | /* global ioc lock to protect controller on list operations */ | ||
| 529 | spin_lock(&gioc_lock); | ||
| 525 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) { | 530 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) { |
| 526 | if (ioc->aen_event_read_flag) | 531 | if (ioc->aen_event_read_flag) { |
| 532 | spin_unlock(&gioc_lock); | ||
| 527 | return POLLIN | POLLRDNORM; | 533 | return POLLIN | POLLRDNORM; |
| 534 | } | ||
| 528 | } | 535 | } |
| 536 | spin_unlock(&gioc_lock); | ||
| 529 | return 0; | 537 | return 0; |
| 530 | } | 538 | } |
| 531 | 539 | ||
| @@ -2168,16 +2176,23 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg, | |||
| 2168 | 2176 | ||
| 2169 | if (_ctl_verify_adapter(ioctl_header.ioc_number, &ioc) == -1 || !ioc) | 2177 | if (_ctl_verify_adapter(ioctl_header.ioc_number, &ioc) == -1 || !ioc) |
| 2170 | return -ENODEV; | 2178 | return -ENODEV; |
| 2179 | /* pci_access_mutex lock acquired by ioctl path */ | ||
| 2180 | mutex_lock(&ioc->pci_access_mutex); | ||
| 2171 | if (ioc->shost_recovery || ioc->pci_error_recovery || | 2181 | if (ioc->shost_recovery || ioc->pci_error_recovery || |
| 2172 | ioc->is_driver_loading) | 2182 | ioc->is_driver_loading || ioc->remove_host) { |
| 2173 | return -EAGAIN; | 2183 | ret = -EAGAIN; |
| 2184 | goto out_unlock_pciaccess; | ||
| 2185 | } | ||
| 2174 | 2186 | ||
| 2175 | state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING; | 2187 | state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING; |
| 2176 | if (state == NON_BLOCKING) { | 2188 | if (state == NON_BLOCKING) { |
| 2177 | if (!mutex_trylock(&ioc->ctl_cmds.mutex)) | 2189 | if (!mutex_trylock(&ioc->ctl_cmds.mutex)) { |
| 2178 | return -EAGAIN; | 2190 | ret = -EAGAIN; |
| 2191 | goto out_unlock_pciaccess; | ||
| 2192 | } | ||
| 2179 | } else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) { | 2193 | } else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) { |
| 2180 | return -ERESTARTSYS; | 2194 | ret = -ERESTARTSYS; |
| 2195 | goto out_unlock_pciaccess; | ||
| 2181 | } | 2196 | } |
| 2182 | 2197 | ||
| 2183 | switch (cmd) { | 2198 | switch (cmd) { |
| @@ -2258,6 +2273,8 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg, | |||
| 2258 | } | 2273 | } |
| 2259 | 2274 | ||
| 2260 | mutex_unlock(&ioc->ctl_cmds.mutex); | 2275 | mutex_unlock(&ioc->ctl_cmds.mutex); |
| 2276 | out_unlock_pciaccess: | ||
| 2277 | mutex_unlock(&ioc->pci_access_mutex); | ||
| 2261 | return ret; | 2278 | return ret; |
| 2262 | } | 2279 | } |
| 2263 | 2280 | ||
| @@ -2711,6 +2728,12 @@ _ctl_BRM_status_show(struct device *cdev, struct device_attribute *attr, | |||
| 2711 | "warpdrive\n", ioc->name, __func__); | 2728 | "warpdrive\n", ioc->name, __func__); |
| 2712 | goto out; | 2729 | goto out; |
| 2713 | } | 2730 | } |
| 2731 | /* pci_access_mutex lock acquired by sysfs show path */ | ||
| 2732 | mutex_lock(&ioc->pci_access_mutex); | ||
| 2733 | if (ioc->pci_error_recovery || ioc->remove_host) { | ||
| 2734 | mutex_unlock(&ioc->pci_access_mutex); | ||
| 2735 | return 0; | ||
| 2736 | } | ||
| 2714 | 2737 | ||
| 2715 | /* allocate upto GPIOVal 36 entries */ | 2738 | /* allocate upto GPIOVal 36 entries */ |
| 2716 | sz = offsetof(Mpi2IOUnitPage3_t, GPIOVal) + (sizeof(u16) * 36); | 2739 | sz = offsetof(Mpi2IOUnitPage3_t, GPIOVal) + (sizeof(u16) * 36); |
| @@ -2749,6 +2772,7 @@ _ctl_BRM_status_show(struct device *cdev, struct device_attribute *attr, | |||
| 2749 | 2772 | ||
| 2750 | out: | 2773 | out: |
| 2751 | kfree(io_unit_pg3); | 2774 | kfree(io_unit_pg3); |
| 2775 | mutex_unlock(&ioc->pci_access_mutex); | ||
| 2752 | return rc; | 2776 | return rc; |
| 2753 | } | 2777 | } |
| 2754 | static DEVICE_ATTR(BRM_status, S_IRUGO, _ctl_BRM_status_show, NULL); | 2778 | static DEVICE_ATTR(BRM_status, S_IRUGO, _ctl_BRM_status_show, NULL); |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 3f26147bbc64..0ad09b2bff9c 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
| @@ -79,7 +79,8 @@ static int _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time); | |||
| 79 | 79 | ||
| 80 | /* global parameters */ | 80 | /* global parameters */ |
| 81 | LIST_HEAD(mpt2sas_ioc_list); | 81 | LIST_HEAD(mpt2sas_ioc_list); |
| 82 | 82 | /* global ioc lock for list operations */ | |
| 83 | DEFINE_SPINLOCK(gioc_lock); | ||
| 83 | /* local parameters */ | 84 | /* local parameters */ |
| 84 | static u8 scsi_io_cb_idx = -1; | 85 | static u8 scsi_io_cb_idx = -1; |
| 85 | static u8 tm_cb_idx = -1; | 86 | static u8 tm_cb_idx = -1; |
| @@ -176,9 +177,37 @@ struct fw_event_work { | |||
| 176 | u8 VP_ID; | 177 | u8 VP_ID; |
| 177 | u8 ignore; | 178 | u8 ignore; |
| 178 | u16 event; | 179 | u16 event; |
| 180 | struct kref refcount; | ||
| 179 | char event_data[0] __aligned(4); | 181 | char event_data[0] __aligned(4); |
| 180 | }; | 182 | }; |
| 181 | 183 | ||
| 184 | static void fw_event_work_free(struct kref *r) | ||
| 185 | { | ||
| 186 | kfree(container_of(r, struct fw_event_work, refcount)); | ||
| 187 | } | ||
| 188 | |||
| 189 | static void fw_event_work_get(struct fw_event_work *fw_work) | ||
| 190 | { | ||
| 191 | kref_get(&fw_work->refcount); | ||
| 192 | } | ||
| 193 | |||
| 194 | static void fw_event_work_put(struct fw_event_work *fw_work) | ||
| 195 | { | ||
| 196 | kref_put(&fw_work->refcount, fw_event_work_free); | ||
| 197 | } | ||
| 198 | |||
| 199 | static struct fw_event_work *alloc_fw_event_work(int len) | ||
| 200 | { | ||
| 201 | struct fw_event_work *fw_event; | ||
| 202 | |||
| 203 | fw_event = kzalloc(sizeof(*fw_event) + len, GFP_ATOMIC); | ||
| 204 | if (!fw_event) | ||
| 205 | return NULL; | ||
| 206 | |||
| 207 | kref_init(&fw_event->refcount); | ||
| 208 | return fw_event; | ||
| 209 | } | ||
| 210 | |||
| 182 | /* raid transport support */ | 211 | /* raid transport support */ |
| 183 | static struct raid_template *mpt2sas_raid_template; | 212 | static struct raid_template *mpt2sas_raid_template; |
| 184 | 213 | ||
| @@ -293,8 +322,10 @@ _scsih_set_debug_level(const char *val, struct kernel_param *kp) | |||
| 293 | return ret; | 322 | return ret; |
| 294 | 323 | ||
| 295 | printk(KERN_INFO "setting logging_level(0x%08x)\n", logging_level); | 324 | printk(KERN_INFO "setting logging_level(0x%08x)\n", logging_level); |
| 325 | spin_lock(&gioc_lock); | ||
| 296 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) | 326 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) |
| 297 | ioc->logging_level = logging_level; | 327 | ioc->logging_level = logging_level; |
| 328 | spin_unlock(&gioc_lock); | ||
| 298 | return 0; | 329 | return 0; |
| 299 | } | 330 | } |
| 300 | module_param_call(logging_level, _scsih_set_debug_level, param_get_int, | 331 | module_param_call(logging_level, _scsih_set_debug_level, param_get_int, |
| @@ -526,8 +557,61 @@ _scsih_determine_boot_device(struct MPT2SAS_ADAPTER *ioc, | |||
| 526 | } | 557 | } |
| 527 | } | 558 | } |
| 528 | 559 | ||
| 560 | static struct _sas_device * | ||
| 561 | __mpt2sas_get_sdev_from_target(struct MPT2SAS_ADAPTER *ioc, | ||
| 562 | struct MPT2SAS_TARGET *tgt_priv) | ||
| 563 | { | ||
| 564 | struct _sas_device *ret; | ||
| 565 | |||
| 566 | assert_spin_locked(&ioc->sas_device_lock); | ||
| 567 | |||
| 568 | ret = tgt_priv->sdev; | ||
| 569 | if (ret) | ||
| 570 | sas_device_get(ret); | ||
| 571 | |||
| 572 | return ret; | ||
| 573 | } | ||
| 574 | |||
| 575 | static struct _sas_device * | ||
| 576 | mpt2sas_get_sdev_from_target(struct MPT2SAS_ADAPTER *ioc, | ||
| 577 | struct MPT2SAS_TARGET *tgt_priv) | ||
| 578 | { | ||
| 579 | struct _sas_device *ret; | ||
| 580 | unsigned long flags; | ||
| 581 | |||
| 582 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 583 | ret = __mpt2sas_get_sdev_from_target(ioc, tgt_priv); | ||
| 584 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 585 | |||
| 586 | return ret; | ||
| 587 | } | ||
| 588 | |||
| 589 | |||
| 590 | struct _sas_device * | ||
| 591 | __mpt2sas_get_sdev_by_addr(struct MPT2SAS_ADAPTER *ioc, | ||
| 592 | u64 sas_address) | ||
| 593 | { | ||
| 594 | struct _sas_device *sas_device; | ||
| 595 | |||
| 596 | assert_spin_locked(&ioc->sas_device_lock); | ||
| 597 | |||
| 598 | list_for_each_entry(sas_device, &ioc->sas_device_list, list) | ||
| 599 | if (sas_device->sas_address == sas_address) | ||
| 600 | goto found_device; | ||
| 601 | |||
| 602 | list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) | ||
| 603 | if (sas_device->sas_address == sas_address) | ||
| 604 | goto found_device; | ||
| 605 | |||
| 606 | return NULL; | ||
| 607 | |||
| 608 | found_device: | ||
| 609 | sas_device_get(sas_device); | ||
| 610 | return sas_device; | ||
| 611 | } | ||
| 612 | |||
| 529 | /** | 613 | /** |
| 530 | * mpt2sas_scsih_sas_device_find_by_sas_address - sas device search | 614 | * mpt2sas_get_sdev_by_addr - sas device search |
| 531 | * @ioc: per adapter object | 615 | * @ioc: per adapter object |
| 532 | * @sas_address: sas address | 616 | * @sas_address: sas address |
| 533 | * Context: Calling function should acquire ioc->sas_device_lock | 617 | * Context: Calling function should acquire ioc->sas_device_lock |
| @@ -536,24 +620,44 @@ _scsih_determine_boot_device(struct MPT2SAS_ADAPTER *ioc, | |||
| 536 | * object. | 620 | * object. |
| 537 | */ | 621 | */ |
| 538 | struct _sas_device * | 622 | struct _sas_device * |
| 539 | mpt2sas_scsih_sas_device_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc, | 623 | mpt2sas_get_sdev_by_addr(struct MPT2SAS_ADAPTER *ioc, |
| 540 | u64 sas_address) | 624 | u64 sas_address) |
| 541 | { | 625 | { |
| 542 | struct _sas_device *sas_device; | 626 | struct _sas_device *sas_device; |
| 627 | unsigned long flags; | ||
| 628 | |||
| 629 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 630 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, | ||
| 631 | sas_address); | ||
| 632 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 633 | |||
| 634 | return sas_device; | ||
| 635 | } | ||
| 636 | |||
| 637 | static struct _sas_device * | ||
| 638 | __mpt2sas_get_sdev_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 639 | { | ||
| 640 | struct _sas_device *sas_device; | ||
| 641 | |||
| 642 | assert_spin_locked(&ioc->sas_device_lock); | ||
| 543 | 643 | ||
| 544 | list_for_each_entry(sas_device, &ioc->sas_device_list, list) | 644 | list_for_each_entry(sas_device, &ioc->sas_device_list, list) |
| 545 | if (sas_device->sas_address == sas_address) | 645 | if (sas_device->handle == handle) |
| 546 | return sas_device; | 646 | goto found_device; |
| 547 | 647 | ||
| 548 | list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) | 648 | list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) |
| 549 | if (sas_device->sas_address == sas_address) | 649 | if (sas_device->handle == handle) |
| 550 | return sas_device; | 650 | goto found_device; |
| 551 | 651 | ||
| 552 | return NULL; | 652 | return NULL; |
| 653 | |||
| 654 | found_device: | ||
| 655 | sas_device_get(sas_device); | ||
| 656 | return sas_device; | ||
| 553 | } | 657 | } |
| 554 | 658 | ||
| 555 | /** | 659 | /** |
| 556 | * _scsih_sas_device_find_by_handle - sas device search | 660 | * mpt2sas_get_sdev_by_handle - sas device search |
| 557 | * @ioc: per adapter object | 661 | * @ioc: per adapter object |
| 558 | * @handle: sas device handle (assigned by firmware) | 662 | * @handle: sas device handle (assigned by firmware) |
| 559 | * Context: Calling function should acquire ioc->sas_device_lock | 663 | * Context: Calling function should acquire ioc->sas_device_lock |
| @@ -562,19 +666,16 @@ mpt2sas_scsih_sas_device_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc, | |||
| 562 | * object. | 666 | * object. |
| 563 | */ | 667 | */ |
| 564 | static struct _sas_device * | 668 | static struct _sas_device * |
| 565 | _scsih_sas_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) | 669 | mpt2sas_get_sdev_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) |
| 566 | { | 670 | { |
| 567 | struct _sas_device *sas_device; | 671 | struct _sas_device *sas_device; |
| 672 | unsigned long flags; | ||
| 568 | 673 | ||
| 569 | list_for_each_entry(sas_device, &ioc->sas_device_list, list) | 674 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 570 | if (sas_device->handle == handle) | 675 | sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle); |
| 571 | return sas_device; | 676 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 572 | |||
| 573 | list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) | ||
| 574 | if (sas_device->handle == handle) | ||
| 575 | return sas_device; | ||
| 576 | 677 | ||
| 577 | return NULL; | 678 | return sas_device; |
| 578 | } | 679 | } |
| 579 | 680 | ||
| 580 | /** | 681 | /** |
| @@ -583,7 +684,7 @@ _scsih_sas_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 583 | * @sas_device: the sas_device object | 684 | * @sas_device: the sas_device object |
| 584 | * Context: This function will acquire ioc->sas_device_lock. | 685 | * Context: This function will acquire ioc->sas_device_lock. |
| 585 | * | 686 | * |
| 586 | * Removing object and freeing associated memory from the ioc->sas_device_list. | 687 | * If sas_device is on the list, remove it and decrement its reference count. |
| 587 | */ | 688 | */ |
| 588 | static void | 689 | static void |
| 589 | _scsih_sas_device_remove(struct MPT2SAS_ADAPTER *ioc, | 690 | _scsih_sas_device_remove(struct MPT2SAS_ADAPTER *ioc, |
| @@ -594,9 +695,15 @@ _scsih_sas_device_remove(struct MPT2SAS_ADAPTER *ioc, | |||
| 594 | if (!sas_device) | 695 | if (!sas_device) |
| 595 | return; | 696 | return; |
| 596 | 697 | ||
| 698 | /* | ||
| 699 | * The lock serializes access to the list, but we still need to verify | ||
| 700 | * that nobody removed the entry while we were waiting on the lock. | ||
| 701 | */ | ||
| 597 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 702 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 598 | list_del(&sas_device->list); | 703 | if (!list_empty(&sas_device->list)) { |
| 599 | kfree(sas_device); | 704 | list_del_init(&sas_device->list); |
| 705 | sas_device_put(sas_device); | ||
| 706 | } | ||
| 600 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 707 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 601 | } | 708 | } |
| 602 | 709 | ||
| @@ -620,6 +727,7 @@ _scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc, | |||
| 620 | sas_device->handle, (unsigned long long)sas_device->sas_address)); | 727 | sas_device->handle, (unsigned long long)sas_device->sas_address)); |
| 621 | 728 | ||
| 622 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 729 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 730 | sas_device_get(sas_device); | ||
| 623 | list_add_tail(&sas_device->list, &ioc->sas_device_list); | 731 | list_add_tail(&sas_device->list, &ioc->sas_device_list); |
| 624 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 732 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 625 | 733 | ||
| @@ -659,6 +767,7 @@ _scsih_sas_device_init_add(struct MPT2SAS_ADAPTER *ioc, | |||
| 659 | sas_device->handle, (unsigned long long)sas_device->sas_address)); | 767 | sas_device->handle, (unsigned long long)sas_device->sas_address)); |
| 660 | 768 | ||
| 661 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 769 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 770 | sas_device_get(sas_device); | ||
| 662 | list_add_tail(&sas_device->list, &ioc->sas_device_init_list); | 771 | list_add_tail(&sas_device->list, &ioc->sas_device_init_list); |
| 663 | _scsih_determine_boot_device(ioc, sas_device, 0); | 772 | _scsih_determine_boot_device(ioc, sas_device, 0); |
| 664 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 773 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| @@ -1208,12 +1317,15 @@ _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) | |||
| 1208 | goto not_sata; | 1317 | goto not_sata; |
| 1209 | if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) | 1318 | if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) |
| 1210 | goto not_sata; | 1319 | goto not_sata; |
| 1320 | |||
| 1211 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1321 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1212 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 1322 | sas_device = __mpt2sas_get_sdev_from_target(ioc, sas_target_priv_data); |
| 1213 | sas_device_priv_data->sas_target->sas_address); | 1323 | if (sas_device) { |
| 1214 | if (sas_device && sas_device->device_info & | 1324 | if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) |
| 1215 | MPI2_SAS_DEVICE_INFO_SATA_DEVICE) | 1325 | max_depth = MPT2SAS_SATA_QUEUE_DEPTH; |
| 1216 | max_depth = MPT2SAS_SATA_QUEUE_DEPTH; | 1326 | |
| 1327 | sas_device_put(sas_device); | ||
| 1328 | } | ||
| 1217 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1329 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1218 | 1330 | ||
| 1219 | not_sata: | 1331 | not_sata: |
| @@ -1271,18 +1383,20 @@ _scsih_target_alloc(struct scsi_target *starget) | |||
| 1271 | /* sas/sata devices */ | 1383 | /* sas/sata devices */ |
| 1272 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1384 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1273 | rphy = dev_to_rphy(starget->dev.parent); | 1385 | rphy = dev_to_rphy(starget->dev.parent); |
| 1274 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 1386 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, |
| 1275 | rphy->identify.sas_address); | 1387 | rphy->identify.sas_address); |
| 1276 | 1388 | ||
| 1277 | if (sas_device) { | 1389 | if (sas_device) { |
| 1278 | sas_target_priv_data->handle = sas_device->handle; | 1390 | sas_target_priv_data->handle = sas_device->handle; |
| 1279 | sas_target_priv_data->sas_address = sas_device->sas_address; | 1391 | sas_target_priv_data->sas_address = sas_device->sas_address; |
| 1392 | sas_target_priv_data->sdev = sas_device; | ||
| 1280 | sas_device->starget = starget; | 1393 | sas_device->starget = starget; |
| 1281 | sas_device->id = starget->id; | 1394 | sas_device->id = starget->id; |
| 1282 | sas_device->channel = starget->channel; | 1395 | sas_device->channel = starget->channel; |
| 1283 | if (test_bit(sas_device->handle, ioc->pd_handles)) | 1396 | if (test_bit(sas_device->handle, ioc->pd_handles)) |
| 1284 | sas_target_priv_data->flags |= | 1397 | sas_target_priv_data->flags |= |
| 1285 | MPT_TARGET_FLAGS_RAID_COMPONENT; | 1398 | MPT_TARGET_FLAGS_RAID_COMPONENT; |
| 1399 | |||
| 1286 | } | 1400 | } |
| 1287 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1401 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1288 | 1402 | ||
| @@ -1324,13 +1438,21 @@ _scsih_target_destroy(struct scsi_target *starget) | |||
| 1324 | 1438 | ||
| 1325 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1439 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1326 | rphy = dev_to_rphy(starget->dev.parent); | 1440 | rphy = dev_to_rphy(starget->dev.parent); |
| 1327 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 1441 | sas_device = __mpt2sas_get_sdev_from_target(ioc, sas_target_priv_data); |
| 1328 | rphy->identify.sas_address); | ||
| 1329 | if (sas_device && (sas_device->starget == starget) && | 1442 | if (sas_device && (sas_device->starget == starget) && |
| 1330 | (sas_device->id == starget->id) && | 1443 | (sas_device->id == starget->id) && |
| 1331 | (sas_device->channel == starget->channel)) | 1444 | (sas_device->channel == starget->channel)) |
| 1332 | sas_device->starget = NULL; | 1445 | sas_device->starget = NULL; |
| 1333 | 1446 | ||
| 1447 | if (sas_device) { | ||
| 1448 | /* | ||
| 1449 | * Corresponding get() is in _scsih_target_alloc() | ||
| 1450 | */ | ||
| 1451 | sas_target_priv_data->sdev = NULL; | ||
| 1452 | sas_device_put(sas_device); | ||
| 1453 | |||
| 1454 | sas_device_put(sas_device); | ||
| 1455 | } | ||
| 1334 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1456 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1335 | 1457 | ||
| 1336 | out: | 1458 | out: |
| @@ -1386,7 +1508,7 @@ _scsih_slave_alloc(struct scsi_device *sdev) | |||
| 1386 | 1508 | ||
| 1387 | if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { | 1509 | if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { |
| 1388 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1510 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1389 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 1511 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, |
| 1390 | sas_target_priv_data->sas_address); | 1512 | sas_target_priv_data->sas_address); |
| 1391 | if (sas_device && (sas_device->starget == NULL)) { | 1513 | if (sas_device && (sas_device->starget == NULL)) { |
| 1392 | sdev_printk(KERN_INFO, sdev, | 1514 | sdev_printk(KERN_INFO, sdev, |
| @@ -1394,6 +1516,10 @@ _scsih_slave_alloc(struct scsi_device *sdev) | |||
| 1394 | __func__, __LINE__); | 1516 | __func__, __LINE__); |
| 1395 | sas_device->starget = starget; | 1517 | sas_device->starget = starget; |
| 1396 | } | 1518 | } |
| 1519 | |||
| 1520 | if (sas_device) | ||
| 1521 | sas_device_put(sas_device); | ||
| 1522 | |||
| 1397 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1523 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1398 | } | 1524 | } |
| 1399 | 1525 | ||
| @@ -1428,10 +1554,13 @@ _scsih_slave_destroy(struct scsi_device *sdev) | |||
| 1428 | 1554 | ||
| 1429 | if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { | 1555 | if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { |
| 1430 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1556 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1431 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 1557 | sas_device = __mpt2sas_get_sdev_from_target(ioc, |
| 1432 | sas_target_priv_data->sas_address); | 1558 | sas_target_priv_data); |
| 1433 | if (sas_device && !sas_target_priv_data->num_luns) | 1559 | if (sas_device && !sas_target_priv_data->num_luns) |
| 1434 | sas_device->starget = NULL; | 1560 | sas_device->starget = NULL; |
| 1561 | |||
| 1562 | if (sas_device) | ||
| 1563 | sas_device_put(sas_device); | ||
| 1435 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1564 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1436 | } | 1565 | } |
| 1437 | 1566 | ||
| @@ -2078,7 +2207,7 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
| 2078 | } | 2207 | } |
| 2079 | 2208 | ||
| 2080 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 2209 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 2081 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 2210 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, |
| 2082 | sas_device_priv_data->sas_target->sas_address); | 2211 | sas_device_priv_data->sas_target->sas_address); |
| 2083 | if (!sas_device) { | 2212 | if (!sas_device) { |
| 2084 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 2213 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| @@ -2112,17 +2241,18 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
| 2112 | (unsigned long long) sas_device->enclosure_logical_id, | 2241 | (unsigned long long) sas_device->enclosure_logical_id, |
| 2113 | sas_device->slot); | 2242 | sas_device->slot); |
| 2114 | 2243 | ||
| 2244 | sas_device_put(sas_device); | ||
| 2115 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 2245 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 2116 | if (!ssp_target) | 2246 | if (!ssp_target) |
| 2117 | _scsih_display_sata_capabilities(ioc, handle, sdev); | 2247 | _scsih_display_sata_capabilities(ioc, handle, sdev); |
| 2118 | 2248 | ||
| 2119 | |||
| 2120 | _scsih_change_queue_depth(sdev, qdepth); | 2249 | _scsih_change_queue_depth(sdev, qdepth); |
| 2121 | 2250 | ||
| 2122 | if (ssp_target) { | 2251 | if (ssp_target) { |
| 2123 | sas_read_port_mode_page(sdev); | 2252 | sas_read_port_mode_page(sdev); |
| 2124 | _scsih_enable_tlr(ioc, sdev); | 2253 | _scsih_enable_tlr(ioc, sdev); |
| 2125 | } | 2254 | } |
| 2255 | |||
| 2126 | return 0; | 2256 | return 0; |
| 2127 | } | 2257 | } |
| 2128 | 2258 | ||
| @@ -2509,8 +2639,7 @@ _scsih_tm_display_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd) | |||
| 2509 | device_str, (unsigned long long)priv_target->sas_address); | 2639 | device_str, (unsigned long long)priv_target->sas_address); |
| 2510 | } else { | 2640 | } else { |
| 2511 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 2641 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 2512 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 2642 | sas_device = __mpt2sas_get_sdev_from_target(ioc, priv_target); |
| 2513 | priv_target->sas_address); | ||
| 2514 | if (sas_device) { | 2643 | if (sas_device) { |
| 2515 | if (priv_target->flags & | 2644 | if (priv_target->flags & |
| 2516 | MPT_TARGET_FLAGS_RAID_COMPONENT) { | 2645 | MPT_TARGET_FLAGS_RAID_COMPONENT) { |
| @@ -2529,6 +2658,8 @@ _scsih_tm_display_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd) | |||
| 2529 | "enclosure_logical_id(0x%016llx), slot(%d)\n", | 2658 | "enclosure_logical_id(0x%016llx), slot(%d)\n", |
| 2530 | (unsigned long long)sas_device->enclosure_logical_id, | 2659 | (unsigned long long)sas_device->enclosure_logical_id, |
| 2531 | sas_device->slot); | 2660 | sas_device->slot); |
| 2661 | |||
| 2662 | sas_device_put(sas_device); | ||
| 2532 | } | 2663 | } |
| 2533 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 2664 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 2534 | } | 2665 | } |
| @@ -2604,12 +2735,12 @@ _scsih_dev_reset(struct scsi_cmnd *scmd) | |||
| 2604 | { | 2735 | { |
| 2605 | struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host); | 2736 | struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host); |
| 2606 | struct MPT2SAS_DEVICE *sas_device_priv_data; | 2737 | struct MPT2SAS_DEVICE *sas_device_priv_data; |
| 2607 | struct _sas_device *sas_device; | 2738 | struct _sas_device *sas_device = NULL; |
| 2608 | unsigned long flags; | ||
| 2609 | u16 handle; | 2739 | u16 handle; |
| 2610 | int r; | 2740 | int r; |
| 2611 | 2741 | ||
| 2612 | struct scsi_target *starget = scmd->device->sdev_target; | 2742 | struct scsi_target *starget = scmd->device->sdev_target; |
| 2743 | struct MPT2SAS_TARGET *target_priv_data = starget->hostdata; | ||
| 2613 | 2744 | ||
| 2614 | starget_printk(KERN_INFO, starget, "attempting device reset! " | 2745 | starget_printk(KERN_INFO, starget, "attempting device reset! " |
| 2615 | "scmd(%p)\n", scmd); | 2746 | "scmd(%p)\n", scmd); |
| @@ -2629,12 +2760,10 @@ _scsih_dev_reset(struct scsi_cmnd *scmd) | |||
| 2629 | handle = 0; | 2760 | handle = 0; |
| 2630 | if (sas_device_priv_data->sas_target->flags & | 2761 | if (sas_device_priv_data->sas_target->flags & |
| 2631 | MPT_TARGET_FLAGS_RAID_COMPONENT) { | 2762 | MPT_TARGET_FLAGS_RAID_COMPONENT) { |
| 2632 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 2763 | sas_device = mpt2sas_get_sdev_from_target(ioc, |
| 2633 | sas_device = _scsih_sas_device_find_by_handle(ioc, | 2764 | target_priv_data); |
| 2634 | sas_device_priv_data->sas_target->handle); | ||
| 2635 | if (sas_device) | 2765 | if (sas_device) |
| 2636 | handle = sas_device->volume_handle; | 2766 | handle = sas_device->volume_handle; |
| 2637 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 2638 | } else | 2767 | } else |
| 2639 | handle = sas_device_priv_data->sas_target->handle; | 2768 | handle = sas_device_priv_data->sas_target->handle; |
| 2640 | 2769 | ||
| @@ -2651,6 +2780,10 @@ _scsih_dev_reset(struct scsi_cmnd *scmd) | |||
| 2651 | out: | 2780 | out: |
| 2652 | sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n", | 2781 | sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n", |
| 2653 | ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); | 2782 | ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); |
| 2783 | |||
| 2784 | if (sas_device) | ||
| 2785 | sas_device_put(sas_device); | ||
| 2786 | |||
| 2654 | return r; | 2787 | return r; |
| 2655 | } | 2788 | } |
| 2656 | 2789 | ||
| @@ -2665,11 +2798,11 @@ _scsih_target_reset(struct scsi_cmnd *scmd) | |||
| 2665 | { | 2798 | { |
| 2666 | struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host); | 2799 | struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host); |
| 2667 | struct MPT2SAS_DEVICE *sas_device_priv_data; | 2800 | struct MPT2SAS_DEVICE *sas_device_priv_data; |
| 2668 | struct _sas_device *sas_device; | 2801 | struct _sas_device *sas_device = NULL; |
| 2669 | unsigned long flags; | ||
| 2670 | u16 handle; | 2802 | u16 handle; |
| 2671 | int r; | 2803 | int r; |
| 2672 | struct scsi_target *starget = scmd->device->sdev_target; | 2804 | struct scsi_target *starget = scmd->device->sdev_target; |
| 2805 | struct MPT2SAS_TARGET *target_priv_data = starget->hostdata; | ||
| 2673 | 2806 | ||
| 2674 | starget_printk(KERN_INFO, starget, "attempting target reset! " | 2807 | starget_printk(KERN_INFO, starget, "attempting target reset! " |
| 2675 | "scmd(%p)\n", scmd); | 2808 | "scmd(%p)\n", scmd); |
| @@ -2689,12 +2822,10 @@ _scsih_target_reset(struct scsi_cmnd *scmd) | |||
| 2689 | handle = 0; | 2822 | handle = 0; |
| 2690 | if (sas_device_priv_data->sas_target->flags & | 2823 | if (sas_device_priv_data->sas_target->flags & |
| 2691 | MPT_TARGET_FLAGS_RAID_COMPONENT) { | 2824 | MPT_TARGET_FLAGS_RAID_COMPONENT) { |
| 2692 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 2825 | sas_device = mpt2sas_get_sdev_from_target(ioc, |
| 2693 | sas_device = _scsih_sas_device_find_by_handle(ioc, | 2826 | target_priv_data); |
| 2694 | sas_device_priv_data->sas_target->handle); | ||
| 2695 | if (sas_device) | 2827 | if (sas_device) |
| 2696 | handle = sas_device->volume_handle; | 2828 | handle = sas_device->volume_handle; |
| 2697 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 2698 | } else | 2829 | } else |
| 2699 | handle = sas_device_priv_data->sas_target->handle; | 2830 | handle = sas_device_priv_data->sas_target->handle; |
| 2700 | 2831 | ||
| @@ -2711,6 +2842,10 @@ _scsih_target_reset(struct scsi_cmnd *scmd) | |||
| 2711 | out: | 2842 | out: |
| 2712 | starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n", | 2843 | starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n", |
| 2713 | ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); | 2844 | ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); |
| 2845 | |||
| 2846 | if (sas_device) | ||
| 2847 | sas_device_put(sas_device); | ||
| 2848 | |||
| 2714 | return r; | 2849 | return r; |
| 2715 | } | 2850 | } |
| 2716 | 2851 | ||
| @@ -2768,36 +2903,39 @@ _scsih_fw_event_add(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work *fw_event) | |||
| 2768 | return; | 2903 | return; |
| 2769 | 2904 | ||
| 2770 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | 2905 | spin_lock_irqsave(&ioc->fw_event_lock, flags); |
| 2906 | fw_event_work_get(fw_event); | ||
| 2771 | list_add_tail(&fw_event->list, &ioc->fw_event_list); | 2907 | list_add_tail(&fw_event->list, &ioc->fw_event_list); |
| 2772 | INIT_DELAYED_WORK(&fw_event->delayed_work, _firmware_event_work); | 2908 | INIT_DELAYED_WORK(&fw_event->delayed_work, _firmware_event_work); |
| 2909 | fw_event_work_get(fw_event); | ||
| 2773 | queue_delayed_work(ioc->firmware_event_thread, | 2910 | queue_delayed_work(ioc->firmware_event_thread, |
| 2774 | &fw_event->delayed_work, 0); | 2911 | &fw_event->delayed_work, 0); |
| 2775 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | 2912 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); |
| 2776 | } | 2913 | } |
| 2777 | 2914 | ||
| 2778 | /** | 2915 | /** |
| 2779 | * _scsih_fw_event_free - delete fw_event | 2916 | * _scsih_fw_event_del_from_list - delete fw_event from the list |
| 2780 | * @ioc: per adapter object | 2917 | * @ioc: per adapter object |
| 2781 | * @fw_event: object describing the event | 2918 | * @fw_event: object describing the event |
| 2782 | * Context: This function will acquire ioc->fw_event_lock. | 2919 | * Context: This function will acquire ioc->fw_event_lock. |
| 2783 | * | 2920 | * |
| 2784 | * This removes firmware event object from link list, frees associated memory. | 2921 | * If the fw_event is on the fw_event_list, remove it and do a put. |
| 2785 | * | 2922 | * |
| 2786 | * Return nothing. | 2923 | * Return nothing. |
| 2787 | */ | 2924 | */ |
| 2788 | static void | 2925 | static void |
| 2789 | _scsih_fw_event_free(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work | 2926 | _scsih_fw_event_del_from_list(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work |
| 2790 | *fw_event) | 2927 | *fw_event) |
| 2791 | { | 2928 | { |
| 2792 | unsigned long flags; | 2929 | unsigned long flags; |
| 2793 | 2930 | ||
| 2794 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | 2931 | spin_lock_irqsave(&ioc->fw_event_lock, flags); |
| 2795 | list_del(&fw_event->list); | 2932 | if (!list_empty(&fw_event->list)) { |
| 2796 | kfree(fw_event); | 2933 | list_del_init(&fw_event->list); |
| 2934 | fw_event_work_put(fw_event); | ||
| 2935 | } | ||
| 2797 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | 2936 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); |
| 2798 | } | 2937 | } |
| 2799 | 2938 | ||
| 2800 | |||
| 2801 | /** | 2939 | /** |
| 2802 | * _scsih_error_recovery_delete_devices - remove devices not responding | 2940 | * _scsih_error_recovery_delete_devices - remove devices not responding |
| 2803 | * @ioc: per adapter object | 2941 | * @ioc: per adapter object |
| @@ -2812,13 +2950,14 @@ _scsih_error_recovery_delete_devices(struct MPT2SAS_ADAPTER *ioc) | |||
| 2812 | if (ioc->is_driver_loading) | 2950 | if (ioc->is_driver_loading) |
| 2813 | return; | 2951 | return; |
| 2814 | 2952 | ||
| 2815 | fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); | 2953 | fw_event = alloc_fw_event_work(0); |
| 2816 | if (!fw_event) | 2954 | if (!fw_event) |
| 2817 | return; | 2955 | return; |
| 2818 | 2956 | ||
| 2819 | fw_event->event = MPT2SAS_REMOVE_UNRESPONDING_DEVICES; | 2957 | fw_event->event = MPT2SAS_REMOVE_UNRESPONDING_DEVICES; |
| 2820 | fw_event->ioc = ioc; | 2958 | fw_event->ioc = ioc; |
| 2821 | _scsih_fw_event_add(ioc, fw_event); | 2959 | _scsih_fw_event_add(ioc, fw_event); |
| 2960 | fw_event_work_put(fw_event); | ||
| 2822 | } | 2961 | } |
| 2823 | 2962 | ||
| 2824 | /** | 2963 | /** |
| @@ -2832,12 +2971,29 @@ mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc) | |||
| 2832 | { | 2971 | { |
| 2833 | struct fw_event_work *fw_event; | 2972 | struct fw_event_work *fw_event; |
| 2834 | 2973 | ||
| 2835 | fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); | 2974 | fw_event = alloc_fw_event_work(0); |
| 2836 | if (!fw_event) | 2975 | if (!fw_event) |
| 2837 | return; | 2976 | return; |
| 2838 | fw_event->event = MPT2SAS_PORT_ENABLE_COMPLETE; | 2977 | fw_event->event = MPT2SAS_PORT_ENABLE_COMPLETE; |
| 2839 | fw_event->ioc = ioc; | 2978 | fw_event->ioc = ioc; |
| 2840 | _scsih_fw_event_add(ioc, fw_event); | 2979 | _scsih_fw_event_add(ioc, fw_event); |
| 2980 | fw_event_work_put(fw_event); | ||
| 2981 | } | ||
| 2982 | |||
| 2983 | static struct fw_event_work *dequeue_next_fw_event(struct MPT2SAS_ADAPTER *ioc) | ||
| 2984 | { | ||
| 2985 | unsigned long flags; | ||
| 2986 | struct fw_event_work *fw_event = NULL; | ||
| 2987 | |||
| 2988 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | ||
| 2989 | if (!list_empty(&ioc->fw_event_list)) { | ||
| 2990 | fw_event = list_first_entry(&ioc->fw_event_list, | ||
| 2991 | struct fw_event_work, list); | ||
| 2992 | list_del_init(&fw_event->list); | ||
| 2993 | } | ||
| 2994 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | ||
| 2995 | |||
| 2996 | return fw_event; | ||
| 2841 | } | 2997 | } |
| 2842 | 2998 | ||
| 2843 | /** | 2999 | /** |
| @@ -2852,17 +3008,25 @@ mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc) | |||
| 2852 | static void | 3008 | static void |
| 2853 | _scsih_fw_event_cleanup_queue(struct MPT2SAS_ADAPTER *ioc) | 3009 | _scsih_fw_event_cleanup_queue(struct MPT2SAS_ADAPTER *ioc) |
| 2854 | { | 3010 | { |
| 2855 | struct fw_event_work *fw_event, *next; | 3011 | struct fw_event_work *fw_event; |
| 2856 | 3012 | ||
| 2857 | if (list_empty(&ioc->fw_event_list) || | 3013 | if (list_empty(&ioc->fw_event_list) || |
| 2858 | !ioc->firmware_event_thread || in_interrupt()) | 3014 | !ioc->firmware_event_thread || in_interrupt()) |
| 2859 | return; | 3015 | return; |
| 2860 | 3016 | ||
| 2861 | list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) { | 3017 | while ((fw_event = dequeue_next_fw_event(ioc))) { |
| 2862 | if (cancel_delayed_work_sync(&fw_event->delayed_work)) { | 3018 | /* |
| 2863 | _scsih_fw_event_free(ioc, fw_event); | 3019 | * Wait on the fw_event to complete. If this returns 1, then |
| 2864 | continue; | 3020 | * the event was never executed, and we need a put for the |
| 2865 | } | 3021 | * reference the delayed_work had on the fw_event. |
| 3022 | * | ||
| 3023 | * If it did execute, we wait for it to finish, and the put will | ||
| 3024 | * happen from _firmware_event_work() | ||
| 3025 | */ | ||
| 3026 | if (cancel_delayed_work_sync(&fw_event->delayed_work)) | ||
| 3027 | fw_event_work_put(fw_event); | ||
| 3028 | |||
| 3029 | fw_event_work_put(fw_event); | ||
| 2866 | } | 3030 | } |
| 2867 | } | 3031 | } |
| 2868 | 3032 | ||
| @@ -3002,15 +3166,15 @@ _scsih_block_io_to_children_attached_to_ex(struct MPT2SAS_ADAPTER *ioc, | |||
| 3002 | 3166 | ||
| 3003 | list_for_each_entry(mpt2sas_port, | 3167 | list_for_each_entry(mpt2sas_port, |
| 3004 | &sas_expander->sas_port_list, port_list) { | 3168 | &sas_expander->sas_port_list, port_list) { |
| 3005 | if (mpt2sas_port->remote_identify.device_type == | 3169 | if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE) { |
| 3006 | SAS_END_DEVICE) { | ||
| 3007 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 3170 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 3008 | sas_device = | 3171 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, |
| 3009 | mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 3172 | mpt2sas_port->remote_identify.sas_address); |
| 3010 | mpt2sas_port->remote_identify.sas_address); | 3173 | if (sas_device) { |
| 3011 | if (sas_device) | ||
| 3012 | set_bit(sas_device->handle, | 3174 | set_bit(sas_device->handle, |
| 3013 | ioc->blocking_handles); | 3175 | ioc->blocking_handles); |
| 3176 | sas_device_put(sas_device); | ||
| 3177 | } | ||
| 3014 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 3178 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 3015 | } | 3179 | } |
| 3016 | } | 3180 | } |
| @@ -3080,7 +3244,7 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 3080 | { | 3244 | { |
| 3081 | Mpi2SCSITaskManagementRequest_t *mpi_request; | 3245 | Mpi2SCSITaskManagementRequest_t *mpi_request; |
| 3082 | u16 smid; | 3246 | u16 smid; |
| 3083 | struct _sas_device *sas_device; | 3247 | struct _sas_device *sas_device = NULL; |
| 3084 | struct MPT2SAS_TARGET *sas_target_priv_data = NULL; | 3248 | struct MPT2SAS_TARGET *sas_target_priv_data = NULL; |
| 3085 | u64 sas_address = 0; | 3249 | u64 sas_address = 0; |
| 3086 | unsigned long flags; | 3250 | unsigned long flags; |
| @@ -3110,7 +3274,7 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 3110 | return; | 3274 | return; |
| 3111 | 3275 | ||
| 3112 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 3276 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 3113 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 3277 | sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle); |
| 3114 | if (sas_device && sas_device->starget && | 3278 | if (sas_device && sas_device->starget && |
| 3115 | sas_device->starget->hostdata) { | 3279 | sas_device->starget->hostdata) { |
| 3116 | sas_target_priv_data = sas_device->starget->hostdata; | 3280 | sas_target_priv_data = sas_device->starget->hostdata; |
| @@ -3131,14 +3295,14 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 3131 | if (!smid) { | 3295 | if (!smid) { |
| 3132 | delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); | 3296 | delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); |
| 3133 | if (!delayed_tr) | 3297 | if (!delayed_tr) |
| 3134 | return; | 3298 | goto out; |
| 3135 | INIT_LIST_HEAD(&delayed_tr->list); | 3299 | INIT_LIST_HEAD(&delayed_tr->list); |
| 3136 | delayed_tr->handle = handle; | 3300 | delayed_tr->handle = handle; |
| 3137 | list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list); | 3301 | list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list); |
| 3138 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | 3302 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT |
| 3139 | "DELAYED:tr:handle(0x%04x), (open)\n", | 3303 | "DELAYED:tr:handle(0x%04x), (open)\n", |
| 3140 | ioc->name, handle)); | 3304 | ioc->name, handle)); |
| 3141 | return; | 3305 | goto out; |
| 3142 | } | 3306 | } |
| 3143 | 3307 | ||
| 3144 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "tr_send:handle(0x%04x), " | 3308 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "tr_send:handle(0x%04x), " |
| @@ -3150,6 +3314,9 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 3150 | mpi_request->DevHandle = cpu_to_le16(handle); | 3314 | mpi_request->DevHandle = cpu_to_le16(handle); |
| 3151 | mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; | 3315 | mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; |
| 3152 | mpt2sas_base_put_smid_hi_priority(ioc, smid); | 3316 | mpt2sas_base_put_smid_hi_priority(ioc, smid); |
| 3317 | out: | ||
| 3318 | if (sas_device) | ||
| 3319 | sas_device_put(sas_device); | ||
| 3153 | } | 3320 | } |
| 3154 | 3321 | ||
| 3155 | 3322 | ||
| @@ -4068,7 +4235,6 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | |||
| 4068 | char *desc_scsi_state = ioc->tmp_string; | 4235 | char *desc_scsi_state = ioc->tmp_string; |
| 4069 | u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo); | 4236 | u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo); |
| 4070 | struct _sas_device *sas_device = NULL; | 4237 | struct _sas_device *sas_device = NULL; |
| 4071 | unsigned long flags; | ||
| 4072 | struct scsi_target *starget = scmd->device->sdev_target; | 4238 | struct scsi_target *starget = scmd->device->sdev_target; |
| 4073 | struct MPT2SAS_TARGET *priv_target = starget->hostdata; | 4239 | struct MPT2SAS_TARGET *priv_target = starget->hostdata; |
| 4074 | char *device_str = NULL; | 4240 | char *device_str = NULL; |
| @@ -4200,9 +4366,7 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | |||
| 4200 | printk(MPT2SAS_WARN_FMT "\t%s wwid(0x%016llx)\n", ioc->name, | 4366 | printk(MPT2SAS_WARN_FMT "\t%s wwid(0x%016llx)\n", ioc->name, |
| 4201 | device_str, (unsigned long long)priv_target->sas_address); | 4367 | device_str, (unsigned long long)priv_target->sas_address); |
| 4202 | } else { | 4368 | } else { |
| 4203 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 4369 | sas_device = mpt2sas_get_sdev_from_target(ioc, priv_target); |
| 4204 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | ||
| 4205 | priv_target->sas_address); | ||
| 4206 | if (sas_device) { | 4370 | if (sas_device) { |
| 4207 | printk(MPT2SAS_WARN_FMT "\tsas_address(0x%016llx), " | 4371 | printk(MPT2SAS_WARN_FMT "\tsas_address(0x%016llx), " |
| 4208 | "phy(%d)\n", ioc->name, sas_device->sas_address, | 4372 | "phy(%d)\n", ioc->name, sas_device->sas_address, |
| @@ -4211,8 +4375,9 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | |||
| 4211 | "\tenclosure_logical_id(0x%016llx), slot(%d)\n", | 4375 | "\tenclosure_logical_id(0x%016llx), slot(%d)\n", |
| 4212 | ioc->name, sas_device->enclosure_logical_id, | 4376 | ioc->name, sas_device->enclosure_logical_id, |
| 4213 | sas_device->slot); | 4377 | sas_device->slot); |
| 4378 | |||
| 4379 | sas_device_put(sas_device); | ||
| 4214 | } | 4380 | } |
| 4215 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 4216 | } | 4381 | } |
| 4217 | 4382 | ||
| 4218 | printk(MPT2SAS_WARN_FMT "\thandle(0x%04x), ioc_status(%s)(0x%04x), " | 4383 | printk(MPT2SAS_WARN_FMT "\thandle(0x%04x), ioc_status(%s)(0x%04x), " |
| @@ -4259,7 +4424,7 @@ _scsih_turn_on_pfa_led(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 4259 | Mpi2SepRequest_t mpi_request; | 4424 | Mpi2SepRequest_t mpi_request; |
| 4260 | struct _sas_device *sas_device; | 4425 | struct _sas_device *sas_device; |
| 4261 | 4426 | ||
| 4262 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 4427 | sas_device = mpt2sas_get_sdev_by_handle(ioc, handle); |
| 4263 | if (!sas_device) | 4428 | if (!sas_device) |
| 4264 | return; | 4429 | return; |
| 4265 | 4430 | ||
| @@ -4274,7 +4439,7 @@ _scsih_turn_on_pfa_led(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 4274 | &mpi_request)) != 0) { | 4439 | &mpi_request)) != 0) { |
| 4275 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name, | 4440 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name, |
| 4276 | __FILE__, __LINE__, __func__); | 4441 | __FILE__, __LINE__, __func__); |
| 4277 | return; | 4442 | goto out; |
| 4278 | } | 4443 | } |
| 4279 | sas_device->pfa_led_on = 1; | 4444 | sas_device->pfa_led_on = 1; |
| 4280 | 4445 | ||
| @@ -4284,8 +4449,10 @@ _scsih_turn_on_pfa_led(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 4284 | "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n", | 4449 | "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n", |
| 4285 | ioc->name, le16_to_cpu(mpi_reply.IOCStatus), | 4450 | ioc->name, le16_to_cpu(mpi_reply.IOCStatus), |
| 4286 | le32_to_cpu(mpi_reply.IOCLogInfo))); | 4451 | le32_to_cpu(mpi_reply.IOCLogInfo))); |
| 4287 | return; | 4452 | goto out; |
| 4288 | } | 4453 | } |
| 4454 | out: | ||
| 4455 | sas_device_put(sas_device); | ||
| 4289 | } | 4456 | } |
| 4290 | 4457 | ||
| 4291 | /** | 4458 | /** |
| @@ -4340,13 +4507,14 @@ _scsih_send_event_to_turn_on_pfa_led(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 4340 | { | 4507 | { |
| 4341 | struct fw_event_work *fw_event; | 4508 | struct fw_event_work *fw_event; |
| 4342 | 4509 | ||
| 4343 | fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); | 4510 | fw_event = alloc_fw_event_work(0); |
| 4344 | if (!fw_event) | 4511 | if (!fw_event) |
| 4345 | return; | 4512 | return; |
| 4346 | fw_event->event = MPT2SAS_TURN_ON_PFA_LED; | 4513 | fw_event->event = MPT2SAS_TURN_ON_PFA_LED; |
| 4347 | fw_event->device_handle = handle; | 4514 | fw_event->device_handle = handle; |
| 4348 | fw_event->ioc = ioc; | 4515 | fw_event->ioc = ioc; |
| 4349 | _scsih_fw_event_add(ioc, fw_event); | 4516 | _scsih_fw_event_add(ioc, fw_event); |
| 4517 | fw_event_work_put(fw_event); | ||
| 4350 | } | 4518 | } |
| 4351 | 4519 | ||
| 4352 | /** | 4520 | /** |
| @@ -4370,19 +4538,17 @@ _scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 4370 | 4538 | ||
| 4371 | /* only handle non-raid devices */ | 4539 | /* only handle non-raid devices */ |
| 4372 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 4540 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 4373 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 4541 | sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle); |
| 4374 | if (!sas_device) { | 4542 | if (!sas_device) { |
| 4375 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 4543 | goto out_unlock; |
| 4376 | return; | ||
| 4377 | } | 4544 | } |
| 4378 | starget = sas_device->starget; | 4545 | starget = sas_device->starget; |
| 4379 | sas_target_priv_data = starget->hostdata; | 4546 | sas_target_priv_data = starget->hostdata; |
| 4380 | 4547 | ||
| 4381 | if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) || | 4548 | if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) || |
| 4382 | ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))) { | 4549 | ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))) |
| 4383 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 4550 | goto out_unlock; |
| 4384 | return; | 4551 | |
| 4385 | } | ||
| 4386 | starget_printk(KERN_WARNING, starget, "predicted fault\n"); | 4552 | starget_printk(KERN_WARNING, starget, "predicted fault\n"); |
| 4387 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 4553 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 4388 | 4554 | ||
| @@ -4396,7 +4562,7 @@ _scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 4396 | if (!event_reply) { | 4562 | if (!event_reply) { |
| 4397 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 4563 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", |
| 4398 | ioc->name, __FILE__, __LINE__, __func__); | 4564 | ioc->name, __FILE__, __LINE__, __func__); |
| 4399 | return; | 4565 | goto out; |
| 4400 | } | 4566 | } |
| 4401 | 4567 | ||
| 4402 | event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION; | 4568 | event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION; |
| @@ -4413,6 +4579,14 @@ _scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 4413 | event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address); | 4579 | event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address); |
| 4414 | mpt2sas_ctl_add_to_event_log(ioc, event_reply); | 4580 | mpt2sas_ctl_add_to_event_log(ioc, event_reply); |
| 4415 | kfree(event_reply); | 4581 | kfree(event_reply); |
| 4582 | out: | ||
| 4583 | if (sas_device) | ||
| 4584 | sas_device_put(sas_device); | ||
| 4585 | return; | ||
| 4586 | |||
| 4587 | out_unlock: | ||
| 4588 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 4589 | goto out; | ||
| 4416 | } | 4590 | } |
| 4417 | 4591 | ||
| 4418 | /** | 4592 | /** |
| @@ -5148,14 +5322,13 @@ _scsih_check_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 5148 | 5322 | ||
| 5149 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 5323 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 5150 | sas_address = le64_to_cpu(sas_device_pg0.SASAddress); | 5324 | sas_address = le64_to_cpu(sas_device_pg0.SASAddress); |
| 5151 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 5325 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, |
| 5152 | sas_address); | 5326 | sas_address); |
| 5153 | 5327 | ||
| 5154 | if (!sas_device) { | 5328 | if (!sas_device) { |
| 5155 | printk(MPT2SAS_ERR_FMT "device is not present " | 5329 | printk(MPT2SAS_ERR_FMT "device is not present " |
| 5156 | "handle(0x%04x), no sas_device!!!\n", ioc->name, handle); | 5330 | "handle(0x%04x), no sas_device!!!\n", ioc->name, handle); |
| 5157 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5331 | goto out_unlock; |
| 5158 | return; | ||
| 5159 | } | 5332 | } |
| 5160 | 5333 | ||
| 5161 | if (unlikely(sas_device->handle != handle)) { | 5334 | if (unlikely(sas_device->handle != handle)) { |
| @@ -5172,19 +5345,24 @@ _scsih_check_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 5172 | MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) { | 5345 | MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) { |
| 5173 | printk(MPT2SAS_ERR_FMT "device is not present " | 5346 | printk(MPT2SAS_ERR_FMT "device is not present " |
| 5174 | "handle(0x%04x), flags!!!\n", ioc->name, handle); | 5347 | "handle(0x%04x), flags!!!\n", ioc->name, handle); |
| 5175 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5348 | goto out_unlock; |
| 5176 | return; | ||
| 5177 | } | 5349 | } |
| 5178 | 5350 | ||
| 5179 | /* check if there were any issues with discovery */ | 5351 | /* check if there were any issues with discovery */ |
| 5180 | if (_scsih_check_access_status(ioc, sas_address, handle, | 5352 | if (_scsih_check_access_status(ioc, sas_address, handle, |
| 5181 | sas_device_pg0.AccessStatus)) { | 5353 | sas_device_pg0.AccessStatus)) |
| 5182 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5354 | goto out_unlock; |
| 5183 | return; | 5355 | |
| 5184 | } | ||
| 5185 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5356 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 5186 | _scsih_ublock_io_device(ioc, sas_address); | 5357 | _scsih_ublock_io_device(ioc, sas_address); |
| 5358 | if (sas_device) | ||
| 5359 | sas_device_put(sas_device); | ||
| 5360 | return; | ||
| 5187 | 5361 | ||
| 5362 | out_unlock: | ||
| 5363 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 5364 | if (sas_device) | ||
| 5365 | sas_device_put(sas_device); | ||
| 5188 | } | 5366 | } |
| 5189 | 5367 | ||
| 5190 | /** | 5368 | /** |
| @@ -5208,7 +5386,6 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) | |||
| 5208 | u32 ioc_status; | 5386 | u32 ioc_status; |
| 5209 | __le64 sas_address; | 5387 | __le64 sas_address; |
| 5210 | u32 device_info; | 5388 | u32 device_info; |
| 5211 | unsigned long flags; | ||
| 5212 | 5389 | ||
| 5213 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, | 5390 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, |
| 5214 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { | 5391 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { |
| @@ -5250,14 +5427,13 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) | |||
| 5250 | return -1; | 5427 | return -1; |
| 5251 | } | 5428 | } |
| 5252 | 5429 | ||
| 5253 | 5430 | sas_device = mpt2sas_get_sdev_by_addr(ioc, | |
| 5254 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 5255 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | ||
| 5256 | sas_address); | 5431 | sas_address); |
| 5257 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 5258 | 5432 | ||
| 5259 | if (sas_device) | 5433 | if (sas_device) { |
| 5434 | sas_device_put(sas_device); | ||
| 5260 | return 0; | 5435 | return 0; |
| 5436 | } | ||
| 5261 | 5437 | ||
| 5262 | sas_device = kzalloc(sizeof(struct _sas_device), | 5438 | sas_device = kzalloc(sizeof(struct _sas_device), |
| 5263 | GFP_KERNEL); | 5439 | GFP_KERNEL); |
| @@ -5267,6 +5443,7 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) | |||
| 5267 | return -1; | 5443 | return -1; |
| 5268 | } | 5444 | } |
| 5269 | 5445 | ||
| 5446 | kref_init(&sas_device->refcount); | ||
| 5270 | sas_device->handle = handle; | 5447 | sas_device->handle = handle; |
| 5271 | if (_scsih_get_sas_address(ioc, le16_to_cpu | 5448 | if (_scsih_get_sas_address(ioc, le16_to_cpu |
| 5272 | (sas_device_pg0.ParentDevHandle), | 5449 | (sas_device_pg0.ParentDevHandle), |
| @@ -5296,6 +5473,7 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) | |||
| 5296 | else | 5473 | else |
| 5297 | _scsih_sas_device_add(ioc, sas_device); | 5474 | _scsih_sas_device_add(ioc, sas_device); |
| 5298 | 5475 | ||
| 5476 | sas_device_put(sas_device); | ||
| 5299 | return 0; | 5477 | return 0; |
| 5300 | } | 5478 | } |
| 5301 | 5479 | ||
| @@ -5344,7 +5522,6 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, | |||
| 5344 | "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__, | 5522 | "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__, |
| 5345 | sas_device->handle, (unsigned long long) | 5523 | sas_device->handle, (unsigned long long) |
| 5346 | sas_device->sas_address)); | 5524 | sas_device->sas_address)); |
| 5347 | kfree(sas_device); | ||
| 5348 | } | 5525 | } |
| 5349 | /** | 5526 | /** |
| 5350 | * _scsih_device_remove_by_handle - removing device object by handle | 5527 | * _scsih_device_remove_by_handle - removing device object by handle |
| @@ -5363,12 +5540,17 @@ _scsih_device_remove_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 5363 | return; | 5540 | return; |
| 5364 | 5541 | ||
| 5365 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 5542 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 5366 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 5543 | sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle); |
| 5367 | if (sas_device) | 5544 | if (sas_device) { |
| 5368 | list_del(&sas_device->list); | 5545 | list_del_init(&sas_device->list); |
| 5546 | sas_device_put(sas_device); | ||
| 5547 | } | ||
| 5369 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5548 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 5370 | if (sas_device) | 5549 | |
| 5550 | if (sas_device) { | ||
| 5371 | _scsih_remove_device(ioc, sas_device); | 5551 | _scsih_remove_device(ioc, sas_device); |
| 5552 | sas_device_put(sas_device); | ||
| 5553 | } | ||
| 5372 | } | 5554 | } |
| 5373 | 5555 | ||
| 5374 | /** | 5556 | /** |
| @@ -5389,13 +5571,17 @@ mpt2sas_device_remove_by_sas_address(struct MPT2SAS_ADAPTER *ioc, | |||
| 5389 | return; | 5571 | return; |
| 5390 | 5572 | ||
| 5391 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 5573 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 5392 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 5574 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, sas_address); |
| 5393 | sas_address); | 5575 | if (sas_device) { |
| 5394 | if (sas_device) | 5576 | list_del_init(&sas_device->list); |
| 5395 | list_del(&sas_device->list); | 5577 | sas_device_put(sas_device); |
| 5578 | } | ||
| 5396 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5579 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 5397 | if (sas_device) | 5580 | |
| 5581 | if (sas_device) { | ||
| 5398 | _scsih_remove_device(ioc, sas_device); | 5582 | _scsih_remove_device(ioc, sas_device); |
| 5583 | sas_device_put(sas_device); | ||
| 5584 | } | ||
| 5399 | } | 5585 | } |
| 5400 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 5586 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
| 5401 | /** | 5587 | /** |
| @@ -5716,26 +5902,28 @@ _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc, | |||
| 5716 | 5902 | ||
| 5717 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 5903 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 5718 | sas_address = le64_to_cpu(event_data->SASAddress); | 5904 | sas_address = le64_to_cpu(event_data->SASAddress); |
| 5719 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 5905 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, |
| 5720 | sas_address); | 5906 | sas_address); |
| 5721 | 5907 | ||
| 5722 | if (!sas_device || !sas_device->starget) { | 5908 | if (!sas_device || !sas_device->starget) |
| 5723 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5909 | goto out; |
| 5724 | return; | ||
| 5725 | } | ||
| 5726 | 5910 | ||
| 5727 | target_priv_data = sas_device->starget->hostdata; | 5911 | target_priv_data = sas_device->starget->hostdata; |
| 5728 | if (!target_priv_data) { | 5912 | if (!target_priv_data) |
| 5729 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5913 | goto out; |
| 5730 | return; | ||
| 5731 | } | ||
| 5732 | 5914 | ||
| 5733 | if (event_data->ReasonCode == | 5915 | if (event_data->ReasonCode == |
| 5734 | MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET) | 5916 | MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET) |
| 5735 | target_priv_data->tm_busy = 1; | 5917 | target_priv_data->tm_busy = 1; |
| 5736 | else | 5918 | else |
| 5737 | target_priv_data->tm_busy = 0; | 5919 | target_priv_data->tm_busy = 0; |
| 5920 | |||
| 5921 | out: | ||
| 5922 | if (sas_device) | ||
| 5923 | sas_device_put(sas_device); | ||
| 5924 | |||
| 5738 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5925 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 5926 | |||
| 5739 | } | 5927 | } |
| 5740 | 5928 | ||
| 5741 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 5929 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
| @@ -6123,7 +6311,7 @@ _scsih_sas_pd_expose(struct MPT2SAS_ADAPTER *ioc, | |||
| 6123 | u16 handle = le16_to_cpu(element->PhysDiskDevHandle); | 6311 | u16 handle = le16_to_cpu(element->PhysDiskDevHandle); |
| 6124 | 6312 | ||
| 6125 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 6313 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 6126 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 6314 | sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle); |
| 6127 | if (sas_device) { | 6315 | if (sas_device) { |
| 6128 | sas_device->volume_handle = 0; | 6316 | sas_device->volume_handle = 0; |
| 6129 | sas_device->volume_wwid = 0; | 6317 | sas_device->volume_wwid = 0; |
| @@ -6142,6 +6330,8 @@ _scsih_sas_pd_expose(struct MPT2SAS_ADAPTER *ioc, | |||
| 6142 | /* exposing raid component */ | 6330 | /* exposing raid component */ |
| 6143 | if (starget) | 6331 | if (starget) |
| 6144 | starget_for_each_device(starget, NULL, _scsih_reprobe_lun); | 6332 | starget_for_each_device(starget, NULL, _scsih_reprobe_lun); |
| 6333 | |||
| 6334 | sas_device_put(sas_device); | ||
| 6145 | } | 6335 | } |
| 6146 | 6336 | ||
| 6147 | /** | 6337 | /** |
| @@ -6170,7 +6360,7 @@ _scsih_sas_pd_hide(struct MPT2SAS_ADAPTER *ioc, | |||
| 6170 | &volume_wwid); | 6360 | &volume_wwid); |
| 6171 | 6361 | ||
| 6172 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 6362 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 6173 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 6363 | sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle); |
| 6174 | if (sas_device) { | 6364 | if (sas_device) { |
| 6175 | set_bit(handle, ioc->pd_handles); | 6365 | set_bit(handle, ioc->pd_handles); |
| 6176 | if (sas_device->starget && sas_device->starget->hostdata) { | 6366 | if (sas_device->starget && sas_device->starget->hostdata) { |
| @@ -6189,6 +6379,8 @@ _scsih_sas_pd_hide(struct MPT2SAS_ADAPTER *ioc, | |||
| 6189 | /* hiding raid component */ | 6379 | /* hiding raid component */ |
| 6190 | if (starget) | 6380 | if (starget) |
| 6191 | starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun); | 6381 | starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun); |
| 6382 | |||
| 6383 | sas_device_put(sas_device); | ||
| 6192 | } | 6384 | } |
| 6193 | 6385 | ||
| 6194 | /** | 6386 | /** |
| @@ -6221,7 +6413,6 @@ _scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc, | |||
| 6221 | Mpi2EventIrConfigElement_t *element) | 6413 | Mpi2EventIrConfigElement_t *element) |
| 6222 | { | 6414 | { |
| 6223 | struct _sas_device *sas_device; | 6415 | struct _sas_device *sas_device; |
| 6224 | unsigned long flags; | ||
| 6225 | u16 handle = le16_to_cpu(element->PhysDiskDevHandle); | 6416 | u16 handle = le16_to_cpu(element->PhysDiskDevHandle); |
| 6226 | Mpi2ConfigReply_t mpi_reply; | 6417 | Mpi2ConfigReply_t mpi_reply; |
| 6227 | Mpi2SasDevicePage0_t sas_device_pg0; | 6418 | Mpi2SasDevicePage0_t sas_device_pg0; |
| @@ -6231,11 +6422,11 @@ _scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc, | |||
| 6231 | 6422 | ||
| 6232 | set_bit(handle, ioc->pd_handles); | 6423 | set_bit(handle, ioc->pd_handles); |
| 6233 | 6424 | ||
| 6234 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 6425 | sas_device = mpt2sas_get_sdev_by_handle(ioc, handle); |
| 6235 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 6426 | if (sas_device) { |
| 6236 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 6427 | sas_device_put(sas_device); |
| 6237 | if (sas_device) | ||
| 6238 | return; | 6428 | return; |
| 6429 | } | ||
| 6239 | 6430 | ||
| 6240 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, | 6431 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, |
| 6241 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { | 6432 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { |
| @@ -6509,7 +6700,6 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, | |||
| 6509 | u16 handle, parent_handle; | 6700 | u16 handle, parent_handle; |
| 6510 | u32 state; | 6701 | u32 state; |
| 6511 | struct _sas_device *sas_device; | 6702 | struct _sas_device *sas_device; |
| 6512 | unsigned long flags; | ||
| 6513 | Mpi2ConfigReply_t mpi_reply; | 6703 | Mpi2ConfigReply_t mpi_reply; |
| 6514 | Mpi2SasDevicePage0_t sas_device_pg0; | 6704 | Mpi2SasDevicePage0_t sas_device_pg0; |
| 6515 | u32 ioc_status; | 6705 | u32 ioc_status; |
| @@ -6542,12 +6732,11 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, | |||
| 6542 | if (!ioc->is_warpdrive) | 6732 | if (!ioc->is_warpdrive) |
| 6543 | set_bit(handle, ioc->pd_handles); | 6733 | set_bit(handle, ioc->pd_handles); |
| 6544 | 6734 | ||
| 6545 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 6735 | sas_device = mpt2sas_get_sdev_by_handle(ioc, handle); |
| 6546 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 6736 | if (sas_device) { |
| 6547 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 6737 | sas_device_put(sas_device); |
| 6548 | |||
| 6549 | if (sas_device) | ||
| 6550 | return; | 6738 | return; |
| 6739 | } | ||
| 6551 | 6740 | ||
| 6552 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, | 6741 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, |
| 6553 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, | 6742 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, |
| @@ -7015,6 +7204,7 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc) | |||
| 7015 | struct _raid_device *raid_device, *raid_device_next; | 7204 | struct _raid_device *raid_device, *raid_device_next; |
| 7016 | struct list_head tmp_list; | 7205 | struct list_head tmp_list; |
| 7017 | unsigned long flags; | 7206 | unsigned long flags; |
| 7207 | LIST_HEAD(head); | ||
| 7018 | 7208 | ||
| 7019 | printk(MPT2SAS_INFO_FMT "removing unresponding devices: start\n", | 7209 | printk(MPT2SAS_INFO_FMT "removing unresponding devices: start\n", |
| 7020 | ioc->name); | 7210 | ioc->name); |
| @@ -7022,14 +7212,29 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc) | |||
| 7022 | /* removing unresponding end devices */ | 7212 | /* removing unresponding end devices */ |
| 7023 | printk(MPT2SAS_INFO_FMT "removing unresponding devices: end-devices\n", | 7213 | printk(MPT2SAS_INFO_FMT "removing unresponding devices: end-devices\n", |
| 7024 | ioc->name); | 7214 | ioc->name); |
| 7215 | |||
| 7216 | /* | ||
| 7217 | * Iterate, pulling off devices marked as non-responding. We become the | ||
| 7218 | * owner for the reference the list had on any object we prune. | ||
| 7219 | */ | ||
| 7220 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 7025 | list_for_each_entry_safe(sas_device, sas_device_next, | 7221 | list_for_each_entry_safe(sas_device, sas_device_next, |
| 7026 | &ioc->sas_device_list, list) { | 7222 | &ioc->sas_device_list, list) { |
| 7027 | if (!sas_device->responding) | 7223 | if (!sas_device->responding) |
| 7028 | mpt2sas_device_remove_by_sas_address(ioc, | 7224 | list_move_tail(&sas_device->list, &head); |
| 7029 | sas_device->sas_address); | ||
| 7030 | else | 7225 | else |
| 7031 | sas_device->responding = 0; | 7226 | sas_device->responding = 0; |
| 7032 | } | 7227 | } |
| 7228 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 7229 | |||
| 7230 | /* | ||
| 7231 | * Now, uninitialize and remove the unresponding devices we pruned. | ||
| 7232 | */ | ||
| 7233 | list_for_each_entry_safe(sas_device, sas_device_next, &head, list) { | ||
| 7234 | _scsih_remove_device(ioc, sas_device); | ||
| 7235 | list_del_init(&sas_device->list); | ||
| 7236 | sas_device_put(sas_device); | ||
| 7237 | } | ||
| 7033 | 7238 | ||
| 7034 | /* removing unresponding volumes */ | 7239 | /* removing unresponding volumes */ |
| 7035 | if (ioc->ir_firmware) { | 7240 | if (ioc->ir_firmware) { |
| @@ -7179,11 +7384,11 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) | |||
| 7179 | } | 7384 | } |
| 7180 | phys_disk_num = pd_pg0.PhysDiskNum; | 7385 | phys_disk_num = pd_pg0.PhysDiskNum; |
| 7181 | handle = le16_to_cpu(pd_pg0.DevHandle); | 7386 | handle = le16_to_cpu(pd_pg0.DevHandle); |
| 7182 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 7387 | sas_device = mpt2sas_get_sdev_by_handle(ioc, handle); |
| 7183 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 7388 | if (sas_device) { |
| 7184 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 7389 | sas_device_put(sas_device); |
| 7185 | if (sas_device) | ||
| 7186 | continue; | 7390 | continue; |
| 7391 | } | ||
| 7187 | if (mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, | 7392 | if (mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, |
| 7188 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, | 7393 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, |
| 7189 | handle) != 0) | 7394 | handle) != 0) |
| @@ -7302,12 +7507,12 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) | |||
| 7302 | if (!(_scsih_is_end_device( | 7507 | if (!(_scsih_is_end_device( |
| 7303 | le32_to_cpu(sas_device_pg0.DeviceInfo)))) | 7508 | le32_to_cpu(sas_device_pg0.DeviceInfo)))) |
| 7304 | continue; | 7509 | continue; |
| 7305 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 7510 | sas_device = mpt2sas_get_sdev_by_addr(ioc, |
| 7306 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | ||
| 7307 | le64_to_cpu(sas_device_pg0.SASAddress)); | 7511 | le64_to_cpu(sas_device_pg0.SASAddress)); |
| 7308 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 7512 | if (sas_device) { |
| 7309 | if (sas_device) | 7513 | sas_device_put(sas_device); |
| 7310 | continue; | 7514 | continue; |
| 7515 | } | ||
| 7311 | parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); | 7516 | parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); |
| 7312 | if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) { | 7517 | if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) { |
| 7313 | printk(MPT2SAS_INFO_FMT "\tBEFORE adding end device: " | 7518 | printk(MPT2SAS_INFO_FMT "\tBEFORE adding end device: " |
| @@ -7410,17 +7615,27 @@ _firmware_event_work(struct work_struct *work) | |||
| 7410 | struct fw_event_work, delayed_work.work); | 7615 | struct fw_event_work, delayed_work.work); |
| 7411 | struct MPT2SAS_ADAPTER *ioc = fw_event->ioc; | 7616 | struct MPT2SAS_ADAPTER *ioc = fw_event->ioc; |
| 7412 | 7617 | ||
| 7618 | _scsih_fw_event_del_from_list(ioc, fw_event); | ||
| 7619 | |||
| 7413 | /* the queue is being flushed so ignore this event */ | 7620 | /* the queue is being flushed so ignore this event */ |
| 7414 | if (ioc->remove_host || | 7621 | if (ioc->remove_host || ioc->pci_error_recovery) { |
| 7415 | ioc->pci_error_recovery) { | 7622 | fw_event_work_put(fw_event); |
| 7416 | _scsih_fw_event_free(ioc, fw_event); | ||
| 7417 | return; | 7623 | return; |
| 7418 | } | 7624 | } |
| 7419 | 7625 | ||
| 7420 | switch (fw_event->event) { | 7626 | switch (fw_event->event) { |
| 7421 | case MPT2SAS_REMOVE_UNRESPONDING_DEVICES: | 7627 | case MPT2SAS_REMOVE_UNRESPONDING_DEVICES: |
| 7422 | while (scsi_host_in_recovery(ioc->shost) || ioc->shost_recovery) | 7628 | while (scsi_host_in_recovery(ioc->shost) || |
| 7629 | ioc->shost_recovery) { | ||
| 7630 | /* | ||
| 7631 | * If we're unloading, bail. Otherwise, this can become | ||
| 7632 | * an infinite loop. | ||
| 7633 | */ | ||
| 7634 | if (ioc->remove_host) | ||
| 7635 | goto out; | ||
| 7636 | |||
| 7423 | ssleep(1); | 7637 | ssleep(1); |
| 7638 | } | ||
| 7424 | _scsih_remove_unresponding_sas_devices(ioc); | 7639 | _scsih_remove_unresponding_sas_devices(ioc); |
| 7425 | _scsih_scan_for_devices_after_reset(ioc); | 7640 | _scsih_scan_for_devices_after_reset(ioc); |
| 7426 | break; | 7641 | break; |
| @@ -7469,7 +7684,8 @@ _firmware_event_work(struct work_struct *work) | |||
| 7469 | _scsih_sas_ir_operation_status_event(ioc, fw_event); | 7684 | _scsih_sas_ir_operation_status_event(ioc, fw_event); |
| 7470 | break; | 7685 | break; |
| 7471 | } | 7686 | } |
| 7472 | _scsih_fw_event_free(ioc, fw_event); | 7687 | out: |
| 7688 | fw_event_work_put(fw_event); | ||
| 7473 | } | 7689 | } |
| 7474 | 7690 | ||
| 7475 | /** | 7691 | /** |
| @@ -7607,7 +7823,7 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | |||
| 7607 | } | 7823 | } |
| 7608 | 7824 | ||
| 7609 | sz = le16_to_cpu(mpi_reply->EventDataLength) * 4; | 7825 | sz = le16_to_cpu(mpi_reply->EventDataLength) * 4; |
| 7610 | fw_event = kzalloc(sizeof(*fw_event) + sz, GFP_ATOMIC); | 7826 | fw_event = alloc_fw_event_work(sz); |
| 7611 | if (!fw_event) { | 7827 | if (!fw_event) { |
| 7612 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 7828 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", |
| 7613 | ioc->name, __FILE__, __LINE__, __func__); | 7829 | ioc->name, __FILE__, __LINE__, __func__); |
| @@ -7620,6 +7836,7 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | |||
| 7620 | fw_event->VP_ID = mpi_reply->VP_ID; | 7836 | fw_event->VP_ID = mpi_reply->VP_ID; |
| 7621 | fw_event->event = event; | 7837 | fw_event->event = event; |
| 7622 | _scsih_fw_event_add(ioc, fw_event); | 7838 | _scsih_fw_event_add(ioc, fw_event); |
| 7839 | fw_event_work_put(fw_event); | ||
| 7623 | return; | 7840 | return; |
| 7624 | } | 7841 | } |
| 7625 | 7842 | ||
| @@ -7867,7 +8084,9 @@ _scsih_remove(struct pci_dev *pdev) | |||
| 7867 | sas_remove_host(shost); | 8084 | sas_remove_host(shost); |
| 7868 | scsi_remove_host(shost); | 8085 | scsi_remove_host(shost); |
| 7869 | mpt2sas_base_detach(ioc); | 8086 | mpt2sas_base_detach(ioc); |
| 8087 | spin_lock(&gioc_lock); | ||
| 7870 | list_del(&ioc->list); | 8088 | list_del(&ioc->list); |
| 8089 | spin_unlock(&gioc_lock); | ||
| 7871 | scsi_host_put(shost); | 8090 | scsi_host_put(shost); |
| 7872 | } | 8091 | } |
| 7873 | 8092 | ||
| @@ -7966,6 +8185,48 @@ _scsih_probe_raid(struct MPT2SAS_ADAPTER *ioc) | |||
| 7966 | } | 8185 | } |
| 7967 | } | 8186 | } |
| 7968 | 8187 | ||
| 8188 | static struct _sas_device *get_next_sas_device(struct MPT2SAS_ADAPTER *ioc) | ||
| 8189 | { | ||
| 8190 | struct _sas_device *sas_device = NULL; | ||
| 8191 | unsigned long flags; | ||
| 8192 | |||
| 8193 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 8194 | if (!list_empty(&ioc->sas_device_init_list)) { | ||
| 8195 | sas_device = list_first_entry(&ioc->sas_device_init_list, | ||
| 8196 | struct _sas_device, list); | ||
| 8197 | sas_device_get(sas_device); | ||
| 8198 | } | ||
| 8199 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 8200 | |||
| 8201 | return sas_device; | ||
| 8202 | } | ||
| 8203 | |||
| 8204 | static void sas_device_make_active(struct MPT2SAS_ADAPTER *ioc, | ||
| 8205 | struct _sas_device *sas_device) | ||
| 8206 | { | ||
| 8207 | unsigned long flags; | ||
| 8208 | |||
| 8209 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 8210 | |||
| 8211 | /* | ||
| 8212 | * Since we dropped the lock during the call to port_add(), we need to | ||
| 8213 | * be careful here that somebody else didn't move or delete this item | ||
| 8214 | * while we were busy with other things. | ||
| 8215 | * | ||
| 8216 | * If it was on the list, we need a put() for the reference the list | ||
| 8217 | * had. Either way, we need a get() for the destination list. | ||
| 8218 | */ | ||
| 8219 | if (!list_empty(&sas_device->list)) { | ||
| 8220 | list_del_init(&sas_device->list); | ||
| 8221 | sas_device_put(sas_device); | ||
| 8222 | } | ||
| 8223 | |||
| 8224 | sas_device_get(sas_device); | ||
| 8225 | list_add_tail(&sas_device->list, &ioc->sas_device_list); | ||
| 8226 | |||
| 8227 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 8228 | } | ||
| 8229 | |||
| 7969 | /** | 8230 | /** |
| 7970 | * _scsih_probe_sas - reporting sas devices to sas transport | 8231 | * _scsih_probe_sas - reporting sas devices to sas transport |
| 7971 | * @ioc: per adapter object | 8232 | * @ioc: per adapter object |
| @@ -7975,34 +8236,30 @@ _scsih_probe_raid(struct MPT2SAS_ADAPTER *ioc) | |||
| 7975 | static void | 8236 | static void |
| 7976 | _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc) | 8237 | _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc) |
| 7977 | { | 8238 | { |
| 7978 | struct _sas_device *sas_device, *next; | 8239 | struct _sas_device *sas_device; |
| 7979 | unsigned long flags; | ||
| 7980 | |||
| 7981 | /* SAS Device List */ | ||
| 7982 | list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list, | ||
| 7983 | list) { | ||
| 7984 | 8240 | ||
| 7985 | if (ioc->hide_drives) | 8241 | if (ioc->hide_drives) |
| 7986 | continue; | 8242 | return; |
| 7987 | 8243 | ||
| 8244 | while ((sas_device = get_next_sas_device(ioc))) { | ||
| 7988 | if (!mpt2sas_transport_port_add(ioc, sas_device->handle, | 8245 | if (!mpt2sas_transport_port_add(ioc, sas_device->handle, |
| 7989 | sas_device->sas_address_parent)) { | 8246 | sas_device->sas_address_parent)) { |
| 7990 | list_del(&sas_device->list); | 8247 | _scsih_sas_device_remove(ioc, sas_device); |
| 7991 | kfree(sas_device); | 8248 | sas_device_put(sas_device); |
| 7992 | continue; | 8249 | continue; |
| 7993 | } else if (!sas_device->starget) { | 8250 | } else if (!sas_device->starget) { |
| 7994 | if (!ioc->is_driver_loading) { | 8251 | if (!ioc->is_driver_loading) { |
| 7995 | mpt2sas_transport_port_remove(ioc, | 8252 | mpt2sas_transport_port_remove(ioc, |
| 7996 | sas_device->sas_address, | 8253 | sas_device->sas_address, |
| 7997 | sas_device->sas_address_parent); | 8254 | sas_device->sas_address_parent); |
| 7998 | list_del(&sas_device->list); | 8255 | _scsih_sas_device_remove(ioc, sas_device); |
| 7999 | kfree(sas_device); | 8256 | sas_device_put(sas_device); |
| 8000 | continue; | 8257 | continue; |
| 8001 | } | 8258 | } |
| 8002 | } | 8259 | } |
| 8003 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 8260 | |
| 8004 | list_move_tail(&sas_device->list, &ioc->sas_device_list); | 8261 | sas_device_make_active(ioc, sas_device); |
| 8005 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 8262 | sas_device_put(sas_device); |
| 8006 | } | 8263 | } |
| 8007 | } | 8264 | } |
| 8008 | 8265 | ||
| @@ -8142,7 +8399,9 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 8142 | ioc = shost_priv(shost); | 8399 | ioc = shost_priv(shost); |
| 8143 | memset(ioc, 0, sizeof(struct MPT2SAS_ADAPTER)); | 8400 | memset(ioc, 0, sizeof(struct MPT2SAS_ADAPTER)); |
| 8144 | INIT_LIST_HEAD(&ioc->list); | 8401 | INIT_LIST_HEAD(&ioc->list); |
| 8402 | spin_lock(&gioc_lock); | ||
| 8145 | list_add_tail(&ioc->list, &mpt2sas_ioc_list); | 8403 | list_add_tail(&ioc->list, &mpt2sas_ioc_list); |
| 8404 | spin_unlock(&gioc_lock); | ||
| 8146 | ioc->shost = shost; | 8405 | ioc->shost = shost; |
| 8147 | ioc->id = mpt_ids++; | 8406 | ioc->id = mpt_ids++; |
| 8148 | sprintf(ioc->name, "%s%d", MPT2SAS_DRIVER_NAME, ioc->id); | 8407 | sprintf(ioc->name, "%s%d", MPT2SAS_DRIVER_NAME, ioc->id); |
| @@ -8167,6 +8426,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 8167 | ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds; | 8426 | ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds; |
| 8168 | /* misc semaphores and spin locks */ | 8427 | /* misc semaphores and spin locks */ |
| 8169 | mutex_init(&ioc->reset_in_progress_mutex); | 8428 | mutex_init(&ioc->reset_in_progress_mutex); |
| 8429 | /* initializing pci_access_mutex lock */ | ||
| 8430 | mutex_init(&ioc->pci_access_mutex); | ||
| 8170 | spin_lock_init(&ioc->ioc_reset_in_progress_lock); | 8431 | spin_lock_init(&ioc->ioc_reset_in_progress_lock); |
| 8171 | spin_lock_init(&ioc->scsi_lookup_lock); | 8432 | spin_lock_init(&ioc->scsi_lookup_lock); |
| 8172 | spin_lock_init(&ioc->sas_device_lock); | 8433 | spin_lock_init(&ioc->sas_device_lock); |
| @@ -8269,7 +8530,9 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 8269 | out_attach_fail: | 8530 | out_attach_fail: |
| 8270 | destroy_workqueue(ioc->firmware_event_thread); | 8531 | destroy_workqueue(ioc->firmware_event_thread); |
| 8271 | out_thread_fail: | 8532 | out_thread_fail: |
| 8533 | spin_lock(&gioc_lock); | ||
| 8272 | list_del(&ioc->list); | 8534 | list_del(&ioc->list); |
| 8535 | spin_unlock(&gioc_lock); | ||
| 8273 | scsi_host_put(shost); | 8536 | scsi_host_put(shost); |
| 8274 | return rv; | 8537 | return rv; |
| 8275 | } | 8538 | } |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c index ff2500ab9ba4..af868009395d 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_transport.c +++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c | |||
| @@ -1323,15 +1323,17 @@ _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) | |||
| 1323 | int rc; | 1323 | int rc; |
| 1324 | 1324 | ||
| 1325 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1325 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1326 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 1326 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, |
| 1327 | rphy->identify.sas_address); | 1327 | rphy->identify.sas_address); |
| 1328 | if (sas_device) { | 1328 | if (sas_device) { |
| 1329 | *identifier = sas_device->enclosure_logical_id; | 1329 | *identifier = sas_device->enclosure_logical_id; |
| 1330 | rc = 0; | 1330 | rc = 0; |
| 1331 | sas_device_put(sas_device); | ||
| 1331 | } else { | 1332 | } else { |
| 1332 | *identifier = 0; | 1333 | *identifier = 0; |
| 1333 | rc = -ENXIO; | 1334 | rc = -ENXIO; |
| 1334 | } | 1335 | } |
| 1336 | |||
| 1335 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1337 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1336 | return rc; | 1338 | return rc; |
| 1337 | } | 1339 | } |
| @@ -1351,12 +1353,14 @@ _transport_get_bay_identifier(struct sas_rphy *rphy) | |||
| 1351 | int rc; | 1353 | int rc; |
| 1352 | 1354 | ||
| 1353 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1355 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1354 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 1356 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, |
| 1355 | rphy->identify.sas_address); | 1357 | rphy->identify.sas_address); |
| 1356 | if (sas_device) | 1358 | if (sas_device) { |
| 1357 | rc = sas_device->slot; | 1359 | rc = sas_device->slot; |
| 1358 | else | 1360 | sas_device_put(sas_device); |
| 1361 | } else { | ||
| 1359 | rc = -ENXIO; | 1362 | rc = -ENXIO; |
| 1363 | } | ||
| 1360 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1364 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1361 | return rc; | 1365 | return rc; |
| 1362 | } | 1366 | } |
