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

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
Loading
Loading
Loading
Loading
+20 −3
Original line number Diff line number Diff line
@@ -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);
+5 −0
Original line number Diff line number Diff line
@@ -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);
+2 −0
Original line number Diff line number Diff line
@@ -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;