Commit a3299ab1 authored by Philip J Kelleher's avatar Philip J Kelleher Committed by Jens Axboe

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: default avatarPhilip J Kelleher <pjk1939@linux.vnet.ibm.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 9138125b
...@@ -163,12 +163,13 @@ static irqreturn_t rsxx_isr(int irq, void *pdata) ...@@ -163,12 +163,13 @@ static irqreturn_t rsxx_isr(int irq, void *pdata)
} }
if (isr & CR_INTR_CREG) { if (isr & CR_INTR_CREG) {
schedule_work(&card->creg_ctrl.done_work); queue_work(card->creg_ctrl.creg_wq,
&card->creg_ctrl.done_work);
handled++; handled++;
} }
if (isr & CR_INTR_EVENT) { if (isr & CR_INTR_EVENT) {
schedule_work(&card->event_work); queue_work(card->event_wq, &card->event_work);
rsxx_disable_ier_and_isr(card, CR_INTR_EVENT); rsxx_disable_ier_and_isr(card, CR_INTR_EVENT);
handled++; handled++;
} }
...@@ -610,7 +611,11 @@ static int rsxx_pci_probe(struct pci_dev *dev, ...@@ -610,7 +611,11 @@ static int rsxx_pci_probe(struct pci_dev *dev,
} }
/************* Setup Processor Command Interface *************/ /************* Setup Processor Command Interface *************/
rsxx_creg_setup(card); st = rsxx_creg_setup(card);
if (st) {
dev_err(CARD_TO_DEV(card), "Failed to setup creg interface.\n");
goto failed_creg_setup;
}
spin_lock_irq(&card->irq_lock); spin_lock_irq(&card->irq_lock);
rsxx_enable_ier_and_isr(card, CR_INTR_CREG); rsxx_enable_ier_and_isr(card, CR_INTR_CREG);
...@@ -650,6 +655,12 @@ static int rsxx_pci_probe(struct pci_dev *dev, ...@@ -650,6 +655,12 @@ static int rsxx_pci_probe(struct pci_dev *dev,
} }
/************* Setup Card Event Handler *************/ /************* Setup Card Event Handler *************/
card->event_wq = create_singlethread_workqueue(DRIVER_NAME"_event");
if (!card->event_wq) {
dev_err(CARD_TO_DEV(card), "Failed card event setup.\n");
goto failed_event_handler;
}
INIT_WORK(&card->event_work, card_event_handler); INIT_WORK(&card->event_work, card_event_handler);
st = rsxx_setup_dev(card); st = rsxx_setup_dev(card);
...@@ -688,9 +699,15 @@ static int rsxx_pci_probe(struct pci_dev *dev, ...@@ -688,9 +699,15 @@ static int rsxx_pci_probe(struct pci_dev *dev,
return 0; return 0;
failed_create_dev: failed_create_dev:
destroy_workqueue(card->event_wq);
card->event_wq = NULL;
failed_event_handler:
rsxx_dma_destroy(card); rsxx_dma_destroy(card);
failed_dma_setup: failed_dma_setup:
failed_compatiblity_check: failed_compatiblity_check:
destroy_workqueue(card->creg_ctrl.creg_wq);
card->creg_ctrl.creg_wq = NULL;
failed_creg_setup:
spin_lock_irq(&card->irq_lock); spin_lock_irq(&card->irq_lock);
rsxx_disable_ier_and_isr(card, CR_INTR_ALL); rsxx_disable_ier_and_isr(card, CR_INTR_ALL);
spin_unlock_irq(&card->irq_lock); spin_unlock_irq(&card->irq_lock);
......
...@@ -727,6 +727,11 @@ int rsxx_creg_setup(struct rsxx_cardinfo *card) ...@@ -727,6 +727,11 @@ int rsxx_creg_setup(struct rsxx_cardinfo *card)
{ {
card->creg_ctrl.active_cmd = NULL; card->creg_ctrl.active_cmd = NULL;
card->creg_ctrl.creg_wq =
create_singlethread_workqueue(DRIVER_NAME"_creg");
if (!card->creg_ctrl.creg_wq)
return -ENOMEM;
INIT_WORK(&card->creg_ctrl.done_work, creg_cmd_done); INIT_WORK(&card->creg_ctrl.done_work, creg_cmd_done);
mutex_init(&card->creg_ctrl.reset_lock); mutex_init(&card->creg_ctrl.reset_lock);
INIT_LIST_HEAD(&card->creg_ctrl.queue); INIT_LIST_HEAD(&card->creg_ctrl.queue);
......
...@@ -134,6 +134,7 @@ struct rsxx_cardinfo { ...@@ -134,6 +134,7 @@ struct rsxx_cardinfo {
spinlock_t lock; spinlock_t lock;
bool active; bool active;
struct creg_cmd *active_cmd; struct creg_cmd *active_cmd;
struct workqueue_struct *creg_wq;
struct work_struct done_work; struct work_struct done_work;
struct list_head queue; struct list_head queue;
unsigned int q_depth; unsigned int q_depth;
...@@ -154,6 +155,7 @@ struct rsxx_cardinfo { ...@@ -154,6 +155,7 @@ struct rsxx_cardinfo {
int buf_len; int buf_len;
} log; } log;
struct workqueue_struct *event_wq;
struct work_struct event_work; struct work_struct event_work;
unsigned int state; unsigned int state;
u64 size8; u64 size8;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment