diff options
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_ctl.c')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_ctl.c | 38 |
1 files changed, 31 insertions, 7 deletions
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); |