diff options
author | Thomas Falcon <tlfalcon@linux.vnet.ibm.com> | 2016-07-06 16:35:17 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-07-09 17:42:10 -0400 |
commit | ea22d51a7831b062978fcf07c3c5ac7ecbb6cbeb (patch) | |
tree | 795cdfad488a8a09a17b0c32c836395f7817fdf3 /drivers/net/ethernet/ibm | |
parent | 88eb98a0178219e1d6e9037b71d293f19b89eef2 (diff) |
ibmvnic: simplify and improve driver probe function
This patch creates a function that handles sub-CRQ IRQ creation
separately from sub-CRQ initialization. Another function is then needed
to release sub-CRQ resources prior to sub-CRQ IRQ creation.
These additions allow the driver probe function to be simplified,
specifically during the VNIC Server login process. A timeout is also
included while waiting for completion of the login process in case
the VNIC Server is not available or some other error occurs.
Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/ibm')
-rw-r--r-- | drivers/net/ethernet/ibm/ibmvnic.c | 159 |
1 files changed, 103 insertions, 56 deletions
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 79d2ab360805..52b0c07d3ca4 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c | |||
@@ -89,6 +89,7 @@ MODULE_VERSION(IBMVNIC_DRIVER_VERSION); | |||
89 | static int ibmvnic_version = IBMVNIC_INITIAL_VERSION; | 89 | static int ibmvnic_version = IBMVNIC_INITIAL_VERSION; |
90 | static int ibmvnic_remove(struct vio_dev *); | 90 | static int ibmvnic_remove(struct vio_dev *); |
91 | static void release_sub_crqs(struct ibmvnic_adapter *); | 91 | static void release_sub_crqs(struct ibmvnic_adapter *); |
92 | static void release_sub_crqs_no_irqs(struct ibmvnic_adapter *); | ||
92 | static int ibmvnic_reset_crq(struct ibmvnic_adapter *); | 93 | static int ibmvnic_reset_crq(struct ibmvnic_adapter *); |
93 | static int ibmvnic_send_crq_init(struct ibmvnic_adapter *); | 94 | static int ibmvnic_send_crq_init(struct ibmvnic_adapter *); |
94 | static int ibmvnic_reenable_crq_queue(struct ibmvnic_adapter *); | 95 | static int ibmvnic_reenable_crq_queue(struct ibmvnic_adapter *); |
@@ -1213,12 +1214,6 @@ static struct ibmvnic_sub_crq_queue *init_sub_crq_queue(struct ibmvnic_adapter | |||
1213 | goto reg_failed; | 1214 | goto reg_failed; |
1214 | } | 1215 | } |
1215 | 1216 | ||
1216 | scrq->irq = irq_create_mapping(NULL, scrq->hw_irq); | ||
1217 | if (scrq->irq == NO_IRQ) { | ||
1218 | dev_err(dev, "Error mapping irq\n"); | ||
1219 | goto map_irq_failed; | ||
1220 | } | ||
1221 | |||
1222 | scrq->adapter = adapter; | 1217 | scrq->adapter = adapter; |
1223 | scrq->size = 4 * PAGE_SIZE / sizeof(*scrq->msgs); | 1218 | scrq->size = 4 * PAGE_SIZE / sizeof(*scrq->msgs); |
1224 | scrq->cur = 0; | 1219 | scrq->cur = 0; |
@@ -1231,12 +1226,6 @@ static struct ibmvnic_sub_crq_queue *init_sub_crq_queue(struct ibmvnic_adapter | |||
1231 | 1226 | ||
1232 | return scrq; | 1227 | return scrq; |
1233 | 1228 | ||
1234 | map_irq_failed: | ||
1235 | do { | ||
1236 | rc = plpar_hcall_norets(H_FREE_SUB_CRQ, | ||
1237 | adapter->vdev->unit_address, | ||
1238 | scrq->crq_num); | ||
1239 | } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); | ||
1240 | reg_failed: | 1229 | reg_failed: |
1241 | dma_unmap_single(dev, scrq->msg_token, 4 * PAGE_SIZE, | 1230 | dma_unmap_single(dev, scrq->msg_token, 4 * PAGE_SIZE, |
1242 | DMA_BIDIRECTIONAL); | 1231 | DMA_BIDIRECTIONAL); |
@@ -1279,6 +1268,29 @@ static void release_sub_crqs(struct ibmvnic_adapter *adapter) | |||
1279 | adapter->requested_caps = 0; | 1268 | adapter->requested_caps = 0; |
1280 | } | 1269 | } |
1281 | 1270 | ||
1271 | static void release_sub_crqs_no_irqs(struct ibmvnic_adapter *adapter) | ||
1272 | { | ||
1273 | int i; | ||
1274 | |||
1275 | if (adapter->tx_scrq) { | ||
1276 | for (i = 0; i < adapter->req_tx_queues; i++) | ||
1277 | if (adapter->tx_scrq[i]) | ||
1278 | release_sub_crq_queue(adapter, | ||
1279 | adapter->tx_scrq[i]); | ||
1280 | adapter->tx_scrq = NULL; | ||
1281 | } | ||
1282 | |||
1283 | if (adapter->rx_scrq) { | ||
1284 | for (i = 0; i < adapter->req_rx_queues; i++) | ||
1285 | if (adapter->rx_scrq[i]) | ||
1286 | release_sub_crq_queue(adapter, | ||
1287 | adapter->rx_scrq[i]); | ||
1288 | adapter->rx_scrq = NULL; | ||
1289 | } | ||
1290 | |||
1291 | adapter->requested_caps = 0; | ||
1292 | } | ||
1293 | |||
1282 | static int disable_scrq_irq(struct ibmvnic_adapter *adapter, | 1294 | static int disable_scrq_irq(struct ibmvnic_adapter *adapter, |
1283 | struct ibmvnic_sub_crq_queue *scrq) | 1295 | struct ibmvnic_sub_crq_queue *scrq) |
1284 | { | 1296 | { |
@@ -1398,6 +1410,66 @@ static irqreturn_t ibmvnic_interrupt_rx(int irq, void *instance) | |||
1398 | return IRQ_HANDLED; | 1410 | return IRQ_HANDLED; |
1399 | } | 1411 | } |
1400 | 1412 | ||
1413 | static int init_sub_crq_irqs(struct ibmvnic_adapter *adapter) | ||
1414 | { | ||
1415 | struct device *dev = &adapter->vdev->dev; | ||
1416 | struct ibmvnic_sub_crq_queue *scrq; | ||
1417 | int i = 0, j = 0; | ||
1418 | int rc = 0; | ||
1419 | |||
1420 | for (i = 0; i < adapter->req_tx_queues; i++) { | ||
1421 | scrq = adapter->tx_scrq[i]; | ||
1422 | scrq->irq = irq_create_mapping(NULL, scrq->hw_irq); | ||
1423 | |||
1424 | if (scrq->irq == NO_IRQ) { | ||
1425 | rc = -EINVAL; | ||
1426 | dev_err(dev, "Error mapping irq\n"); | ||
1427 | goto req_tx_irq_failed; | ||
1428 | } | ||
1429 | |||
1430 | rc = request_irq(scrq->irq, ibmvnic_interrupt_tx, | ||
1431 | 0, "ibmvnic_tx", scrq); | ||
1432 | |||
1433 | if (rc) { | ||
1434 | dev_err(dev, "Couldn't register tx irq 0x%x. rc=%d\n", | ||
1435 | scrq->irq, rc); | ||
1436 | irq_dispose_mapping(scrq->irq); | ||
1437 | goto req_rx_irq_failed; | ||
1438 | } | ||
1439 | } | ||
1440 | |||
1441 | for (i = 0; i < adapter->req_rx_queues; i++) { | ||
1442 | scrq = adapter->rx_scrq[i]; | ||
1443 | scrq->irq = irq_create_mapping(NULL, scrq->hw_irq); | ||
1444 | if (scrq->irq == NO_IRQ) { | ||
1445 | rc = -EINVAL; | ||
1446 | dev_err(dev, "Error mapping irq\n"); | ||
1447 | goto req_rx_irq_failed; | ||
1448 | } | ||
1449 | rc = request_irq(scrq->irq, ibmvnic_interrupt_rx, | ||
1450 | 0, "ibmvnic_rx", scrq); | ||
1451 | if (rc) { | ||
1452 | dev_err(dev, "Couldn't register rx irq 0x%x. rc=%d\n", | ||
1453 | scrq->irq, rc); | ||
1454 | irq_dispose_mapping(scrq->irq); | ||
1455 | goto req_rx_irq_failed; | ||
1456 | } | ||
1457 | } | ||
1458 | return rc; | ||
1459 | |||
1460 | req_rx_irq_failed: | ||
1461 | for (j = 0; j < i; j++) | ||
1462 | free_irq(adapter->rx_scrq[j]->irq, adapter->rx_scrq[j]); | ||
1463 | irq_dispose_mapping(adapter->rx_scrq[j]->irq); | ||
1464 | i = adapter->req_tx_queues; | ||
1465 | req_tx_irq_failed: | ||
1466 | for (j = 0; j < i; j++) | ||
1467 | free_irq(adapter->tx_scrq[j]->irq, adapter->tx_scrq[j]); | ||
1468 | irq_dispose_mapping(adapter->rx_scrq[j]->irq); | ||
1469 | release_sub_crqs_no_irqs(adapter); | ||
1470 | return rc; | ||
1471 | } | ||
1472 | |||
1401 | static void init_sub_crqs(struct ibmvnic_adapter *adapter, int retry) | 1473 | static void init_sub_crqs(struct ibmvnic_adapter *adapter, int retry) |
1402 | { | 1474 | { |
1403 | struct device *dev = &adapter->vdev->dev; | 1475 | struct device *dev = &adapter->vdev->dev; |
@@ -1406,8 +1478,7 @@ static void init_sub_crqs(struct ibmvnic_adapter *adapter, int retry) | |||
1406 | union ibmvnic_crq crq; | 1478 | union ibmvnic_crq crq; |
1407 | int total_queues; | 1479 | int total_queues; |
1408 | int more = 0; | 1480 | int more = 0; |
1409 | int i, j; | 1481 | int i; |
1410 | int rc; | ||
1411 | 1482 | ||
1412 | if (!retry) { | 1483 | if (!retry) { |
1413 | /* Sub-CRQ entries are 32 byte long */ | 1484 | /* Sub-CRQ entries are 32 byte long */ |
@@ -1486,13 +1557,6 @@ static void init_sub_crqs(struct ibmvnic_adapter *adapter, int retry) | |||
1486 | for (i = 0; i < adapter->req_tx_queues; i++) { | 1557 | for (i = 0; i < adapter->req_tx_queues; i++) { |
1487 | adapter->tx_scrq[i] = allqueues[i]; | 1558 | adapter->tx_scrq[i] = allqueues[i]; |
1488 | adapter->tx_scrq[i]->pool_index = i; | 1559 | adapter->tx_scrq[i]->pool_index = i; |
1489 | rc = request_irq(adapter->tx_scrq[i]->irq, ibmvnic_interrupt_tx, | ||
1490 | 0, "ibmvnic_tx", adapter->tx_scrq[i]); | ||
1491 | if (rc) { | ||
1492 | dev_err(dev, "Couldn't register tx irq 0x%x. rc=%d\n", | ||
1493 | adapter->tx_scrq[i]->irq, rc); | ||
1494 | goto req_tx_irq_failed; | ||
1495 | } | ||
1496 | } | 1560 | } |
1497 | 1561 | ||
1498 | adapter->rx_scrq = kcalloc(adapter->req_rx_queues, | 1562 | adapter->rx_scrq = kcalloc(adapter->req_rx_queues, |
@@ -1503,13 +1567,6 @@ static void init_sub_crqs(struct ibmvnic_adapter *adapter, int retry) | |||
1503 | for (i = 0; i < adapter->req_rx_queues; i++) { | 1567 | for (i = 0; i < adapter->req_rx_queues; i++) { |
1504 | adapter->rx_scrq[i] = allqueues[i + adapter->req_tx_queues]; | 1568 | adapter->rx_scrq[i] = allqueues[i + adapter->req_tx_queues]; |
1505 | adapter->rx_scrq[i]->scrq_num = i; | 1569 | adapter->rx_scrq[i]->scrq_num = i; |
1506 | rc = request_irq(adapter->rx_scrq[i]->irq, ibmvnic_interrupt_rx, | ||
1507 | 0, "ibmvnic_rx", adapter->rx_scrq[i]); | ||
1508 | if (rc) { | ||
1509 | dev_err(dev, "Couldn't register rx irq 0x%x. rc=%d\n", | ||
1510 | adapter->rx_scrq[i]->irq, rc); | ||
1511 | goto req_rx_irq_failed; | ||
1512 | } | ||
1513 | } | 1570 | } |
1514 | 1571 | ||
1515 | memset(&crq, 0, sizeof(crq)); | 1572 | memset(&crq, 0, sizeof(crq)); |
@@ -1562,15 +1619,6 @@ static void init_sub_crqs(struct ibmvnic_adapter *adapter, int retry) | |||
1562 | 1619 | ||
1563 | return; | 1620 | return; |
1564 | 1621 | ||
1565 | req_rx_irq_failed: | ||
1566 | for (j = 0; j < i; j++) | ||
1567 | free_irq(adapter->rx_scrq[j]->irq, adapter->rx_scrq[j]); | ||
1568 | i = adapter->req_tx_queues; | ||
1569 | req_tx_irq_failed: | ||
1570 | for (j = 0; j < i; j++) | ||
1571 | free_irq(adapter->tx_scrq[j]->irq, adapter->tx_scrq[j]); | ||
1572 | kfree(adapter->rx_scrq); | ||
1573 | adapter->rx_scrq = NULL; | ||
1574 | rx_failed: | 1622 | rx_failed: |
1575 | kfree(adapter->tx_scrq); | 1623 | kfree(adapter->tx_scrq); |
1576 | adapter->tx_scrq = NULL; | 1624 | adapter->tx_scrq = NULL; |
@@ -2351,9 +2399,9 @@ static void handle_request_cap_rsp(union ibmvnic_crq *crq, | |||
2351 | *req_value, | 2399 | *req_value, |
2352 | (long int)be32_to_cpu(crq->request_capability_rsp. | 2400 | (long int)be32_to_cpu(crq->request_capability_rsp. |
2353 | number), name); | 2401 | number), name); |
2354 | release_sub_crqs(adapter); | 2402 | release_sub_crqs_no_irqs(adapter); |
2355 | *req_value = be32_to_cpu(crq->request_capability_rsp.number); | 2403 | *req_value = be32_to_cpu(crq->request_capability_rsp.number); |
2356 | complete(&adapter->init_done); | 2404 | init_sub_crqs(adapter, 1); |
2357 | return; | 2405 | return; |
2358 | default: | 2406 | default: |
2359 | dev_err(dev, "Error %d in request cap rsp\n", | 2407 | dev_err(dev, "Error %d in request cap rsp\n", |
@@ -2662,7 +2710,7 @@ static void handle_query_cap_rsp(union ibmvnic_crq *crq, | |||
2662 | 2710 | ||
2663 | out: | 2711 | out: |
2664 | if (atomic_read(&adapter->running_cap_queries) == 0) | 2712 | if (atomic_read(&adapter->running_cap_queries) == 0) |
2665 | complete(&adapter->init_done); | 2713 | init_sub_crqs(adapter, 0); |
2666 | /* We're done querying the capabilities, initialize sub-crqs */ | 2714 | /* We're done querying the capabilities, initialize sub-crqs */ |
2667 | } | 2715 | } |
2668 | 2716 | ||
@@ -3560,6 +3608,7 @@ static const struct file_operations ibmvnic_dump_ops = { | |||
3560 | 3608 | ||
3561 | static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) | 3609 | static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) |
3562 | { | 3610 | { |
3611 | unsigned long timeout = msecs_to_jiffies(30000); | ||
3563 | struct ibmvnic_adapter *adapter; | 3612 | struct ibmvnic_adapter *adapter; |
3564 | struct net_device *netdev; | 3613 | struct net_device *netdev; |
3565 | unsigned char *mac_addr_p; | 3614 | unsigned char *mac_addr_p; |
@@ -3638,30 +3687,26 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) | |||
3638 | ibmvnic_send_crq_init(adapter); | 3687 | ibmvnic_send_crq_init(adapter); |
3639 | 3688 | ||
3640 | init_completion(&adapter->init_done); | 3689 | init_completion(&adapter->init_done); |
3641 | wait_for_completion(&adapter->init_done); | 3690 | if (!wait_for_completion_timeout(&adapter->init_done, timeout)) |
3691 | return 0; | ||
3642 | 3692 | ||
3643 | do { | 3693 | do { |
3644 | adapter->renegotiate = false; | ||
3645 | |||
3646 | init_sub_crqs(adapter, 0); | ||
3647 | reinit_completion(&adapter->init_done); | ||
3648 | wait_for_completion(&adapter->init_done); | ||
3649 | |||
3650 | if (adapter->renegotiate) { | 3694 | if (adapter->renegotiate) { |
3651 | release_sub_crqs(adapter); | 3695 | adapter->renegotiate = false; |
3696 | release_sub_crqs_no_irqs(adapter); | ||
3652 | send_cap_queries(adapter); | 3697 | send_cap_queries(adapter); |
3653 | 3698 | ||
3654 | reinit_completion(&adapter->init_done); | 3699 | reinit_completion(&adapter->init_done); |
3655 | wait_for_completion(&adapter->init_done); | 3700 | if (!wait_for_completion_timeout(&adapter->init_done, |
3701 | timeout)) | ||
3702 | return 0; | ||
3656 | } | 3703 | } |
3657 | } while (adapter->renegotiate); | 3704 | } while (adapter->renegotiate); |
3658 | 3705 | ||
3659 | /* if init_sub_crqs is partially successful, retry */ | 3706 | rc = init_sub_crq_irqs(adapter); |
3660 | while (!adapter->tx_scrq || !adapter->rx_scrq) { | 3707 | if (rc) { |
3661 | init_sub_crqs(adapter, 1); | 3708 | dev_err(&dev->dev, "failed to initialize sub crq irqs\n"); |
3662 | 3709 | goto free_debugfs; | |
3663 | reinit_completion(&adapter->init_done); | ||
3664 | wait_for_completion(&adapter->init_done); | ||
3665 | } | 3710 | } |
3666 | 3711 | ||
3667 | netdev->real_num_tx_queues = adapter->req_tx_queues; | 3712 | netdev->real_num_tx_queues = adapter->req_tx_queues; |
@@ -3669,12 +3714,14 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) | |||
3669 | rc = register_netdev(netdev); | 3714 | rc = register_netdev(netdev); |
3670 | if (rc) { | 3715 | if (rc) { |
3671 | dev_err(&dev->dev, "failed to register netdev rc=%d\n", rc); | 3716 | dev_err(&dev->dev, "failed to register netdev rc=%d\n", rc); |
3672 | goto free_debugfs; | 3717 | goto free_sub_crqs; |
3673 | } | 3718 | } |
3674 | dev_info(&dev->dev, "ibmvnic registered\n"); | 3719 | dev_info(&dev->dev, "ibmvnic registered\n"); |
3675 | 3720 | ||
3676 | return 0; | 3721 | return 0; |
3677 | 3722 | ||
3723 | free_sub_crqs: | ||
3724 | release_sub_crqs(adapter); | ||
3678 | free_debugfs: | 3725 | free_debugfs: |
3679 | if (adapter->debugfs_dir && !IS_ERR(adapter->debugfs_dir)) | 3726 | if (adapter->debugfs_dir && !IS_ERR(adapter->debugfs_dir)) |
3680 | debugfs_remove_recursive(adapter->debugfs_dir); | 3727 | debugfs_remove_recursive(adapter->debugfs_dir); |