From 8862541de781329b3e1e553bd936cecf998dc565 Mon Sep 17 00:00:00 2001 From: Nathan Fontenot Date: Mon, 19 Feb 2018 13:30:05 -0600 Subject: ibmvnic: Rename active queue count variables Rename the tx/rx active pool variables to be tx/rx active scrq counts. The tx/rx pools are per sub-crq so this is a more appropriate name. This also is a preparatory step for using thiese variables for handling updates to sub-crqs and napi based on the active count. Signed-off-by: Nathan Fontenot Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ibmvnic.c | 16 ++++++++-------- drivers/net/ethernet/ibm/ibmvnic.h | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 64770a1c406d..f1166efd8eb7 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -461,7 +461,7 @@ static void release_rx_pools(struct ibmvnic_adapter *adapter) if (!adapter->rx_pool) return; - for (i = 0; i < adapter->num_active_rx_pools; i++) { + for (i = 0; i < adapter->num_active_rx_scrqs; i++) { rx_pool = &adapter->rx_pool[i]; netdev_dbg(adapter->netdev, "Releasing rx_pool[%d]\n", i); @@ -484,7 +484,7 @@ static void release_rx_pools(struct ibmvnic_adapter *adapter) kfree(adapter->rx_pool); adapter->rx_pool = NULL; - adapter->num_active_rx_pools = 0; + adapter->num_active_rx_scrqs = 0; } static int init_rx_pools(struct net_device *netdev) @@ -509,7 +509,7 @@ static int init_rx_pools(struct net_device *netdev) return -1; } - adapter->num_active_rx_pools = 0; + adapter->num_active_rx_scrqs = 0; for (i = 0; i < rxadd_subcrqs; i++) { rx_pool = &adapter->rx_pool[i]; @@ -554,7 +554,7 @@ static int init_rx_pools(struct net_device *netdev) rx_pool->next_free = 0; } - adapter->num_active_rx_pools = rxadd_subcrqs; + adapter->num_active_rx_scrqs = rxadd_subcrqs; return 0; } @@ -613,7 +613,7 @@ static void release_tx_pools(struct ibmvnic_adapter *adapter) if (!adapter->tx_pool) return; - for (i = 0; i < adapter->num_active_tx_pools; i++) { + for (i = 0; i < adapter->num_active_tx_scrqs; i++) { netdev_dbg(adapter->netdev, "Releasing tx_pool[%d]\n", i); tx_pool = &adapter->tx_pool[i]; kfree(tx_pool->tx_buff); @@ -624,7 +624,7 @@ static void release_tx_pools(struct ibmvnic_adapter *adapter) kfree(adapter->tx_pool); adapter->tx_pool = NULL; - adapter->num_active_tx_pools = 0; + adapter->num_active_tx_scrqs = 0; } static int init_tx_pools(struct net_device *netdev) @@ -641,7 +641,7 @@ static int init_tx_pools(struct net_device *netdev) if (!adapter->tx_pool) return -1; - adapter->num_active_tx_pools = 0; + adapter->num_active_tx_scrqs = 0; for (i = 0; i < tx_subcrqs; i++) { tx_pool = &adapter->tx_pool[i]; @@ -690,7 +690,7 @@ static int init_tx_pools(struct net_device *netdev) tx_pool->producer_index = 0; } - adapter->num_active_tx_pools = tx_subcrqs; + adapter->num_active_tx_scrqs = tx_subcrqs; return 0; } diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h index 2f51458ccdc3..68e712c69211 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.h +++ b/drivers/net/ethernet/ibm/ibmvnic.h @@ -1092,8 +1092,8 @@ struct ibmvnic_adapter { u64 opt_rxba_entries_per_subcrq; __be64 tx_rx_desc_req; u8 map_id; - u64 num_active_rx_pools; - u64 num_active_tx_pools; + u64 num_active_rx_scrqs; + u64 num_active_tx_scrqs; struct tasklet_struct tasklet; enum vnic_state state; -- cgit v1.2.3 From d9043c102e73b9abc01f2120d47ba8195823172a Mon Sep 17 00:00:00 2001 From: Nathan Fontenot Date: Mon, 19 Feb 2018 13:30:14 -0600 Subject: ibmvnic: Move active sub-crq count settings Inpreparation for using the active scrq count to track more active resources, move the setting of the active count to after initialization occurs in initial driver init and during driver reset. Signed-off-by: Nathan Fontenot Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ibmvnic.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index f1166efd8eb7..0c9adeffbe46 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -484,7 +484,6 @@ static void release_rx_pools(struct ibmvnic_adapter *adapter) kfree(adapter->rx_pool); adapter->rx_pool = NULL; - adapter->num_active_rx_scrqs = 0; } static int init_rx_pools(struct net_device *netdev) @@ -509,8 +508,6 @@ static int init_rx_pools(struct net_device *netdev) return -1; } - adapter->num_active_rx_scrqs = 0; - for (i = 0; i < rxadd_subcrqs; i++) { rx_pool = &adapter->rx_pool[i]; @@ -554,8 +551,6 @@ static int init_rx_pools(struct net_device *netdev) rx_pool->next_free = 0; } - adapter->num_active_rx_scrqs = rxadd_subcrqs; - return 0; } @@ -624,7 +619,6 @@ static void release_tx_pools(struct ibmvnic_adapter *adapter) kfree(adapter->tx_pool); adapter->tx_pool = NULL; - adapter->num_active_tx_scrqs = 0; } static int init_tx_pools(struct net_device *netdev) @@ -641,8 +635,6 @@ static int init_tx_pools(struct net_device *netdev) if (!adapter->tx_pool) return -1; - adapter->num_active_tx_scrqs = 0; - for (i = 0; i < tx_subcrqs; i++) { tx_pool = &adapter->tx_pool[i]; @@ -690,8 +682,6 @@ static int init_tx_pools(struct net_device *netdev) tx_pool->producer_index = 0; } - adapter->num_active_tx_scrqs = tx_subcrqs; - return 0; } @@ -991,6 +981,10 @@ static int init_resources(struct ibmvnic_adapter *adapter) return rc; rc = init_tx_pools(netdev); + + adapter->num_active_tx_scrqs = adapter->req_tx_queues; + adapter->num_active_rx_scrqs = adapter->req_rx_queues; + return rc; } @@ -1692,6 +1686,9 @@ static int do_reset(struct ibmvnic_adapter *adapter, release_tx_pools(adapter); init_rx_pools(netdev); init_tx_pools(netdev); + + adapter->num_active_tx_scrqs = adapter->req_tx_queues; + adapter->num_active_rx_scrqs = adapter->req_rx_queues; } else { rc = reset_tx_pools(adapter); if (rc) -- cgit v1.2.3 From d7c0ef36bde03af0d119d895bba4cc0362e79dbb Mon Sep 17 00:00:00 2001 From: Nathan Fontenot Date: Mon, 19 Feb 2018 13:30:31 -0600 Subject: ibmvnic: Free and re-allocate scrqs when tx/rx scrqs change When the driver resets it is possible that the number of tx/rx sub-crqs can change. This patch handles this so that the driver does not try to access non-existent sub-crqs. The count for releasing sub crqs depends on the adapter state. The active queue count is not set in probe, so if we are relasing in probe state we use the request queue count. Additionally, a parameter is added to release_sub_crqs() so that we know if the h_call to free the sub-crq needs to be made. In the reset path we have to do a reset of the main crq, which is a free followed by a register of the main crq. The free of main crq results in all of the sub crq's being free'ed. When updating sub-crq count in the reset path we do not want to h_free the sub-crqs, they are already free'ed. Signed-off-by: Nathan Fontenot Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ibmvnic.c | 78 +++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 0c9adeffbe46..33cfd277f008 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -90,7 +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(struct ibmvnic_adapter *, bool); 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 *); @@ -740,7 +740,7 @@ static int ibmvnic_login(struct net_device *netdev) do { if (adapter->renegotiate) { adapter->renegotiate = false; - release_sub_crqs(adapter); + release_sub_crqs(adapter, 1); reinit_completion(&adapter->init_done); send_cap_queries(adapter); @@ -1648,7 +1648,7 @@ static int do_reset(struct ibmvnic_adapter *adapter, if (adapter->reset_reason == VNIC_RESET_CHANGE_PARAM || adapter->wait_for_reset) { release_resources(adapter); - release_sub_crqs(adapter); + release_sub_crqs(adapter, 1); release_crq_queue(adapter); } @@ -2288,24 +2288,27 @@ static int reset_sub_crq_queues(struct ibmvnic_adapter *adapter) } static void release_sub_crq_queue(struct ibmvnic_adapter *adapter, - struct ibmvnic_sub_crq_queue *scrq) + struct ibmvnic_sub_crq_queue *scrq, + bool do_h_free) { struct device *dev = &adapter->vdev->dev; long rc; netdev_dbg(adapter->netdev, "Releasing sub-CRQ\n"); - /* Close the sub-crqs */ - 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)); + if (do_h_free) { + /* Close the sub-crqs */ + 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)); - if (rc) { - netdev_err(adapter->netdev, - "Failed to release sub-CRQ %16lx, rc = %ld\n", - scrq->crq_num, rc); + if (rc) { + netdev_err(adapter->netdev, + "Failed to release sub-CRQ %16lx, rc = %ld\n", + scrq->crq_num, rc); + } } dma_unmap_single(dev, scrq->msg_token, 4 * PAGE_SIZE, @@ -2373,12 +2376,21 @@ zero_page_failed: return NULL; } -static void release_sub_crqs(struct ibmvnic_adapter *adapter) +static void release_sub_crqs(struct ibmvnic_adapter *adapter, bool do_h_free) { + u64 num_tx_scrqs, num_rx_scrqs; int i; + if (adapter->state == VNIC_PROBED) { + num_tx_scrqs = adapter->req_tx_queues; + num_rx_scrqs = adapter->req_rx_queues; + } else { + num_tx_scrqs = adapter->num_active_tx_scrqs; + num_rx_scrqs = adapter->num_active_rx_scrqs; + } + if (adapter->tx_scrq) { - for (i = 0; i < adapter->req_tx_queues; i++) { + for (i = 0; i < num_tx_scrqs; i++) { if (!adapter->tx_scrq[i]) continue; @@ -2391,7 +2403,8 @@ static void release_sub_crqs(struct ibmvnic_adapter *adapter) adapter->tx_scrq[i]->irq = 0; } - release_sub_crq_queue(adapter, adapter->tx_scrq[i]); + release_sub_crq_queue(adapter, adapter->tx_scrq[i], + do_h_free); } kfree(adapter->tx_scrq); @@ -2399,7 +2412,7 @@ static void release_sub_crqs(struct ibmvnic_adapter *adapter) } if (adapter->rx_scrq) { - for (i = 0; i < adapter->req_rx_queues; i++) { + for (i = 0; i < num_rx_scrqs; i++) { if (!adapter->rx_scrq[i]) continue; @@ -2412,7 +2425,8 @@ static void release_sub_crqs(struct ibmvnic_adapter *adapter) adapter->rx_scrq[i]->irq = 0; } - release_sub_crq_queue(adapter, adapter->rx_scrq[i]); + release_sub_crq_queue(adapter, adapter->rx_scrq[i], + do_h_free); } kfree(adapter->rx_scrq); @@ -2622,7 +2636,7 @@ req_tx_irq_failed: free_irq(adapter->tx_scrq[j]->irq, adapter->tx_scrq[j]); irq_dispose_mapping(adapter->rx_scrq[j]->irq); } - release_sub_crqs(adapter); + release_sub_crqs(adapter, 1); return rc; } @@ -2704,7 +2718,7 @@ rx_failed: adapter->tx_scrq = NULL; tx_failed: for (i = 0; i < registered_queues; i++) - release_sub_crq_queue(adapter, allqueues[i]); + release_sub_crq_queue(adapter, allqueues[i], 1); kfree(allqueues); return -1; } @@ -4331,6 +4345,7 @@ static int ibmvnic_init(struct ibmvnic_adapter *adapter) { struct device *dev = &adapter->vdev->dev; unsigned long timeout = msecs_to_jiffies(30000); + u64 old_num_rx_queues, old_num_tx_queues; int rc; if (adapter->resetting && !adapter->wait_for_reset) { @@ -4348,6 +4363,9 @@ static int ibmvnic_init(struct ibmvnic_adapter *adapter) adapter->from_passive_init = false; + old_num_rx_queues = adapter->req_rx_queues; + old_num_tx_queues = adapter->req_tx_queues; + init_completion(&adapter->init_done); adapter->init_done_rc = 0; ibmvnic_send_crq_init(adapter); @@ -4367,10 +4385,18 @@ static int ibmvnic_init(struct ibmvnic_adapter *adapter) return -1; } - if (adapter->resetting && !adapter->wait_for_reset) - rc = reset_sub_crq_queues(adapter); - else + if (adapter->resetting && !adapter->wait_for_reset) { + if (adapter->req_rx_queues != old_num_rx_queues || + adapter->req_tx_queues != old_num_tx_queues) { + release_sub_crqs(adapter, 0); + rc = init_sub_crqs(adapter); + } else { + rc = reset_sub_crq_queues(adapter); + } + } else { rc = init_sub_crqs(adapter); + } + if (rc) { dev_err(dev, "Initialization of sub crqs failed\n"); release_crq_queue(adapter); @@ -4470,7 +4496,7 @@ ibmvnic_register_fail: device_remove_file(&dev->dev, &dev_attr_failover); ibmvnic_init_fail: - release_sub_crqs(adapter); + release_sub_crqs(adapter, 1); release_crq_queue(adapter); free_netdev(netdev); @@ -4487,7 +4513,7 @@ static int ibmvnic_remove(struct vio_dev *dev) mutex_lock(&adapter->reset_lock); release_resources(adapter); - release_sub_crqs(adapter); + release_sub_crqs(adapter, 1); release_crq_queue(adapter); adapter->state = VNIC_REMOVED; -- cgit v1.2.3 From 86f669b2b7491b5697d9e63538c960ad7e94c6cc Mon Sep 17 00:00:00 2001 From: Nathan Fontenot Date: Mon, 19 Feb 2018 13:30:39 -0600 Subject: ibmvnic: Make napi usage dynamic In order to handle the number of rx sub crqs changing during a driver reset, the ibmvnic driver also needs to update the number of napi. To do this the code to init and free napi's is moved to their own routines so they can be called during the reset process. Signed-off-by: Nathan Fontenot Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ibmvnic.c | 70 ++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 33cfd277f008..7dc67de269f5 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -730,6 +730,43 @@ static void ibmvnic_napi_disable(struct ibmvnic_adapter *adapter) adapter->napi_enabled = false; } +static int init_napi(struct ibmvnic_adapter *adapter) +{ + int i; + + adapter->napi = kcalloc(adapter->req_rx_queues, + sizeof(struct napi_struct), GFP_KERNEL); + if (!adapter->napi) + return -ENOMEM; + + for (i = 0; i < adapter->req_rx_queues; i++) { + netdev_dbg(adapter->netdev, "Adding napi[%d]\n", i); + netif_napi_add(adapter->netdev, &adapter->napi[i], + ibmvnic_poll, NAPI_POLL_WEIGHT); + } + + return 0; +} + +static void release_napi(struct ibmvnic_adapter *adapter) +{ + int i; + + if (!adapter->napi) + return; + + for (i = 0; i < adapter->num_active_rx_scrqs; i++) { + if (&adapter->napi[i]) { + netdev_dbg(adapter->netdev, + "Releasing napi[%d]\n", i); + netif_napi_del(&adapter->napi[i]); + } + } + + kfree(adapter->napi); + adapter->napi = NULL; +} + static int ibmvnic_login(struct net_device *netdev) { struct ibmvnic_adapter *adapter = netdev_priv(netdev); @@ -795,8 +832,6 @@ static void release_login_rsp_buffer(struct ibmvnic_adapter *adapter) static void release_resources(struct ibmvnic_adapter *adapter) { - int i; - release_vpd_data(adapter); release_tx_pools(adapter); @@ -805,19 +840,7 @@ static void release_resources(struct ibmvnic_adapter *adapter) release_stats_token(adapter); release_stats_buffers(adapter); release_error_buffers(adapter); - - if (adapter->napi) { - for (i = 0; i < adapter->req_rx_queues; i++) { - if (&adapter->napi[i]) { - netdev_dbg(adapter->netdev, - "Releasing napi[%d]\n", i); - netif_napi_del(&adapter->napi[i]); - } - } - } - kfree(adapter->napi); - adapter->napi = NULL; - + release_napi(adapter); release_login_rsp_buffer(adapter); } @@ -937,7 +960,7 @@ static int ibmvnic_get_vpd(struct ibmvnic_adapter *adapter) static int init_resources(struct ibmvnic_adapter *adapter) { struct net_device *netdev = adapter->netdev; - int i, rc; + int rc; rc = set_real_num_queues(netdev); if (rc) @@ -963,16 +986,10 @@ static int init_resources(struct ibmvnic_adapter *adapter) } adapter->map_id = 1; - adapter->napi = kcalloc(adapter->req_rx_queues, - sizeof(struct napi_struct), GFP_KERNEL); - if (!adapter->napi) - return -ENOMEM; - for (i = 0; i < adapter->req_rx_queues; i++) { - netdev_dbg(netdev, "Adding napi[%d]\n", i); - netif_napi_add(netdev, &adapter->napi[i], ibmvnic_poll, - NAPI_POLL_WEIGHT); - } + rc = init_napi(adapter); + if (rc) + return rc; send_map_query(adapter); @@ -1687,6 +1704,9 @@ static int do_reset(struct ibmvnic_adapter *adapter, init_rx_pools(netdev); init_tx_pools(netdev); + release_napi(adapter); + init_napi(adapter); + adapter->num_active_tx_scrqs = adapter->req_tx_queues; adapter->num_active_rx_scrqs = adapter->req_rx_queues; } else { -- cgit v1.2.3 From abcae546f7b49f02f4b73d6cc8b33c2fc5f2f8a4 Mon Sep 17 00:00:00 2001 From: Nathan Fontenot Date: Mon, 19 Feb 2018 13:30:47 -0600 Subject: ibmvnic: Allocate max queues stats buffers To avoid losing any stats when the number of sub-crqs change, allocate the max number of stats buffers so a stats buffer exists all possible sub-crqs. Signed-off-by: Nathan Fontenot Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ibmvnic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 7dc67de269f5..ad0f9cc1be04 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -361,14 +361,14 @@ static void release_stats_buffers(struct ibmvnic_adapter *adapter) static int init_stats_buffers(struct ibmvnic_adapter *adapter) { adapter->tx_stats_buffers = - kcalloc(adapter->req_tx_queues, + kcalloc(IBMVNIC_MAX_QUEUES, sizeof(struct ibmvnic_tx_queue_stats), GFP_KERNEL); if (!adapter->tx_stats_buffers) return -ENOMEM; adapter->rx_stats_buffers = - kcalloc(adapter->req_rx_queues, + kcalloc(IBMVNIC_MAX_QUEUES, sizeof(struct ibmvnic_rx_queue_stats), GFP_KERNEL); if (!adapter->rx_stats_buffers) -- cgit v1.2.3