diff options
author | Tejun Heo <tj@kernel.org> | 2010-07-02 04:03:52 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2010-07-02 04:59:24 -0400 |
commit | ad72cf9885c536e3adae03f8337557ac9dd1e4bb (patch) | |
tree | e93af7f241987ffe365792c0130d182b0ac890d1 /drivers/ata/libata-core.c | |
parent | d313dd85ad846bc768d58e9ceb28588f917f4c9a (diff) |
libata: take advantage of cmwq and remove concurrency limitations
libata has two concurrency related limitations.
a. ata_wq which is used for polling PIO has single thread per CPU. If
there are multiple devices doing polling PIO on the same CPU, they
can't be executed simultaneously.
b. ata_aux_wq which is used for SCSI probing has single thread. In
cases where SCSI probing is stalled for extended period of time
which is possible for ATAPI devices, this will stall all probing.
#a is solved by increasing maximum concurrency of ata_wq. Please note
that polling PIO might be used under allocation path and thus needs to
be served by a separate wq with a rescuer.
#b is solved by using the default wq instead and achieving exclusion
via per-port mutex.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r-- | drivers/ata/libata-core.c | 20 |
1 files changed, 5 insertions, 15 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index ddf8e4862787..4f78741692dc 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -98,8 +98,6 @@ static unsigned long ata_dev_blacklisted(const struct ata_device *dev); | |||
98 | 98 | ||
99 | unsigned int ata_print_id = 1; | 99 | unsigned int ata_print_id = 1; |
100 | 100 | ||
101 | struct workqueue_struct *ata_aux_wq; | ||
102 | |||
103 | struct ata_force_param { | 101 | struct ata_force_param { |
104 | const char *name; | 102 | const char *name; |
105 | unsigned int cbl; | 103 | unsigned int cbl; |
@@ -5611,6 +5609,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host) | |||
5611 | ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN; | 5609 | ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN; |
5612 | #endif | 5610 | #endif |
5613 | 5611 | ||
5612 | mutex_init(&ap->scsi_scan_mutex); | ||
5614 | INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug); | 5613 | INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug); |
5615 | INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan); | 5614 | INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan); |
5616 | INIT_LIST_HEAD(&ap->eh_done_q); | 5615 | INIT_LIST_HEAD(&ap->eh_done_q); |
@@ -6549,29 +6548,20 @@ static int __init ata_init(void) | |||
6549 | 6548 | ||
6550 | ata_parse_force_param(); | 6549 | ata_parse_force_param(); |
6551 | 6550 | ||
6552 | ata_aux_wq = create_singlethread_workqueue("ata_aux"); | ||
6553 | if (!ata_aux_wq) | ||
6554 | goto fail; | ||
6555 | |||
6556 | rc = ata_sff_init(); | 6551 | rc = ata_sff_init(); |
6557 | if (rc) | 6552 | if (rc) { |
6558 | goto fail; | 6553 | kfree(ata_force_tbl); |
6554 | return rc; | ||
6555 | } | ||
6559 | 6556 | ||
6560 | printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n"); | 6557 | printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n"); |
6561 | return 0; | 6558 | return 0; |
6562 | |||
6563 | fail: | ||
6564 | kfree(ata_force_tbl); | ||
6565 | if (ata_aux_wq) | ||
6566 | destroy_workqueue(ata_aux_wq); | ||
6567 | return rc; | ||
6568 | } | 6559 | } |
6569 | 6560 | ||
6570 | static void __exit ata_exit(void) | 6561 | static void __exit ata_exit(void) |
6571 | { | 6562 | { |
6572 | ata_sff_exit(); | 6563 | ata_sff_exit(); |
6573 | kfree(ata_force_tbl); | 6564 | kfree(ata_force_tbl); |
6574 | destroy_workqueue(ata_aux_wq); | ||
6575 | } | 6565 | } |
6576 | 6566 | ||
6577 | subsys_initcall(ata_init); | 6567 | subsys_initcall(ata_init); |