diff options
author | Rasesh Mody <rmody@brocade.com> | 2013-12-17 17:07:34 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-12-18 00:30:33 -0500 |
commit | fe1624cfb1286a1dff072daca96678e1111068f4 (patch) | |
tree | 2d51b756a4cda2f0bfd33a2e0eea32084f1b262e /drivers/net/ethernet/brocade/bna/bna_tx_rx.c | |
parent | bna: Fix Filter Add Del (diff) | |
download | linux-dev-fe1624cfb1286a1dff072daca96678e1111068f4.tar.xz linux-dev-fe1624cfb1286a1dff072daca96678e1111068f4.zip |
bna: RX Filter Enhancements
Change Details:
- Added bna_rx_ucast_listset() for synchronous ucast listadd operation.
- Clear mac->handle before adding it to free_q.
- bnad_set_rx_mode() rewritten. bnad_set_rx_mode() adds the MACs in uc_list
to UCAM. If it exceeds the max supported, DEFAULT mode is turned on. If
MCAM limit is exceeded, ALLMULTI mode is turned on.
- Clear CF flags, check for the new mode and reprogram the Rx approach.
- Added bnad_set_rx_ucast_fltr() and bnad_set_rx_mcast_fltr().
- Check for IFF_PROMISC to set the correct mode.
Signed-off-by: Rasesh Mody <rmody@brocade.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/brocade/bna/bna_tx_rx.c')
-rw-r--r-- | drivers/net/ethernet/brocade/bna/bna_tx_rx.c | 138 |
1 files changed, 137 insertions, 1 deletions
diff --git a/drivers/net/ethernet/brocade/bna/bna_tx_rx.c b/drivers/net/ethernet/brocade/bna/bna_tx_rx.c index 40558b643b6e..e02c1265e323 100644 --- a/drivers/net/ethernet/brocade/bna/bna_tx_rx.c +++ b/drivers/net/ethernet/brocade/bna/bna_tx_rx.c @@ -916,6 +916,75 @@ bna_rx_mcast_add(struct bna_rx *rx, u8 *addr, } enum bna_cb_status +bna_rx_ucast_listset(struct bna_rx *rx, int count, u8 *uclist, + void (*cbfn)(struct bnad *, struct bna_rx *)) +{ + struct bna_ucam_mod *ucam_mod = &rx->bna->ucam_mod; + struct bna_rxf *rxf = &rx->rxf; + struct list_head list_head; + struct list_head *qe; + u8 *mcaddr; + struct bna_mac *mac, *del_mac; + int i; + + /* Purge the pending_add_q */ + while (!list_empty(&rxf->ucast_pending_add_q)) { + bfa_q_deq(&rxf->ucast_pending_add_q, &qe); + bfa_q_qe_init(qe); + mac = (struct bna_mac *)qe; + bna_cam_mod_mac_put(&ucam_mod->free_q, mac); + } + + /* Schedule active_q entries for deletion */ + while (!list_empty(&rxf->ucast_active_q)) { + bfa_q_deq(&rxf->ucast_active_q, &qe); + mac = (struct bna_mac *)qe; + bfa_q_qe_init(&mac->qe); + + del_mac = bna_cam_mod_mac_get(&ucam_mod->del_q); + memcpy(del_mac, mac, sizeof(*del_mac)); + list_add_tail(&del_mac->qe, &rxf->ucast_pending_del_q); + bna_cam_mod_mac_put(&ucam_mod->free_q, mac); + } + + /* Allocate nodes */ + INIT_LIST_HEAD(&list_head); + for (i = 0, mcaddr = uclist; i < count; i++) { + mac = bna_cam_mod_mac_get(&ucam_mod->free_q); + if (mac == NULL) + goto err_return; + bfa_q_qe_init(&mac->qe); + memcpy(mac->addr, mcaddr, ETH_ALEN); + list_add_tail(&mac->qe, &list_head); + mcaddr += ETH_ALEN; + } + + /* Add the new entries */ + while (!list_empty(&list_head)) { + bfa_q_deq(&list_head, &qe); + mac = (struct bna_mac *)qe; + bfa_q_qe_init(&mac->qe); + list_add_tail(&mac->qe, &rxf->ucast_pending_add_q); + } + + rxf->cam_fltr_cbfn = cbfn; + rxf->cam_fltr_cbarg = rx->bna->bnad; + bfa_fsm_send_event(rxf, RXF_E_CONFIG); + + return BNA_CB_SUCCESS; + +err_return: + while (!list_empty(&list_head)) { + bfa_q_deq(&list_head, &qe); + mac = (struct bna_mac *)qe; + bfa_q_qe_init(&mac->qe); + bna_cam_mod_mac_put(&ucam_mod->free_q, mac); + } + + return BNA_CB_UCAST_CAM_FULL; +} + +enum bna_cb_status bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mclist, void (*cbfn)(struct bnad *, struct bna_rx *)) { @@ -943,7 +1012,7 @@ bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mclist, del_mac = bna_cam_mod_mac_get(&mcam_mod->del_q); - memcpy(del_mac, mac, sizeof(*mac)); + memcpy(del_mac, mac, sizeof(*del_mac)); list_add_tail(&del_mac->qe, &rxf->mcast_pending_del_q); mac->handle = NULL; bna_cam_mod_mac_put(&mcam_mod->free_q, mac); @@ -988,6 +1057,49 @@ err_return: } void +bna_rx_mcast_delall(struct bna_rx *rx, + void (*cbfn)(struct bnad *, struct bna_rx *)) +{ + struct bna_rxf *rxf = &rx->rxf; + struct list_head *qe; + struct bna_mac *mac, *del_mac; + int need_hw_config = 0; + + /* Purge all entries from pending_add_q */ + while (!list_empty(&rxf->mcast_pending_add_q)) { + bfa_q_deq(&rxf->mcast_pending_add_q, &qe); + mac = (struct bna_mac *)qe; + bfa_q_qe_init(&mac->qe); + bna_cam_mod_mac_put(bna_mcam_mod_free_q(rxf->rx->bna), mac); + } + + /* Schedule all entries in active_q for deletion */ + while (!list_empty(&rxf->mcast_active_q)) { + bfa_q_deq(&rxf->mcast_active_q, &qe); + mac = (struct bna_mac *)qe; + bfa_q_qe_init(&mac->qe); + + del_mac = bna_cam_mod_mac_get(bna_mcam_mod_del_q(rxf->rx->bna)); + + memcpy(del_mac, mac, sizeof(*del_mac)); + list_add_tail(&del_mac->qe, &rxf->mcast_pending_del_q); + mac->handle = NULL; + bna_cam_mod_mac_put(bna_mcam_mod_free_q(rxf->rx->bna), mac); + need_hw_config = 1; + } + + if (need_hw_config) { + rxf->cam_fltr_cbfn = cbfn; + rxf->cam_fltr_cbarg = rx->bna->bnad; + bfa_fsm_send_event(rxf, RXF_E_CONFIG); + return; + } + + if (cbfn) + (*cbfn)(rx->bna->bnad, rx); +} + +void bna_rx_vlan_add(struct bna_rx *rx, int vlan_id) { struct bna_rxf *rxf = &rx->rxf; @@ -2679,6 +2791,30 @@ bna_rx_cleanup_complete(struct bna_rx *rx) bfa_fsm_send_event(rx, RX_E_CLEANUP_DONE); } +void +bna_rx_vlan_strip_enable(struct bna_rx *rx) +{ + struct bna_rxf *rxf = &rx->rxf; + + if (rxf->vlan_strip_status == BNA_STATUS_T_DISABLED) { + rxf->vlan_strip_status = BNA_STATUS_T_ENABLED; + rxf->vlan_strip_pending = true; + bfa_fsm_send_event(rxf, RXF_E_CONFIG); + } +} + +void +bna_rx_vlan_strip_disable(struct bna_rx *rx) +{ + struct bna_rxf *rxf = &rx->rxf; + + if (rxf->vlan_strip_status != BNA_STATUS_T_DISABLED) { + rxf->vlan_strip_status = BNA_STATUS_T_DISABLED; + rxf->vlan_strip_pending = true; + bfa_fsm_send_event(rxf, RXF_E_CONFIG); + } +} + enum bna_cb_status bna_rx_mode_set(struct bna_rx *rx, enum bna_rxmode new_mode, enum bna_rxmode bitmask, |