|
@@ -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 *);
|
|
@@ -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)
|
|
@@ -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,6 @@ static void release_rx_pools(struct ibmvnic_adapter *adapter)
|
|
|
|
|
|
kfree(adapter->rx_pool);
|
|
|
adapter->rx_pool = NULL;
|
|
|
- adapter->num_active_rx_pools = 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_pools = 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_pools = rxadd_subcrqs;
|
|
|
-
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -613,7 +608,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 +619,6 @@ static void release_tx_pools(struct ibmvnic_adapter *adapter)
|
|
|
|
|
|
kfree(adapter->tx_pool);
|
|
|
adapter->tx_pool = NULL;
|
|
|
- adapter->num_active_tx_pools = 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_pools = 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_pools = tx_subcrqs;
|
|
|
-
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -740,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);
|
|
@@ -750,7 +777,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);
|
|
@@ -805,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);
|
|
@@ -815,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);
|
|
|
}
|
|
|
|
|
@@ -947,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)
|
|
@@ -973,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);
|
|
|
|
|
@@ -991,6 +998,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;
|
|
|
}
|
|
|
|
|
@@ -1654,7 +1665,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);
|
|
|
}
|
|
|
|
|
@@ -1692,6 +1703,12 @@ static int do_reset(struct ibmvnic_adapter *adapter,
|
|
|
release_tx_pools(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 {
|
|
|
rc = reset_tx_pools(adapter);
|
|
|
if (rc)
|
|
@@ -2291,24 +2308,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,
|
|
@@ -2376,12 +2396,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;
|
|
|
|
|
@@ -2394,7 +2423,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);
|
|
@@ -2402,7 +2432,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;
|
|
|
|
|
@@ -2415,7 +2445,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);
|
|
@@ -2625,7 +2656,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;
|
|
|
}
|
|
|
|
|
@@ -2707,7 +2738,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;
|
|
|
}
|
|
@@ -4334,6 +4365,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) {
|
|
@@ -4351,6 +4383,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);
|
|
@@ -4370,10 +4405,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);
|
|
@@ -4473,7 +4516,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);
|
|
|
|
|
@@ -4490,7 +4533,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;
|