Loading drivers/net/ethernet/ibm/ibmvnic.c +167 −60 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ #include <linux/uaccess.h> #include <asm/firmware.h> #include <linux/seq_file.h> #include <linux/workqueue.h> #include "ibmvnic.h" Loading @@ -89,6 +90,7 @@ MODULE_VERSION(IBMVNIC_DRIVER_VERSION); static int ibmvnic_version = IBMVNIC_INITIAL_VERSION; static int ibmvnic_remove(struct vio_dev *); static void release_sub_crqs(struct ibmvnic_adapter *); static void release_sub_crqs_no_irqs(struct ibmvnic_adapter *); static int ibmvnic_reset_crq(struct ibmvnic_adapter *); static int ibmvnic_send_crq_init(struct ibmvnic_adapter *); static int ibmvnic_reenable_crq_queue(struct ibmvnic_adapter *); Loading Loading @@ -469,7 +471,8 @@ static int ibmvnic_open(struct net_device *netdev) crq.logical_link_state.link_state = IBMVNIC_LOGICAL_LNK_UP; ibmvnic_send_crq(adapter, &crq); netif_start_queue(netdev); netif_tx_start_all_queues(netdev); return 0; bounce_map_failed: Loading Loading @@ -519,7 +522,7 @@ static int ibmvnic_close(struct net_device *netdev) for (i = 0; i < adapter->req_rx_queues; i++) napi_disable(&adapter->napi[i]); netif_stop_queue(netdev); netif_tx_stop_all_queues(netdev); if (adapter->bounce_buffer) { if (!dma_mapping_error(dev, adapter->bounce_buffer_dma)) { Loading Loading @@ -1212,12 +1215,6 @@ static struct ibmvnic_sub_crq_queue *init_sub_crq_queue(struct ibmvnic_adapter goto reg_failed; } scrq->irq = irq_create_mapping(NULL, scrq->hw_irq); if (scrq->irq == NO_IRQ) { dev_err(dev, "Error mapping irq\n"); goto map_irq_failed; } scrq->adapter = adapter; scrq->size = 4 * PAGE_SIZE / sizeof(*scrq->msgs); scrq->cur = 0; Loading @@ -1230,12 +1227,6 @@ static struct ibmvnic_sub_crq_queue *init_sub_crq_queue(struct ibmvnic_adapter return scrq; map_irq_failed: do { rc = plpar_hcall_norets(H_FREE_SUB_CRQ, adapter->vdev->unit_address, scrq->crq_num); } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); reg_failed: dma_unmap_single(dev, scrq->msg_token, 4 * PAGE_SIZE, DMA_BIDIRECTIONAL); Loading @@ -1256,6 +1247,7 @@ static void release_sub_crqs(struct ibmvnic_adapter *adapter) if (adapter->tx_scrq[i]) { free_irq(adapter->tx_scrq[i]->irq, adapter->tx_scrq[i]); irq_dispose_mapping(adapter->tx_scrq[i]->irq); release_sub_crq_queue(adapter, adapter->tx_scrq[i]); } Loading @@ -1267,6 +1259,7 @@ static void release_sub_crqs(struct ibmvnic_adapter *adapter) if (adapter->rx_scrq[i]) { free_irq(adapter->rx_scrq[i]->irq, adapter->rx_scrq[i]); irq_dispose_mapping(adapter->rx_scrq[i]->irq); release_sub_crq_queue(adapter, adapter->rx_scrq[i]); } Loading @@ -1276,6 +1269,29 @@ static void release_sub_crqs(struct ibmvnic_adapter *adapter) adapter->requested_caps = 0; } static void release_sub_crqs_no_irqs(struct ibmvnic_adapter *adapter) { int i; if (adapter->tx_scrq) { for (i = 0; i < adapter->req_tx_queues; i++) if (adapter->tx_scrq[i]) release_sub_crq_queue(adapter, adapter->tx_scrq[i]); adapter->tx_scrq = NULL; } if (adapter->rx_scrq) { for (i = 0; i < adapter->req_rx_queues; i++) if (adapter->rx_scrq[i]) release_sub_crq_queue(adapter, adapter->rx_scrq[i]); adapter->rx_scrq = NULL; } adapter->requested_caps = 0; } static int disable_scrq_irq(struct ibmvnic_adapter *adapter, struct ibmvnic_sub_crq_queue *scrq) { Loading Loading @@ -1395,6 +1411,66 @@ static irqreturn_t ibmvnic_interrupt_rx(int irq, void *instance) return IRQ_HANDLED; } static int init_sub_crq_irqs(struct ibmvnic_adapter *adapter) { struct device *dev = &adapter->vdev->dev; struct ibmvnic_sub_crq_queue *scrq; int i = 0, j = 0; int rc = 0; for (i = 0; i < adapter->req_tx_queues; i++) { scrq = adapter->tx_scrq[i]; scrq->irq = irq_create_mapping(NULL, scrq->hw_irq); if (scrq->irq == NO_IRQ) { rc = -EINVAL; dev_err(dev, "Error mapping irq\n"); goto req_tx_irq_failed; } rc = request_irq(scrq->irq, ibmvnic_interrupt_tx, 0, "ibmvnic_tx", scrq); if (rc) { dev_err(dev, "Couldn't register tx irq 0x%x. rc=%d\n", scrq->irq, rc); irq_dispose_mapping(scrq->irq); goto req_rx_irq_failed; } } for (i = 0; i < adapter->req_rx_queues; i++) { scrq = adapter->rx_scrq[i]; scrq->irq = irq_create_mapping(NULL, scrq->hw_irq); if (scrq->irq == NO_IRQ) { rc = -EINVAL; dev_err(dev, "Error mapping irq\n"); goto req_rx_irq_failed; } rc = request_irq(scrq->irq, ibmvnic_interrupt_rx, 0, "ibmvnic_rx", scrq); if (rc) { dev_err(dev, "Couldn't register rx irq 0x%x. rc=%d\n", scrq->irq, rc); irq_dispose_mapping(scrq->irq); goto req_rx_irq_failed; } } return rc; req_rx_irq_failed: for (j = 0; j < i; j++) free_irq(adapter->rx_scrq[j]->irq, adapter->rx_scrq[j]); irq_dispose_mapping(adapter->rx_scrq[j]->irq); i = adapter->req_tx_queues; req_tx_irq_failed: for (j = 0; j < i; j++) free_irq(adapter->tx_scrq[j]->irq, adapter->tx_scrq[j]); irq_dispose_mapping(adapter->rx_scrq[j]->irq); release_sub_crqs_no_irqs(adapter); return rc; } static void init_sub_crqs(struct ibmvnic_adapter *adapter, int retry) { struct device *dev = &adapter->vdev->dev; Loading @@ -1403,8 +1479,7 @@ static void init_sub_crqs(struct ibmvnic_adapter *adapter, int retry) union ibmvnic_crq crq; int total_queues; int more = 0; int i, j; int rc; int i; if (!retry) { /* Sub-CRQ entries are 32 byte long */ Loading Loading @@ -1483,13 +1558,6 @@ static void init_sub_crqs(struct ibmvnic_adapter *adapter, int retry) for (i = 0; i < adapter->req_tx_queues; i++) { adapter->tx_scrq[i] = allqueues[i]; adapter->tx_scrq[i]->pool_index = i; rc = request_irq(adapter->tx_scrq[i]->irq, ibmvnic_interrupt_tx, 0, "ibmvnic_tx", adapter->tx_scrq[i]); if (rc) { dev_err(dev, "Couldn't register tx irq 0x%x. rc=%d\n", adapter->tx_scrq[i]->irq, rc); goto req_tx_irq_failed; } } adapter->rx_scrq = kcalloc(adapter->req_rx_queues, Loading @@ -1500,13 +1568,6 @@ static void init_sub_crqs(struct ibmvnic_adapter *adapter, int retry) for (i = 0; i < adapter->req_rx_queues; i++) { adapter->rx_scrq[i] = allqueues[i + adapter->req_tx_queues]; adapter->rx_scrq[i]->scrq_num = i; rc = request_irq(adapter->rx_scrq[i]->irq, ibmvnic_interrupt_rx, 0, "ibmvnic_rx", adapter->rx_scrq[i]); if (rc) { dev_err(dev, "Couldn't register rx irq 0x%x. rc=%d\n", adapter->rx_scrq[i]->irq, rc); goto req_rx_irq_failed; } } memset(&crq, 0, sizeof(crq)); Loading Loading @@ -1559,15 +1620,6 @@ static void init_sub_crqs(struct ibmvnic_adapter *adapter, int retry) return; req_rx_irq_failed: for (j = 0; j < i; j++) free_irq(adapter->rx_scrq[j]->irq, adapter->rx_scrq[j]); i = adapter->req_tx_queues; req_tx_irq_failed: for (j = 0; j < i; j++) free_irq(adapter->tx_scrq[j]->irq, adapter->tx_scrq[j]); kfree(adapter->rx_scrq); adapter->rx_scrq = NULL; rx_failed: kfree(adapter->tx_scrq); adapter->tx_scrq = NULL; Loading Loading @@ -2348,9 +2400,9 @@ static void handle_request_cap_rsp(union ibmvnic_crq *crq, *req_value, (long int)be32_to_cpu(crq->request_capability_rsp. number), name); release_sub_crqs(adapter); release_sub_crqs_no_irqs(adapter); *req_value = be32_to_cpu(crq->request_capability_rsp.number); complete(&adapter->init_done); init_sub_crqs(adapter, 1); return; default: dev_err(dev, "Error %d in request cap rsp\n", Loading Loading @@ -2659,7 +2711,7 @@ static void handle_query_cap_rsp(union ibmvnic_crq *crq, out: if (atomic_read(&adapter->running_cap_queries) == 0) complete(&adapter->init_done); init_sub_crqs(adapter, 0); /* We're done querying the capabilities, initialize sub-crqs */ } Loading Loading @@ -3202,8 +3254,8 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq, dev_info(dev, "Partner initialized\n"); /* Send back a response */ rc = ibmvnic_send_crq_init_complete(adapter); if (rc == 0) send_version_xchg(adapter); if (!rc) schedule_work(&adapter->vnic_crq_init); else dev_err(dev, "Can't send initrsp rc=%ld\n", rc); break; Loading Loading @@ -3555,8 +3607,63 @@ static const struct file_operations ibmvnic_dump_ops = { .release = single_release, }; static void handle_crq_init_rsp(struct work_struct *work) { struct ibmvnic_adapter *adapter = container_of(work, struct ibmvnic_adapter, vnic_crq_init); struct device *dev = &adapter->vdev->dev; struct net_device *netdev = adapter->netdev; unsigned long timeout = msecs_to_jiffies(30000); int rc; send_version_xchg(adapter); reinit_completion(&adapter->init_done); if (!wait_for_completion_timeout(&adapter->init_done, timeout)) { dev_err(dev, "Passive init timeout\n"); goto task_failed; } do { if (adapter->renegotiate) { adapter->renegotiate = false; release_sub_crqs_no_irqs(adapter); send_cap_queries(adapter); reinit_completion(&adapter->init_done); if (!wait_for_completion_timeout(&adapter->init_done, timeout)) { dev_err(dev, "Passive init timeout\n"); goto task_failed; } } } while (adapter->renegotiate); rc = init_sub_crq_irqs(adapter); if (rc) goto task_failed; netdev->real_num_tx_queues = adapter->req_tx_queues; rc = register_netdev(netdev); if (rc) { dev_err(dev, "failed to register netdev rc=%d\n", rc); goto register_failed; } dev_info(dev, "ibmvnic registered\n"); return; register_failed: release_sub_crqs(adapter); task_failed: dev_err(dev, "Passive initialization was not successful\n"); } static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) { unsigned long timeout = msecs_to_jiffies(30000); struct ibmvnic_adapter *adapter; struct net_device *netdev; unsigned char *mac_addr_p; Loading Loading @@ -3593,6 +3700,8 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) netdev->ethtool_ops = &ibmvnic_ethtool_ops; SET_NETDEV_DEV(netdev, &dev->dev); INIT_WORK(&adapter->vnic_crq_init, handle_crq_init_rsp); spin_lock_init(&adapter->stats_lock); rc = ibmvnic_init_crq_queue(adapter); Loading Loading @@ -3635,30 +3744,26 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) ibmvnic_send_crq_init(adapter); init_completion(&adapter->init_done); wait_for_completion(&adapter->init_done); if (!wait_for_completion_timeout(&adapter->init_done, timeout)) return 0; do { adapter->renegotiate = false; init_sub_crqs(adapter, 0); reinit_completion(&adapter->init_done); wait_for_completion(&adapter->init_done); if (adapter->renegotiate) { release_sub_crqs(adapter); adapter->renegotiate = false; release_sub_crqs_no_irqs(adapter); send_cap_queries(adapter); reinit_completion(&adapter->init_done); wait_for_completion(&adapter->init_done); if (!wait_for_completion_timeout(&adapter->init_done, timeout)) return 0; } } while (adapter->renegotiate); /* if init_sub_crqs is partially successful, retry */ while (!adapter->tx_scrq || !adapter->rx_scrq) { init_sub_crqs(adapter, 1); reinit_completion(&adapter->init_done); wait_for_completion(&adapter->init_done); rc = init_sub_crq_irqs(adapter); if (rc) { dev_err(&dev->dev, "failed to initialize sub crq irqs\n"); goto free_debugfs; } netdev->real_num_tx_queues = adapter->req_tx_queues; Loading @@ -3666,12 +3771,14 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) rc = register_netdev(netdev); if (rc) { dev_err(&dev->dev, "failed to register netdev rc=%d\n", rc); goto free_debugfs; goto free_sub_crqs; } dev_info(&dev->dev, "ibmvnic registered\n"); return 0; free_sub_crqs: release_sub_crqs(adapter); free_debugfs: if (adapter->debugfs_dir && !IS_ERR(adapter->debugfs_dir)) debugfs_remove_recursive(adapter->debugfs_dir); Loading drivers/net/ethernet/ibm/ibmvnic.h +2 −0 Original line number Diff line number Diff line Loading @@ -1045,4 +1045,6 @@ struct ibmvnic_adapter { u64 opt_rxba_entries_per_subcrq; __be64 tx_rx_desc_req; u8 map_id; struct work_struct vnic_crq_init; }; Loading
drivers/net/ethernet/ibm/ibmvnic.c +167 −60 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ #include <linux/uaccess.h> #include <asm/firmware.h> #include <linux/seq_file.h> #include <linux/workqueue.h> #include "ibmvnic.h" Loading @@ -89,6 +90,7 @@ MODULE_VERSION(IBMVNIC_DRIVER_VERSION); static int ibmvnic_version = IBMVNIC_INITIAL_VERSION; static int ibmvnic_remove(struct vio_dev *); static void release_sub_crqs(struct ibmvnic_adapter *); static void release_sub_crqs_no_irqs(struct ibmvnic_adapter *); static int ibmvnic_reset_crq(struct ibmvnic_adapter *); static int ibmvnic_send_crq_init(struct ibmvnic_adapter *); static int ibmvnic_reenable_crq_queue(struct ibmvnic_adapter *); Loading Loading @@ -469,7 +471,8 @@ static int ibmvnic_open(struct net_device *netdev) crq.logical_link_state.link_state = IBMVNIC_LOGICAL_LNK_UP; ibmvnic_send_crq(adapter, &crq); netif_start_queue(netdev); netif_tx_start_all_queues(netdev); return 0; bounce_map_failed: Loading Loading @@ -519,7 +522,7 @@ static int ibmvnic_close(struct net_device *netdev) for (i = 0; i < adapter->req_rx_queues; i++) napi_disable(&adapter->napi[i]); netif_stop_queue(netdev); netif_tx_stop_all_queues(netdev); if (adapter->bounce_buffer) { if (!dma_mapping_error(dev, adapter->bounce_buffer_dma)) { Loading Loading @@ -1212,12 +1215,6 @@ static struct ibmvnic_sub_crq_queue *init_sub_crq_queue(struct ibmvnic_adapter goto reg_failed; } scrq->irq = irq_create_mapping(NULL, scrq->hw_irq); if (scrq->irq == NO_IRQ) { dev_err(dev, "Error mapping irq\n"); goto map_irq_failed; } scrq->adapter = adapter; scrq->size = 4 * PAGE_SIZE / sizeof(*scrq->msgs); scrq->cur = 0; Loading @@ -1230,12 +1227,6 @@ static struct ibmvnic_sub_crq_queue *init_sub_crq_queue(struct ibmvnic_adapter return scrq; map_irq_failed: do { rc = plpar_hcall_norets(H_FREE_SUB_CRQ, adapter->vdev->unit_address, scrq->crq_num); } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); reg_failed: dma_unmap_single(dev, scrq->msg_token, 4 * PAGE_SIZE, DMA_BIDIRECTIONAL); Loading @@ -1256,6 +1247,7 @@ static void release_sub_crqs(struct ibmvnic_adapter *adapter) if (adapter->tx_scrq[i]) { free_irq(adapter->tx_scrq[i]->irq, adapter->tx_scrq[i]); irq_dispose_mapping(adapter->tx_scrq[i]->irq); release_sub_crq_queue(adapter, adapter->tx_scrq[i]); } Loading @@ -1267,6 +1259,7 @@ static void release_sub_crqs(struct ibmvnic_adapter *adapter) if (adapter->rx_scrq[i]) { free_irq(adapter->rx_scrq[i]->irq, adapter->rx_scrq[i]); irq_dispose_mapping(adapter->rx_scrq[i]->irq); release_sub_crq_queue(adapter, adapter->rx_scrq[i]); } Loading @@ -1276,6 +1269,29 @@ static void release_sub_crqs(struct ibmvnic_adapter *adapter) adapter->requested_caps = 0; } static void release_sub_crqs_no_irqs(struct ibmvnic_adapter *adapter) { int i; if (adapter->tx_scrq) { for (i = 0; i < adapter->req_tx_queues; i++) if (adapter->tx_scrq[i]) release_sub_crq_queue(adapter, adapter->tx_scrq[i]); adapter->tx_scrq = NULL; } if (adapter->rx_scrq) { for (i = 0; i < adapter->req_rx_queues; i++) if (adapter->rx_scrq[i]) release_sub_crq_queue(adapter, adapter->rx_scrq[i]); adapter->rx_scrq = NULL; } adapter->requested_caps = 0; } static int disable_scrq_irq(struct ibmvnic_adapter *adapter, struct ibmvnic_sub_crq_queue *scrq) { Loading Loading @@ -1395,6 +1411,66 @@ static irqreturn_t ibmvnic_interrupt_rx(int irq, void *instance) return IRQ_HANDLED; } static int init_sub_crq_irqs(struct ibmvnic_adapter *adapter) { struct device *dev = &adapter->vdev->dev; struct ibmvnic_sub_crq_queue *scrq; int i = 0, j = 0; int rc = 0; for (i = 0; i < adapter->req_tx_queues; i++) { scrq = adapter->tx_scrq[i]; scrq->irq = irq_create_mapping(NULL, scrq->hw_irq); if (scrq->irq == NO_IRQ) { rc = -EINVAL; dev_err(dev, "Error mapping irq\n"); goto req_tx_irq_failed; } rc = request_irq(scrq->irq, ibmvnic_interrupt_tx, 0, "ibmvnic_tx", scrq); if (rc) { dev_err(dev, "Couldn't register tx irq 0x%x. rc=%d\n", scrq->irq, rc); irq_dispose_mapping(scrq->irq); goto req_rx_irq_failed; } } for (i = 0; i < adapter->req_rx_queues; i++) { scrq = adapter->rx_scrq[i]; scrq->irq = irq_create_mapping(NULL, scrq->hw_irq); if (scrq->irq == NO_IRQ) { rc = -EINVAL; dev_err(dev, "Error mapping irq\n"); goto req_rx_irq_failed; } rc = request_irq(scrq->irq, ibmvnic_interrupt_rx, 0, "ibmvnic_rx", scrq); if (rc) { dev_err(dev, "Couldn't register rx irq 0x%x. rc=%d\n", scrq->irq, rc); irq_dispose_mapping(scrq->irq); goto req_rx_irq_failed; } } return rc; req_rx_irq_failed: for (j = 0; j < i; j++) free_irq(adapter->rx_scrq[j]->irq, adapter->rx_scrq[j]); irq_dispose_mapping(adapter->rx_scrq[j]->irq); i = adapter->req_tx_queues; req_tx_irq_failed: for (j = 0; j < i; j++) free_irq(adapter->tx_scrq[j]->irq, adapter->tx_scrq[j]); irq_dispose_mapping(adapter->rx_scrq[j]->irq); release_sub_crqs_no_irqs(adapter); return rc; } static void init_sub_crqs(struct ibmvnic_adapter *adapter, int retry) { struct device *dev = &adapter->vdev->dev; Loading @@ -1403,8 +1479,7 @@ static void init_sub_crqs(struct ibmvnic_adapter *adapter, int retry) union ibmvnic_crq crq; int total_queues; int more = 0; int i, j; int rc; int i; if (!retry) { /* Sub-CRQ entries are 32 byte long */ Loading Loading @@ -1483,13 +1558,6 @@ static void init_sub_crqs(struct ibmvnic_adapter *adapter, int retry) for (i = 0; i < adapter->req_tx_queues; i++) { adapter->tx_scrq[i] = allqueues[i]; adapter->tx_scrq[i]->pool_index = i; rc = request_irq(adapter->tx_scrq[i]->irq, ibmvnic_interrupt_tx, 0, "ibmvnic_tx", adapter->tx_scrq[i]); if (rc) { dev_err(dev, "Couldn't register tx irq 0x%x. rc=%d\n", adapter->tx_scrq[i]->irq, rc); goto req_tx_irq_failed; } } adapter->rx_scrq = kcalloc(adapter->req_rx_queues, Loading @@ -1500,13 +1568,6 @@ static void init_sub_crqs(struct ibmvnic_adapter *adapter, int retry) for (i = 0; i < adapter->req_rx_queues; i++) { adapter->rx_scrq[i] = allqueues[i + adapter->req_tx_queues]; adapter->rx_scrq[i]->scrq_num = i; rc = request_irq(adapter->rx_scrq[i]->irq, ibmvnic_interrupt_rx, 0, "ibmvnic_rx", adapter->rx_scrq[i]); if (rc) { dev_err(dev, "Couldn't register rx irq 0x%x. rc=%d\n", adapter->rx_scrq[i]->irq, rc); goto req_rx_irq_failed; } } memset(&crq, 0, sizeof(crq)); Loading Loading @@ -1559,15 +1620,6 @@ static void init_sub_crqs(struct ibmvnic_adapter *adapter, int retry) return; req_rx_irq_failed: for (j = 0; j < i; j++) free_irq(adapter->rx_scrq[j]->irq, adapter->rx_scrq[j]); i = adapter->req_tx_queues; req_tx_irq_failed: for (j = 0; j < i; j++) free_irq(adapter->tx_scrq[j]->irq, adapter->tx_scrq[j]); kfree(adapter->rx_scrq); adapter->rx_scrq = NULL; rx_failed: kfree(adapter->tx_scrq); adapter->tx_scrq = NULL; Loading Loading @@ -2348,9 +2400,9 @@ static void handle_request_cap_rsp(union ibmvnic_crq *crq, *req_value, (long int)be32_to_cpu(crq->request_capability_rsp. number), name); release_sub_crqs(adapter); release_sub_crqs_no_irqs(adapter); *req_value = be32_to_cpu(crq->request_capability_rsp.number); complete(&adapter->init_done); init_sub_crqs(adapter, 1); return; default: dev_err(dev, "Error %d in request cap rsp\n", Loading Loading @@ -2659,7 +2711,7 @@ static void handle_query_cap_rsp(union ibmvnic_crq *crq, out: if (atomic_read(&adapter->running_cap_queries) == 0) complete(&adapter->init_done); init_sub_crqs(adapter, 0); /* We're done querying the capabilities, initialize sub-crqs */ } Loading Loading @@ -3202,8 +3254,8 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq, dev_info(dev, "Partner initialized\n"); /* Send back a response */ rc = ibmvnic_send_crq_init_complete(adapter); if (rc == 0) send_version_xchg(adapter); if (!rc) schedule_work(&adapter->vnic_crq_init); else dev_err(dev, "Can't send initrsp rc=%ld\n", rc); break; Loading Loading @@ -3555,8 +3607,63 @@ static const struct file_operations ibmvnic_dump_ops = { .release = single_release, }; static void handle_crq_init_rsp(struct work_struct *work) { struct ibmvnic_adapter *adapter = container_of(work, struct ibmvnic_adapter, vnic_crq_init); struct device *dev = &adapter->vdev->dev; struct net_device *netdev = adapter->netdev; unsigned long timeout = msecs_to_jiffies(30000); int rc; send_version_xchg(adapter); reinit_completion(&adapter->init_done); if (!wait_for_completion_timeout(&adapter->init_done, timeout)) { dev_err(dev, "Passive init timeout\n"); goto task_failed; } do { if (adapter->renegotiate) { adapter->renegotiate = false; release_sub_crqs_no_irqs(adapter); send_cap_queries(adapter); reinit_completion(&adapter->init_done); if (!wait_for_completion_timeout(&adapter->init_done, timeout)) { dev_err(dev, "Passive init timeout\n"); goto task_failed; } } } while (adapter->renegotiate); rc = init_sub_crq_irqs(adapter); if (rc) goto task_failed; netdev->real_num_tx_queues = adapter->req_tx_queues; rc = register_netdev(netdev); if (rc) { dev_err(dev, "failed to register netdev rc=%d\n", rc); goto register_failed; } dev_info(dev, "ibmvnic registered\n"); return; register_failed: release_sub_crqs(adapter); task_failed: dev_err(dev, "Passive initialization was not successful\n"); } static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) { unsigned long timeout = msecs_to_jiffies(30000); struct ibmvnic_adapter *adapter; struct net_device *netdev; unsigned char *mac_addr_p; Loading Loading @@ -3593,6 +3700,8 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) netdev->ethtool_ops = &ibmvnic_ethtool_ops; SET_NETDEV_DEV(netdev, &dev->dev); INIT_WORK(&adapter->vnic_crq_init, handle_crq_init_rsp); spin_lock_init(&adapter->stats_lock); rc = ibmvnic_init_crq_queue(adapter); Loading Loading @@ -3635,30 +3744,26 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) ibmvnic_send_crq_init(adapter); init_completion(&adapter->init_done); wait_for_completion(&adapter->init_done); if (!wait_for_completion_timeout(&adapter->init_done, timeout)) return 0; do { adapter->renegotiate = false; init_sub_crqs(adapter, 0); reinit_completion(&adapter->init_done); wait_for_completion(&adapter->init_done); if (adapter->renegotiate) { release_sub_crqs(adapter); adapter->renegotiate = false; release_sub_crqs_no_irqs(adapter); send_cap_queries(adapter); reinit_completion(&adapter->init_done); wait_for_completion(&adapter->init_done); if (!wait_for_completion_timeout(&adapter->init_done, timeout)) return 0; } } while (adapter->renegotiate); /* if init_sub_crqs is partially successful, retry */ while (!adapter->tx_scrq || !adapter->rx_scrq) { init_sub_crqs(adapter, 1); reinit_completion(&adapter->init_done); wait_for_completion(&adapter->init_done); rc = init_sub_crq_irqs(adapter); if (rc) { dev_err(&dev->dev, "failed to initialize sub crq irqs\n"); goto free_debugfs; } netdev->real_num_tx_queues = adapter->req_tx_queues; Loading @@ -3666,12 +3771,14 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) rc = register_netdev(netdev); if (rc) { dev_err(&dev->dev, "failed to register netdev rc=%d\n", rc); goto free_debugfs; goto free_sub_crqs; } dev_info(&dev->dev, "ibmvnic registered\n"); return 0; free_sub_crqs: release_sub_crqs(adapter); free_debugfs: if (adapter->debugfs_dir && !IS_ERR(adapter->debugfs_dir)) debugfs_remove_recursive(adapter->debugfs_dir); Loading
drivers/net/ethernet/ibm/ibmvnic.h +2 −0 Original line number Diff line number Diff line Loading @@ -1045,4 +1045,6 @@ struct ibmvnic_adapter { u64 opt_rxba_entries_per_subcrq; __be64 tx_rx_desc_req; u8 map_id; struct work_struct vnic_crq_init; };