Commit 6c267b3d authored by Thomas Falcon's avatar Thomas Falcon Committed by David S. Miller

ibmvnic: Handle processing of CRQ messages in a tasklet

Create a tasklet to process queued commands or messages received from
firmware instead of processing them in the interrupt handler. Note that
this handler does not process network traffic, but communications related
to resource allocation and device settings.
Signed-off-by: default avatarThomas Falcon <tlfalcon@linux.vnet.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1e128c81
...@@ -3420,6 +3420,18 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq, ...@@ -3420,6 +3420,18 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
static irqreturn_t ibmvnic_interrupt(int irq, void *instance) static irqreturn_t ibmvnic_interrupt(int irq, void *instance)
{ {
struct ibmvnic_adapter *adapter = instance; struct ibmvnic_adapter *adapter = instance;
unsigned long flags;
spin_lock_irqsave(&adapter->crq.lock, flags);
vio_disable_interrupts(adapter->vdev);
tasklet_schedule(&adapter->tasklet);
spin_unlock_irqrestore(&adapter->crq.lock, flags);
return IRQ_HANDLED;
}
static void ibmvnic_tasklet(void *data)
{
struct ibmvnic_adapter *adapter = data;
struct ibmvnic_crq_queue *queue = &adapter->crq; struct ibmvnic_crq_queue *queue = &adapter->crq;
struct vio_dev *vdev = adapter->vdev; struct vio_dev *vdev = adapter->vdev;
union ibmvnic_crq *crq; union ibmvnic_crq *crq;
...@@ -3445,7 +3457,6 @@ static irqreturn_t ibmvnic_interrupt(int irq, void *instance) ...@@ -3445,7 +3457,6 @@ static irqreturn_t ibmvnic_interrupt(int irq, void *instance)
} }
} }
spin_unlock_irqrestore(&queue->lock, flags); spin_unlock_irqrestore(&queue->lock, flags);
return IRQ_HANDLED;
} }
static int ibmvnic_reenable_crq_queue(struct ibmvnic_adapter *adapter) static int ibmvnic_reenable_crq_queue(struct ibmvnic_adapter *adapter)
...@@ -3500,6 +3511,7 @@ static void ibmvnic_release_crq_queue(struct ibmvnic_adapter *adapter) ...@@ -3500,6 +3511,7 @@ static void ibmvnic_release_crq_queue(struct ibmvnic_adapter *adapter)
netdev_dbg(adapter->netdev, "Releasing CRQ\n"); netdev_dbg(adapter->netdev, "Releasing CRQ\n");
free_irq(vdev->irq, adapter); free_irq(vdev->irq, adapter);
tasklet_kill(&adapter->tasklet);
do { do {
rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
} while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); } while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
...@@ -3545,6 +3557,9 @@ static int ibmvnic_init_crq_queue(struct ibmvnic_adapter *adapter) ...@@ -3545,6 +3557,9 @@ static int ibmvnic_init_crq_queue(struct ibmvnic_adapter *adapter)
retrc = 0; retrc = 0;
tasklet_init(&adapter->tasklet, (void *)ibmvnic_tasklet,
(unsigned long)adapter);
netdev_dbg(adapter->netdev, "registering irq 0x%x\n", vdev->irq); netdev_dbg(adapter->netdev, "registering irq 0x%x\n", vdev->irq);
rc = request_irq(vdev->irq, ibmvnic_interrupt, 0, IBMVNIC_NAME, rc = request_irq(vdev->irq, ibmvnic_interrupt, 0, IBMVNIC_NAME,
adapter); adapter);
...@@ -3566,6 +3581,7 @@ static int ibmvnic_init_crq_queue(struct ibmvnic_adapter *adapter) ...@@ -3566,6 +3581,7 @@ static int ibmvnic_init_crq_queue(struct ibmvnic_adapter *adapter)
return retrc; return retrc;
req_irq_failed: req_irq_failed:
tasklet_kill(&adapter->tasklet);
do { do {
rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
} while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); } while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
......
...@@ -1049,5 +1049,6 @@ struct ibmvnic_adapter { ...@@ -1049,5 +1049,6 @@ struct ibmvnic_adapter {
struct work_struct vnic_crq_init; struct work_struct vnic_crq_init;
struct work_struct ibmvnic_xport; struct work_struct ibmvnic_xport;
struct tasklet_struct tasklet;
bool failover; bool failover;
}; };
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