Commit 8d7533e5 authored by Thomas Falcon's avatar Thomas Falcon Committed by David S. Miller

ibmvnic: Fix releasing of sub-CRQ IRQs in interrupt context

Schedule these XPORT event tasks in the shared workqueue
so that IRQs are not freed in an interrupt context when
sub-CRQs are released.
Signed-off-by: default avatarThomas Falcon <tlfalcon@linux.vnet.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fd33b244
...@@ -3232,6 +3232,27 @@ static void ibmvnic_free_inflight(struct ibmvnic_adapter *adapter) ...@@ -3232,6 +3232,27 @@ static void ibmvnic_free_inflight(struct ibmvnic_adapter *adapter)
spin_unlock_irqrestore(&adapter->inflight_lock, flags); spin_unlock_irqrestore(&adapter->inflight_lock, flags);
} }
static void ibmvnic_xport_event(struct work_struct *work)
{
struct ibmvnic_adapter *adapter = container_of(work,
struct ibmvnic_adapter,
ibmvnic_xport);
struct device *dev = &adapter->vdev->dev;
int rc;
ibmvnic_free_inflight(adapter);
release_sub_crqs(adapter);
if (adapter->migrated) {
rc = ibmvnic_reenable_crq_queue(adapter);
if (rc)
dev_err(dev, "Error after enable rc=%ld\n", rc);
adapter->migrated = false;
rc = ibmvnic_send_crq_init(adapter);
if (rc)
dev_err(dev, "Error sending init rc=%ld\n", rc);
}
}
static void ibmvnic_handle_crq(union ibmvnic_crq *crq, static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
struct ibmvnic_adapter *adapter) struct ibmvnic_adapter *adapter)
{ {
...@@ -3267,15 +3288,7 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq, ...@@ -3267,15 +3288,7 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
if (gen_crq->cmd == IBMVNIC_PARTITION_MIGRATED) { if (gen_crq->cmd == IBMVNIC_PARTITION_MIGRATED) {
dev_info(dev, "Re-enabling adapter\n"); dev_info(dev, "Re-enabling adapter\n");
adapter->migrated = true; adapter->migrated = true;
ibmvnic_free_inflight(adapter); schedule_work(&adapter->ibmvnic_xport);
release_sub_crqs(adapter);
rc = ibmvnic_reenable_crq_queue(adapter);
if (rc)
dev_err(dev, "Error after enable rc=%ld\n", rc);
adapter->migrated = false;
rc = ibmvnic_send_crq_init(adapter);
if (rc)
dev_err(dev, "Error sending init rc=%ld\n", rc);
} else if (gen_crq->cmd == IBMVNIC_DEVICE_FAILOVER) { } else if (gen_crq->cmd == IBMVNIC_DEVICE_FAILOVER) {
dev_info(dev, "Backing device failover detected\n"); dev_info(dev, "Backing device failover detected\n");
netif_carrier_off(netdev); netif_carrier_off(netdev);
...@@ -3284,8 +3297,7 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq, ...@@ -3284,8 +3297,7 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
/* The adapter lost the connection */ /* The adapter lost the connection */
dev_err(dev, "Virtual Adapter failed (rc=%d)\n", dev_err(dev, "Virtual Adapter failed (rc=%d)\n",
gen_crq->cmd); gen_crq->cmd);
ibmvnic_free_inflight(adapter); schedule_work(&adapter->ibmvnic_xport);
release_sub_crqs(adapter);
} }
return; return;
case IBMVNIC_CRQ_CMD_RSP: case IBMVNIC_CRQ_CMD_RSP:
...@@ -3726,6 +3738,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) ...@@ -3726,6 +3738,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
SET_NETDEV_DEV(netdev, &dev->dev); SET_NETDEV_DEV(netdev, &dev->dev);
INIT_WORK(&adapter->vnic_crq_init, handle_crq_init_rsp); INIT_WORK(&adapter->vnic_crq_init, handle_crq_init_rsp);
INIT_WORK(&adapter->ibmvnic_xport, ibmvnic_xport_event);
spin_lock_init(&adapter->stats_lock); spin_lock_init(&adapter->stats_lock);
......
...@@ -1048,5 +1048,6 @@ struct ibmvnic_adapter { ...@@ -1048,5 +1048,6 @@ struct ibmvnic_adapter {
u8 map_id; u8 map_id;
struct work_struct vnic_crq_init; struct work_struct vnic_crq_init;
struct work_struct ibmvnic_xport;
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