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>
This commit is contained in:
Родитель
9138125bea
Коммит
a3299ab185
|
@ -163,12 +163,13 @@ static irqreturn_t rsxx_isr(int irq, void *pdata)
|
|||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
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);
|
||||
handled++;
|
||||
}
|
||||
|
@ -610,7 +611,11 @@ static int rsxx_pci_probe(struct pci_dev *dev,
|
|||
}
|
||||
|
||||
/************* 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);
|
||||
rsxx_enable_ier_and_isr(card, CR_INTR_CREG);
|
||||
|
@ -650,6 +655,12 @@ static int rsxx_pci_probe(struct pci_dev *dev,
|
|||
}
|
||||
|
||||
/************* 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);
|
||||
|
||||
st = rsxx_setup_dev(card);
|
||||
|
@ -688,9 +699,15 @@ static int rsxx_pci_probe(struct pci_dev *dev,
|
|||
return 0;
|
||||
|
||||
failed_create_dev:
|
||||
destroy_workqueue(card->event_wq);
|
||||
card->event_wq = NULL;
|
||||
failed_event_handler:
|
||||
rsxx_dma_destroy(card);
|
||||
failed_dma_setup:
|
||||
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);
|
||||
rsxx_disable_ier_and_isr(card, CR_INTR_ALL);
|
||||
spin_unlock_irq(&card->irq_lock);
|
||||
|
|
|
@ -727,6 +727,11 @@ int rsxx_creg_setup(struct rsxx_cardinfo *card)
|
|||
{
|
||||
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);
|
||||
mutex_init(&card->creg_ctrl.reset_lock);
|
||||
INIT_LIST_HEAD(&card->creg_ctrl.queue);
|
||||
|
|
|
@ -134,6 +134,7 @@ struct rsxx_cardinfo {
|
|||
spinlock_t lock;
|
||||
bool active;
|
||||
struct creg_cmd *active_cmd;
|
||||
struct workqueue_struct *creg_wq;
|
||||
struct work_struct done_work;
|
||||
struct list_head queue;
|
||||
unsigned int q_depth;
|
||||
|
@ -154,6 +155,7 @@ struct rsxx_cardinfo {
|
|||
int buf_len;
|
||||
} log;
|
||||
|
||||
struct workqueue_struct *event_wq;
|
||||
struct work_struct event_work;
|
||||
unsigned int state;
|
||||
u64 size8;
|
||||
|
|
Загрузка…
Ссылка в новой задаче