diff options
author | Rasesh Mody <rmody@brocade.com> | 2011-08-30 11:27:39 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-09-15 15:36:33 -0400 |
commit | 2be671442214402f890e367a19b5fc64cc13f878 (patch) | |
tree | f52dbb1500ee6d61623a0f3ee328319dd9aa5bba /drivers | |
parent | 0caa9aaec515268ec13b0939bfb7e32cf5a31a55 (diff) |
bna: Interrupt Polling and NAPI Init Changes
Change details:
- Remove unnecessary ccb check from bnad_poll_cq
- Add bnad pointer to rx_ctrl structure, so that bnad can be accessed directly
from rx_ctrl in the NAPI poll routines, even if ccb is NULL
- Validate ccb before referencing to it in bnad_msix_rx and bnad_napi_poll_rx
- Fix the order of NAPI init / uninit in Tx / Rx setup / teardown path:
a. Kill bnad tx free tasklet ahead of call to bna_tx_destroy()
b. Call NAPI disable only after call to Rx free_irq(). This makes sure Rx
interrupt does not schedule a poll when NAPI is already disabled
- NAPI poll runs before the h/w has completed configuration. This causes a
crash. Delay enabling NAPI till after bna_rx_enable(). Split NAPI
initialization into 2 steps, bnad_napi_init() & bnad_napi_enable().
Signed-off-by: Gurunatha Karaje <gkaraje@brocade.com>
Signed-off-by: Rasesh Mody <rmody@brocade.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/brocade/bna/bnad.c | 83 | ||||
-rw-r--r-- | drivers/net/ethernet/brocade/bna/bnad.h | 1 |
2 files changed, 54 insertions, 30 deletions
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c index 939abd45c0a4..630e818551a5 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.c +++ b/drivers/net/ethernet/brocade/bna/bnad.c | |||
@@ -535,16 +535,11 @@ next: | |||
535 | 535 | ||
536 | BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth); | 536 | BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth); |
537 | 537 | ||
538 | if (likely(ccb)) { | 538 | if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags))) |
539 | if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags))) | 539 | bna_ib_ack(ccb->i_dbell, packets); |
540 | bna_ib_ack(ccb->i_dbell, packets); | 540 | bnad_refill_rxq(bnad, ccb->rcb[0]); |
541 | bnad_refill_rxq(bnad, ccb->rcb[0]); | 541 | if (ccb->rcb[1]) |
542 | if (ccb->rcb[1]) | 542 | bnad_refill_rxq(bnad, ccb->rcb[1]); |
543 | bnad_refill_rxq(bnad, ccb->rcb[1]); | ||
544 | } else { | ||
545 | if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags))) | ||
546 | bna_ib_ack(ccb->i_dbell, 0); | ||
547 | } | ||
548 | 543 | ||
549 | clear_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags); | 544 | clear_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags); |
550 | 545 | ||
@@ -590,9 +585,9 @@ static irqreturn_t | |||
590 | bnad_msix_rx(int irq, void *data) | 585 | bnad_msix_rx(int irq, void *data) |
591 | { | 586 | { |
592 | struct bna_ccb *ccb = (struct bna_ccb *)data; | 587 | struct bna_ccb *ccb = (struct bna_ccb *)data; |
593 | struct bnad *bnad = ccb->bnad; | ||
594 | 588 | ||
595 | bnad_netif_rx_schedule_poll(bnad, ccb); | 589 | if (ccb) |
590 | bnad_netif_rx_schedule_poll(ccb->bnad, ccb); | ||
596 | 591 | ||
597 | return IRQ_HANDLED; | 592 | return IRQ_HANDLED; |
598 | } | 593 | } |
@@ -1658,18 +1653,14 @@ bnad_napi_poll_rx(struct napi_struct *napi, int budget) | |||
1658 | { | 1653 | { |
1659 | struct bnad_rx_ctrl *rx_ctrl = | 1654 | struct bnad_rx_ctrl *rx_ctrl = |
1660 | container_of(napi, struct bnad_rx_ctrl, napi); | 1655 | container_of(napi, struct bnad_rx_ctrl, napi); |
1661 | struct bna_ccb *ccb; | 1656 | struct bnad *bnad = rx_ctrl->bnad; |
1662 | struct bnad *bnad; | ||
1663 | int rcvd = 0; | 1657 | int rcvd = 0; |
1664 | 1658 | ||
1665 | ccb = rx_ctrl->ccb; | ||
1666 | |||
1667 | bnad = ccb->bnad; | ||
1668 | 1659 | ||
1669 | if (!netif_carrier_ok(bnad->netdev)) | 1660 | if (!netif_carrier_ok(bnad->netdev)) |
1670 | goto poll_exit; | 1661 | goto poll_exit; |
1671 | 1662 | ||
1672 | rcvd = bnad_poll_cq(bnad, ccb, budget); | 1663 | rcvd = bnad_poll_cq(bnad, rx_ctrl->ccb, budget); |
1673 | if (rcvd == budget) | 1664 | if (rcvd == budget) |
1674 | return rcvd; | 1665 | return rcvd; |
1675 | 1666 | ||
@@ -1678,12 +1669,15 @@ poll_exit: | |||
1678 | 1669 | ||
1679 | BNAD_UPDATE_CTR(bnad, netif_rx_complete); | 1670 | BNAD_UPDATE_CTR(bnad, netif_rx_complete); |
1680 | 1671 | ||
1681 | bnad_enable_rx_irq(bnad, ccb); | 1672 | |
1673 | if (rx_ctrl->ccb) | ||
1674 | bnad_enable_rx_irq(bnad, rx_ctrl->ccb); | ||
1682 | return rcvd; | 1675 | return rcvd; |
1683 | } | 1676 | } |
1684 | 1677 | ||
1678 | #define BNAD_NAPI_POLL_QUOTA 64 | ||
1685 | static void | 1679 | static void |
1686 | bnad_napi_enable(struct bnad *bnad, u32 rx_id) | 1680 | bnad_napi_init(struct bnad *bnad, u32 rx_id) |
1687 | { | 1681 | { |
1688 | struct bnad_rx_ctrl *rx_ctrl; | 1682 | struct bnad_rx_ctrl *rx_ctrl; |
1689 | int i; | 1683 | int i; |
@@ -1691,9 +1685,20 @@ bnad_napi_enable(struct bnad *bnad, u32 rx_id) | |||
1691 | /* Initialize & enable NAPI */ | 1685 | /* Initialize & enable NAPI */ |
1692 | for (i = 0; i < bnad->num_rxp_per_rx; i++) { | 1686 | for (i = 0; i < bnad->num_rxp_per_rx; i++) { |
1693 | rx_ctrl = &bnad->rx_info[rx_id].rx_ctrl[i]; | 1687 | rx_ctrl = &bnad->rx_info[rx_id].rx_ctrl[i]; |
1694 | |||
1695 | netif_napi_add(bnad->netdev, &rx_ctrl->napi, | 1688 | netif_napi_add(bnad->netdev, &rx_ctrl->napi, |
1696 | bnad_napi_poll_rx, 64); | 1689 | bnad_napi_poll_rx, BNAD_NAPI_POLL_QUOTA); |
1690 | } | ||
1691 | } | ||
1692 | |||
1693 | static void | ||
1694 | bnad_napi_enable(struct bnad *bnad, u32 rx_id) | ||
1695 | { | ||
1696 | struct bnad_rx_ctrl *rx_ctrl; | ||
1697 | int i; | ||
1698 | |||
1699 | /* Initialize & enable NAPI */ | ||
1700 | for (i = 0; i < bnad->num_rxp_per_rx; i++) { | ||
1701 | rx_ctrl = &bnad->rx_info[rx_id].rx_ctrl[i]; | ||
1697 | 1702 | ||
1698 | napi_enable(&rx_ctrl->napi); | 1703 | napi_enable(&rx_ctrl->napi); |
1699 | } | 1704 | } |
@@ -1732,6 +1737,9 @@ bnad_cleanup_tx(struct bnad *bnad, u32 tx_id) | |||
1732 | bnad_tx_msix_unregister(bnad, tx_info, | 1737 | bnad_tx_msix_unregister(bnad, tx_info, |
1733 | bnad->num_txq_per_tx); | 1738 | bnad->num_txq_per_tx); |
1734 | 1739 | ||
1740 | if (0 == tx_id) | ||
1741 | tasklet_kill(&bnad->tx_free_tasklet); | ||
1742 | |||
1735 | spin_lock_irqsave(&bnad->bna_lock, flags); | 1743 | spin_lock_irqsave(&bnad->bna_lock, flags); |
1736 | bna_tx_destroy(tx_info->tx); | 1744 | bna_tx_destroy(tx_info->tx); |
1737 | spin_unlock_irqrestore(&bnad->bna_lock, flags); | 1745 | spin_unlock_irqrestore(&bnad->bna_lock, flags); |
@@ -1739,9 +1747,6 @@ bnad_cleanup_tx(struct bnad *bnad, u32 tx_id) | |||
1739 | tx_info->tx = NULL; | 1747 | tx_info->tx = NULL; |
1740 | tx_info->tx_id = 0; | 1748 | tx_info->tx_id = 0; |
1741 | 1749 | ||
1742 | if (0 == tx_id) | ||
1743 | tasklet_kill(&bnad->tx_free_tasklet); | ||
1744 | |||
1745 | bnad_tx_res_free(bnad, res_info); | 1750 | bnad_tx_res_free(bnad, res_info); |
1746 | } | 1751 | } |
1747 | 1752 | ||
@@ -1852,6 +1857,16 @@ bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config) | |||
1852 | rx_config->vlan_strip_status = BNA_STATUS_T_ENABLED; | 1857 | rx_config->vlan_strip_status = BNA_STATUS_T_ENABLED; |
1853 | } | 1858 | } |
1854 | 1859 | ||
1860 | static void | ||
1861 | bnad_rx_ctrl_init(struct bnad *bnad, u32 rx_id) | ||
1862 | { | ||
1863 | struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id]; | ||
1864 | int i; | ||
1865 | |||
1866 | for (i = 0; i < bnad->num_rxp_per_rx; i++) | ||
1867 | rx_info->rx_ctrl[i].bnad = bnad; | ||
1868 | } | ||
1869 | |||
1855 | /* Called with mutex_lock(&bnad->conf_mutex) held */ | 1870 | /* Called with mutex_lock(&bnad->conf_mutex) held */ |
1856 | void | 1871 | void |
1857 | bnad_cleanup_rx(struct bnad *bnad, u32 rx_id) | 1872 | bnad_cleanup_rx(struct bnad *bnad, u32 rx_id) |
@@ -1875,8 +1890,6 @@ bnad_cleanup_rx(struct bnad *bnad, u32 rx_id) | |||
1875 | del_timer_sync(&bnad->dim_timer); | 1890 | del_timer_sync(&bnad->dim_timer); |
1876 | } | 1891 | } |
1877 | 1892 | ||
1878 | bnad_napi_disable(bnad, rx_id); | ||
1879 | |||
1880 | init_completion(&bnad->bnad_completions.rx_comp); | 1893 | init_completion(&bnad->bnad_completions.rx_comp); |
1881 | spin_lock_irqsave(&bnad->bna_lock, flags); | 1894 | spin_lock_irqsave(&bnad->bna_lock, flags); |
1882 | bna_rx_disable(rx_info->rx, BNA_HARD_CLEANUP, bnad_cb_rx_disabled); | 1895 | bna_rx_disable(rx_info->rx, BNA_HARD_CLEANUP, bnad_cb_rx_disabled); |
@@ -1886,6 +1899,8 @@ bnad_cleanup_rx(struct bnad *bnad, u32 rx_id) | |||
1886 | if (rx_info->rx_ctrl[0].ccb->intr_type == BNA_INTR_T_MSIX) | 1899 | if (rx_info->rx_ctrl[0].ccb->intr_type == BNA_INTR_T_MSIX) |
1887 | bnad_rx_msix_unregister(bnad, rx_info, rx_config->num_paths); | 1900 | bnad_rx_msix_unregister(bnad, rx_info, rx_config->num_paths); |
1888 | 1901 | ||
1902 | bnad_napi_disable(bnad, rx_id); | ||
1903 | |||
1889 | spin_lock_irqsave(&bnad->bna_lock, flags); | 1904 | spin_lock_irqsave(&bnad->bna_lock, flags); |
1890 | bna_rx_destroy(rx_info->rx); | 1905 | bna_rx_destroy(rx_info->rx); |
1891 | spin_unlock_irqrestore(&bnad->bna_lock, flags); | 1906 | spin_unlock_irqrestore(&bnad->bna_lock, flags); |
@@ -1939,6 +1954,8 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id) | |||
1939 | if (err) | 1954 | if (err) |
1940 | return err; | 1955 | return err; |
1941 | 1956 | ||
1957 | bnad_rx_ctrl_init(bnad, rx_id); | ||
1958 | |||
1942 | /* Ask BNA to create one Rx object, supplying required resources */ | 1959 | /* Ask BNA to create one Rx object, supplying required resources */ |
1943 | spin_lock_irqsave(&bnad->bna_lock, flags); | 1960 | spin_lock_irqsave(&bnad->bna_lock, flags); |
1944 | rx = bna_rx_create(&bnad->bna, bnad, rx_config, &rx_cbfn, res_info, | 1961 | rx = bna_rx_create(&bnad->bna, bnad, rx_config, &rx_cbfn, res_info, |
@@ -1948,6 +1965,12 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id) | |||
1948 | goto err_return; | 1965 | goto err_return; |
1949 | rx_info->rx = rx; | 1966 | rx_info->rx = rx; |
1950 | 1967 | ||
1968 | /* | ||
1969 | * Init NAPI, so that state is set to NAPI_STATE_SCHED, | ||
1970 | * so that IRQ handler cannot schedule NAPI at this point. | ||
1971 | */ | ||
1972 | bnad_napi_init(bnad, rx_id); | ||
1973 | |||
1951 | /* Register ISR for the Rx object */ | 1974 | /* Register ISR for the Rx object */ |
1952 | if (intr_info->intr_type == BNA_INTR_T_MSIX) { | 1975 | if (intr_info->intr_type == BNA_INTR_T_MSIX) { |
1953 | err = bnad_rx_msix_register(bnad, rx_info, rx_id, | 1976 | err = bnad_rx_msix_register(bnad, rx_info, rx_id, |
@@ -1956,9 +1979,6 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id) | |||
1956 | goto err_return; | 1979 | goto err_return; |
1957 | } | 1980 | } |
1958 | 1981 | ||
1959 | /* Enable NAPI */ | ||
1960 | bnad_napi_enable(bnad, rx_id); | ||
1961 | |||
1962 | spin_lock_irqsave(&bnad->bna_lock, flags); | 1982 | spin_lock_irqsave(&bnad->bna_lock, flags); |
1963 | if (0 == rx_id) { | 1983 | if (0 == rx_id) { |
1964 | /* Set up Dynamic Interrupt Moderation Vector */ | 1984 | /* Set up Dynamic Interrupt Moderation Vector */ |
@@ -1975,6 +1995,9 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id) | |||
1975 | bna_rx_enable(rx); | 1995 | bna_rx_enable(rx); |
1976 | spin_unlock_irqrestore(&bnad->bna_lock, flags); | 1996 | spin_unlock_irqrestore(&bnad->bna_lock, flags); |
1977 | 1997 | ||
1998 | /* Enable scheduling of NAPI */ | ||
1999 | bnad_napi_enable(bnad, rx_id); | ||
2000 | |||
1978 | return 0; | 2001 | return 0; |
1979 | 2002 | ||
1980 | err_return: | 2003 | err_return: |
diff --git a/drivers/net/ethernet/brocade/bna/bnad.h b/drivers/net/ethernet/brocade/bna/bnad.h index 3c231390b17c..60c2e9d534a7 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.h +++ b/drivers/net/ethernet/brocade/bna/bnad.h | |||
@@ -53,6 +53,7 @@ | |||
53 | */ | 53 | */ |
54 | struct bnad_rx_ctrl { | 54 | struct bnad_rx_ctrl { |
55 | struct bna_ccb *ccb; | 55 | struct bna_ccb *ccb; |
56 | struct bnad *bnad; | ||
56 | unsigned long flags; | 57 | unsigned long flags; |
57 | struct napi_struct napi; | 58 | struct napi_struct napi; |
58 | }; | 59 | }; |