Skip to content

Commit d7c0ef3

Browse files
nfontdavem330
authored andcommitted
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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d9043c1 commit d7c0ef3

File tree

1 file changed

+52
-26
lines changed

1 file changed

+52
-26
lines changed

drivers/net/ethernet/ibm/ibmvnic.c

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ MODULE_VERSION(IBMVNIC_DRIVER_VERSION);
9090

9191
static int ibmvnic_version = IBMVNIC_INITIAL_VERSION;
9292
static int ibmvnic_remove(struct vio_dev *);
93-
static void release_sub_crqs(struct ibmvnic_adapter *);
93+
static void release_sub_crqs(struct ibmvnic_adapter *, bool);
9494
static int ibmvnic_reset_crq(struct ibmvnic_adapter *);
9595
static int ibmvnic_send_crq_init(struct ibmvnic_adapter *);
9696
static int ibmvnic_reenable_crq_queue(struct ibmvnic_adapter *);
@@ -740,7 +740,7 @@ static int ibmvnic_login(struct net_device *netdev)
740740
do {
741741
if (adapter->renegotiate) {
742742
adapter->renegotiate = false;
743-
release_sub_crqs(adapter);
743+
release_sub_crqs(adapter, 1);
744744

745745
reinit_completion(&adapter->init_done);
746746
send_cap_queries(adapter);
@@ -1648,7 +1648,7 @@ static int do_reset(struct ibmvnic_adapter *adapter,
16481648
if (adapter->reset_reason == VNIC_RESET_CHANGE_PARAM ||
16491649
adapter->wait_for_reset) {
16501650
release_resources(adapter);
1651-
release_sub_crqs(adapter);
1651+
release_sub_crqs(adapter, 1);
16521652
release_crq_queue(adapter);
16531653
}
16541654

@@ -2288,24 +2288,27 @@ static int reset_sub_crq_queues(struct ibmvnic_adapter *adapter)
22882288
}
22892289

22902290
static void release_sub_crq_queue(struct ibmvnic_adapter *adapter,
2291-
struct ibmvnic_sub_crq_queue *scrq)
2291+
struct ibmvnic_sub_crq_queue *scrq,
2292+
bool do_h_free)
22922293
{
22932294
struct device *dev = &adapter->vdev->dev;
22942295
long rc;
22952296

22962297
netdev_dbg(adapter->netdev, "Releasing sub-CRQ\n");
22972298

2298-
/* Close the sub-crqs */
2299-
do {
2300-
rc = plpar_hcall_norets(H_FREE_SUB_CRQ,
2301-
adapter->vdev->unit_address,
2302-
scrq->crq_num);
2303-
} while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
2299+
if (do_h_free) {
2300+
/* Close the sub-crqs */
2301+
do {
2302+
rc = plpar_hcall_norets(H_FREE_SUB_CRQ,
2303+
adapter->vdev->unit_address,
2304+
scrq->crq_num);
2305+
} while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
23042306

2305-
if (rc) {
2306-
netdev_err(adapter->netdev,
2307-
"Failed to release sub-CRQ %16lx, rc = %ld\n",
2308-
scrq->crq_num, rc);
2307+
if (rc) {
2308+
netdev_err(adapter->netdev,
2309+
"Failed to release sub-CRQ %16lx, rc = %ld\n",
2310+
scrq->crq_num, rc);
2311+
}
23092312
}
23102313

23112314
dma_unmap_single(dev, scrq->msg_token, 4 * PAGE_SIZE,
@@ -2373,12 +2376,21 @@ static struct ibmvnic_sub_crq_queue *init_sub_crq_queue(struct ibmvnic_adapter
23732376
return NULL;
23742377
}
23752378

2376-
static void release_sub_crqs(struct ibmvnic_adapter *adapter)
2379+
static void release_sub_crqs(struct ibmvnic_adapter *adapter, bool do_h_free)
23772380
{
2381+
u64 num_tx_scrqs, num_rx_scrqs;
23782382
int i;
23792383

2384+
if (adapter->state == VNIC_PROBED) {
2385+
num_tx_scrqs = adapter->req_tx_queues;
2386+
num_rx_scrqs = adapter->req_rx_queues;
2387+
} else {
2388+
num_tx_scrqs = adapter->num_active_tx_scrqs;
2389+
num_rx_scrqs = adapter->num_active_rx_scrqs;
2390+
}
2391+
23802392
if (adapter->tx_scrq) {
2381-
for (i = 0; i < adapter->req_tx_queues; i++) {
2393+
for (i = 0; i < num_tx_scrqs; i++) {
23822394
if (!adapter->tx_scrq[i])
23832395
continue;
23842396

@@ -2391,15 +2403,16 @@ static void release_sub_crqs(struct ibmvnic_adapter *adapter)
23912403
adapter->tx_scrq[i]->irq = 0;
23922404
}
23932405

2394-
release_sub_crq_queue(adapter, adapter->tx_scrq[i]);
2406+
release_sub_crq_queue(adapter, adapter->tx_scrq[i],
2407+
do_h_free);
23952408
}
23962409

23972410
kfree(adapter->tx_scrq);
23982411
adapter->tx_scrq = NULL;
23992412
}
24002413

24012414
if (adapter->rx_scrq) {
2402-
for (i = 0; i < adapter->req_rx_queues; i++) {
2415+
for (i = 0; i < num_rx_scrqs; i++) {
24032416
if (!adapter->rx_scrq[i])
24042417
continue;
24052418

@@ -2412,7 +2425,8 @@ static void release_sub_crqs(struct ibmvnic_adapter *adapter)
24122425
adapter->rx_scrq[i]->irq = 0;
24132426
}
24142427

2415-
release_sub_crq_queue(adapter, adapter->rx_scrq[i]);
2428+
release_sub_crq_queue(adapter, adapter->rx_scrq[i],
2429+
do_h_free);
24162430
}
24172431

24182432
kfree(adapter->rx_scrq);
@@ -2622,7 +2636,7 @@ static int init_sub_crq_irqs(struct ibmvnic_adapter *adapter)
26222636
free_irq(adapter->tx_scrq[j]->irq, adapter->tx_scrq[j]);
26232637
irq_dispose_mapping(adapter->rx_scrq[j]->irq);
26242638
}
2625-
release_sub_crqs(adapter);
2639+
release_sub_crqs(adapter, 1);
26262640
return rc;
26272641
}
26282642

@@ -2704,7 +2718,7 @@ static int init_sub_crqs(struct ibmvnic_adapter *adapter)
27042718
adapter->tx_scrq = NULL;
27052719
tx_failed:
27062720
for (i = 0; i < registered_queues; i++)
2707-
release_sub_crq_queue(adapter, allqueues[i]);
2721+
release_sub_crq_queue(adapter, allqueues[i], 1);
27082722
kfree(allqueues);
27092723
return -1;
27102724
}
@@ -4331,6 +4345,7 @@ static int ibmvnic_init(struct ibmvnic_adapter *adapter)
43314345
{
43324346
struct device *dev = &adapter->vdev->dev;
43334347
unsigned long timeout = msecs_to_jiffies(30000);
4348+
u64 old_num_rx_queues, old_num_tx_queues;
43344349
int rc;
43354350

43364351
if (adapter->resetting && !adapter->wait_for_reset) {
@@ -4348,6 +4363,9 @@ static int ibmvnic_init(struct ibmvnic_adapter *adapter)
43484363

43494364
adapter->from_passive_init = false;
43504365

4366+
old_num_rx_queues = adapter->req_rx_queues;
4367+
old_num_tx_queues = adapter->req_tx_queues;
4368+
43514369
init_completion(&adapter->init_done);
43524370
adapter->init_done_rc = 0;
43534371
ibmvnic_send_crq_init(adapter);
@@ -4367,10 +4385,18 @@ static int ibmvnic_init(struct ibmvnic_adapter *adapter)
43674385
return -1;
43684386
}
43694387

4370-
if (adapter->resetting && !adapter->wait_for_reset)
4371-
rc = reset_sub_crq_queues(adapter);
4372-
else
4388+
if (adapter->resetting && !adapter->wait_for_reset) {
4389+
if (adapter->req_rx_queues != old_num_rx_queues ||
4390+
adapter->req_tx_queues != old_num_tx_queues) {
4391+
release_sub_crqs(adapter, 0);
4392+
rc = init_sub_crqs(adapter);
4393+
} else {
4394+
rc = reset_sub_crq_queues(adapter);
4395+
}
4396+
} else {
43734397
rc = init_sub_crqs(adapter);
4398+
}
4399+
43744400
if (rc) {
43754401
dev_err(dev, "Initialization of sub crqs failed\n");
43764402
release_crq_queue(adapter);
@@ -4470,7 +4496,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
44704496
device_remove_file(&dev->dev, &dev_attr_failover);
44714497

44724498
ibmvnic_init_fail:
4473-
release_sub_crqs(adapter);
4499+
release_sub_crqs(adapter, 1);
44744500
release_crq_queue(adapter);
44754501
free_netdev(netdev);
44764502

@@ -4487,7 +4513,7 @@ static int ibmvnic_remove(struct vio_dev *dev)
44874513
mutex_lock(&adapter->reset_lock);
44884514

44894515
release_resources(adapter);
4490-
release_sub_crqs(adapter);
4516+
release_sub_crqs(adapter, 1);
44914517
release_crq_queue(adapter);
44924518

44934519
adapter->state = VNIC_REMOVED;

0 commit comments

Comments
 (0)