diff options
author | Philip J Kelleher <pjk1939@linux.vnet.ibm.com> | 2013-06-18 15:34:54 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2013-06-19 07:52:09 -0400 |
commit | a3299ab18591d36ad5622f5064619123c439b779 (patch) | |
tree | 5a08d03af4ef28eea4f1638a385d10d3fa107856 | |
parent | 9138125beabbb76b4a373d4a619870f6f5d86fc5 (diff) |
rsxx: Individual workqueues for interruptible events.
Giving all interrupt based events their own workqueue to complete
tasks on. This fixes a bug that would cause creg commands to timeout
if too many are issued at once.
Signed-off-by: Philip J Kelleher <pjk1939@linux.vnet.ibm.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | drivers/block/rsxx/core.c | 23 | ||||
-rw-r--r-- | drivers/block/rsxx/cregs.c | 5 | ||||
-rw-r--r-- | drivers/block/rsxx/rsxx_priv.h | 2 |
3 files changed, 27 insertions, 3 deletions
diff --git a/drivers/block/rsxx/core.c b/drivers/block/rsxx/core.c index 5af21f2db29c..774f810c6a9c 100644 --- a/drivers/block/rsxx/core.c +++ b/drivers/block/rsxx/core.c | |||
@@ -163,12 +163,13 @@ static irqreturn_t rsxx_isr(int irq, void *pdata) | |||
163 | } | 163 | } |
164 | 164 | ||
165 | if (isr & CR_INTR_CREG) { | 165 | if (isr & CR_INTR_CREG) { |
166 | schedule_work(&card->creg_ctrl.done_work); | 166 | queue_work(card->creg_ctrl.creg_wq, |
167 | &card->creg_ctrl.done_work); | ||
167 | handled++; | 168 | handled++; |
168 | } | 169 | } |
169 | 170 | ||
170 | if (isr & CR_INTR_EVENT) { | 171 | if (isr & CR_INTR_EVENT) { |
171 | schedule_work(&card->event_work); | 172 | queue_work(card->event_wq, &card->event_work); |
172 | rsxx_disable_ier_and_isr(card, CR_INTR_EVENT); | 173 | rsxx_disable_ier_and_isr(card, CR_INTR_EVENT); |
173 | handled++; | 174 | handled++; |
174 | } | 175 | } |
@@ -610,7 +611,11 @@ static int rsxx_pci_probe(struct pci_dev *dev, | |||
610 | } | 611 | } |
611 | 612 | ||
612 | /************* Setup Processor Command Interface *************/ | 613 | /************* Setup Processor Command Interface *************/ |
613 | rsxx_creg_setup(card); | 614 | st = rsxx_creg_setup(card); |
615 | if (st) { | ||
616 | dev_err(CARD_TO_DEV(card), "Failed to setup creg interface.\n"); | ||
617 | goto failed_creg_setup; | ||
618 | } | ||
614 | 619 | ||
615 | spin_lock_irq(&card->irq_lock); | 620 | spin_lock_irq(&card->irq_lock); |
616 | rsxx_enable_ier_and_isr(card, CR_INTR_CREG); | 621 | rsxx_enable_ier_and_isr(card, CR_INTR_CREG); |
@@ -650,6 +655,12 @@ static int rsxx_pci_probe(struct pci_dev *dev, | |||
650 | } | 655 | } |
651 | 656 | ||
652 | /************* Setup Card Event Handler *************/ | 657 | /************* Setup Card Event Handler *************/ |
658 | card->event_wq = create_singlethread_workqueue(DRIVER_NAME"_event"); | ||
659 | if (!card->event_wq) { | ||
660 | dev_err(CARD_TO_DEV(card), "Failed card event setup.\n"); | ||
661 | goto failed_event_handler; | ||
662 | } | ||
663 | |||
653 | INIT_WORK(&card->event_work, card_event_handler); | 664 | INIT_WORK(&card->event_work, card_event_handler); |
654 | 665 | ||
655 | st = rsxx_setup_dev(card); | 666 | st = rsxx_setup_dev(card); |
@@ -688,9 +699,15 @@ static int rsxx_pci_probe(struct pci_dev *dev, | |||
688 | return 0; | 699 | return 0; |
689 | 700 | ||
690 | failed_create_dev: | 701 | failed_create_dev: |
702 | destroy_workqueue(card->event_wq); | ||
703 | card->event_wq = NULL; | ||
704 | failed_event_handler: | ||
691 | rsxx_dma_destroy(card); | 705 | rsxx_dma_destroy(card); |
692 | failed_dma_setup: | 706 | failed_dma_setup: |
693 | failed_compatiblity_check: | 707 | failed_compatiblity_check: |
708 | destroy_workqueue(card->creg_ctrl.creg_wq); | ||
709 | card->creg_ctrl.creg_wq = NULL; | ||
710 | failed_creg_setup: | ||
694 | spin_lock_irq(&card->irq_lock); | 711 | spin_lock_irq(&card->irq_lock); |
695 | rsxx_disable_ier_and_isr(card, CR_INTR_ALL); | 712 | rsxx_disable_ier_and_isr(card, CR_INTR_ALL); |
696 | spin_unlock_irq(&card->irq_lock); | 713 | spin_unlock_irq(&card->irq_lock); |
diff --git a/drivers/block/rsxx/cregs.c b/drivers/block/rsxx/cregs.c index 4b5c020a0a65..4914464c19fc 100644 --- a/drivers/block/rsxx/cregs.c +++ b/drivers/block/rsxx/cregs.c | |||
@@ -727,6 +727,11 @@ int rsxx_creg_setup(struct rsxx_cardinfo *card) | |||
727 | { | 727 | { |
728 | card->creg_ctrl.active_cmd = NULL; | 728 | card->creg_ctrl.active_cmd = NULL; |
729 | 729 | ||
730 | card->creg_ctrl.creg_wq = | ||
731 | create_singlethread_workqueue(DRIVER_NAME"_creg"); | ||
732 | if (!card->creg_ctrl.creg_wq) | ||
733 | return -ENOMEM; | ||
734 | |||
730 | INIT_WORK(&card->creg_ctrl.done_work, creg_cmd_done); | 735 | INIT_WORK(&card->creg_ctrl.done_work, creg_cmd_done); |
731 | mutex_init(&card->creg_ctrl.reset_lock); | 736 | mutex_init(&card->creg_ctrl.reset_lock); |
732 | INIT_LIST_HEAD(&card->creg_ctrl.queue); | 737 | INIT_LIST_HEAD(&card->creg_ctrl.queue); |
diff --git a/drivers/block/rsxx/rsxx_priv.h b/drivers/block/rsxx/rsxx_priv.h index 382e8bf5c03b..0dd62d966772 100644 --- a/drivers/block/rsxx/rsxx_priv.h +++ b/drivers/block/rsxx/rsxx_priv.h | |||
@@ -134,6 +134,7 @@ struct rsxx_cardinfo { | |||
134 | spinlock_t lock; | 134 | spinlock_t lock; |
135 | bool active; | 135 | bool active; |
136 | struct creg_cmd *active_cmd; | 136 | struct creg_cmd *active_cmd; |
137 | struct workqueue_struct *creg_wq; | ||
137 | struct work_struct done_work; | 138 | struct work_struct done_work; |
138 | struct list_head queue; | 139 | struct list_head queue; |
139 | unsigned int q_depth; | 140 | unsigned int q_depth; |
@@ -154,6 +155,7 @@ struct rsxx_cardinfo { | |||
154 | int buf_len; | 155 | int buf_len; |
155 | } log; | 156 | } log; |
156 | 157 | ||
158 | struct workqueue_struct *event_wq; | ||
157 | struct work_struct event_work; | 159 | struct work_struct event_work; |
158 | unsigned int state; | 160 | unsigned int state; |
159 | u64 size8; | 161 | u64 size8; |