diff options
author | Ariel Elior <ariele@broadcom.com> | 2013-01-01 00:22:29 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-01-02 04:45:05 -0500 |
commit | 381ac16b10ae9369ebbbd74bb52b970818f68022 (patch) | |
tree | ae14a3c059359493aaf25df0f7ec345546208ad3 /drivers/net | |
parent | 9b176b6b63ed07472c26b6833a0ac23b373e6bf8 (diff) |
bnx2x: Support ndo_set_rxmode in VF driver
The VF driver uses the 'q_filter' request in the VF <-> PF channel to
have the PF configure the requested rxmode to device. ndo_set_rxmode
is called under bottom half lock, so sleeping until the response
arrives over the VF <-> PF channel is out of the question. For this reason
the VF driver returns from the ndo after scheduling a work item, which
in turn processes the rx mode request and adds the classification
information through the VF <-> PF channel accordingly.
Signed-off-by: Ariel Elior <ariele@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 173 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h | 7 |
3 files changed, 179 insertions, 6 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 82c6233bcace..2fe1908e94d7 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | |||
@@ -1191,6 +1191,8 @@ enum { | |||
1191 | BNX2X_SP_RTNL_TX_TIMEOUT, | 1191 | BNX2X_SP_RTNL_TX_TIMEOUT, |
1192 | BNX2X_SP_RTNL_AFEX_F_UPDATE, | 1192 | BNX2X_SP_RTNL_AFEX_F_UPDATE, |
1193 | BNX2X_SP_RTNL_FAN_FAILURE, | 1193 | BNX2X_SP_RTNL_FAN_FAILURE, |
1194 | BNX2X_SP_RTNL_VFPF_MCAST, | ||
1195 | BNX2X_SP_RTNL_VFPF_STORM_RX_MODE, | ||
1194 | }; | 1196 | }; |
1195 | 1197 | ||
1196 | 1198 | ||
@@ -2229,6 +2231,9 @@ void bnx2x_vfpf_close_vf(struct bnx2x *bp); | |||
2229 | int bnx2x_vfpf_setup_q(struct bnx2x *bp, int fp_idx); | 2231 | int bnx2x_vfpf_setup_q(struct bnx2x *bp, int fp_idx); |
2230 | int bnx2x_vfpf_teardown_queue(struct bnx2x *bp, int qidx); | 2232 | int bnx2x_vfpf_teardown_queue(struct bnx2x *bp, int qidx); |
2231 | int bnx2x_vfpf_set_mac(struct bnx2x *bp); | 2233 | int bnx2x_vfpf_set_mac(struct bnx2x *bp); |
2234 | int bnx2x_vfpf_set_mcast(struct net_device *dev); | ||
2235 | int bnx2x_vfpf_storm_rx_mode(struct bnx2x *bp); | ||
2236 | |||
2232 | int bnx2x_nic_load_analyze_req(struct bnx2x *bp, u32 load_code); | 2237 | int bnx2x_nic_load_analyze_req(struct bnx2x *bp, u32 load_code); |
2233 | /* Congestion management fairness mode */ | 2238 | /* Congestion management fairness mode */ |
2234 | #define CMNG_FNS_NONE 0 | 2239 | #define CMNG_FNS_NONE 0 |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 2bf7dcca397d..d27820542c3e 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |||
@@ -9403,6 +9403,19 @@ sp_rtnl_not_reset: | |||
9403 | bnx2x_close(bp->dev); | 9403 | bnx2x_close(bp->dev); |
9404 | } | 9404 | } |
9405 | 9405 | ||
9406 | if (test_and_clear_bit(BNX2X_SP_RTNL_VFPF_MCAST, &bp->sp_rtnl_state)) { | ||
9407 | DP(BNX2X_MSG_SP, | ||
9408 | "sending set mcast vf pf channel message from rtnl sp-task\n"); | ||
9409 | bnx2x_vfpf_set_mcast(bp->dev); | ||
9410 | } | ||
9411 | |||
9412 | if (test_and_clear_bit(BNX2X_SP_RTNL_VFPF_STORM_RX_MODE, | ||
9413 | &bp->sp_rtnl_state)) { | ||
9414 | DP(BNX2X_MSG_SP, | ||
9415 | "sending set storm rx mode vf pf channel message from rtnl sp-task\n"); | ||
9416 | bnx2x_vfpf_storm_rx_mode(bp); | ||
9417 | } | ||
9418 | |||
9406 | sp_rtnl_exit: | 9419 | sp_rtnl_exit: |
9407 | rtnl_unlock(); | 9420 | rtnl_unlock(); |
9408 | } | 9421 | } |
@@ -11479,12 +11492,25 @@ void bnx2x_set_rx_mode(struct net_device *dev) | |||
11479 | CHIP_IS_E1(bp))) | 11492 | CHIP_IS_E1(bp))) |
11480 | rx_mode = BNX2X_RX_MODE_ALLMULTI; | 11493 | rx_mode = BNX2X_RX_MODE_ALLMULTI; |
11481 | else { | 11494 | else { |
11482 | /* some multicasts */ | 11495 | if (IS_PF(bp)) { |
11483 | if (bnx2x_set_mc_list(bp) < 0) | 11496 | /* some multicasts */ |
11484 | rx_mode = BNX2X_RX_MODE_ALLMULTI; | 11497 | if (bnx2x_set_mc_list(bp) < 0) |
11498 | rx_mode = BNX2X_RX_MODE_ALLMULTI; | ||
11485 | 11499 | ||
11486 | if (bnx2x_set_uc_list(bp) < 0) | 11500 | if (bnx2x_set_uc_list(bp) < 0) |
11487 | rx_mode = BNX2X_RX_MODE_PROMISC; | 11501 | rx_mode = BNX2X_RX_MODE_PROMISC; |
11502 | } else { | ||
11503 | /* configuring mcast to a vf involves sleeping (when we | ||
11504 | * wait for the pf's response). Since this function is | ||
11505 | * called from non sleepable context we must schedule | ||
11506 | * a work item for this purpose | ||
11507 | */ | ||
11508 | smp_mb__before_clear_bit(); | ||
11509 | set_bit(BNX2X_SP_RTNL_VFPF_MCAST, | ||
11510 | &bp->sp_rtnl_state); | ||
11511 | smp_mb__after_clear_bit(); | ||
11512 | schedule_delayed_work(&bp->sp_rtnl_task, 0); | ||
11513 | } | ||
11488 | } | 11514 | } |
11489 | 11515 | ||
11490 | bp->rx_mode = rx_mode; | 11516 | bp->rx_mode = rx_mode; |
@@ -11498,7 +11524,20 @@ void bnx2x_set_rx_mode(struct net_device *dev) | |||
11498 | return; | 11524 | return; |
11499 | } | 11525 | } |
11500 | 11526 | ||
11501 | bnx2x_set_storm_rx_mode(bp); | 11527 | if (IS_PF(bp)) { |
11528 | bnx2x_set_storm_rx_mode(bp); | ||
11529 | } else { | ||
11530 | /* configuring rx mode to storms in a vf involves sleeping (when | ||
11531 | * we wait for the pf's response). Since this function is | ||
11532 | * called from non sleepable context we must schedule | ||
11533 | * a work item for this purpose | ||
11534 | */ | ||
11535 | smp_mb__before_clear_bit(); | ||
11536 | set_bit(BNX2X_SP_RTNL_VFPF_STORM_RX_MODE, | ||
11537 | &bp->sp_rtnl_state); | ||
11538 | smp_mb__after_clear_bit(); | ||
11539 | schedule_delayed_work(&bp->sp_rtnl_task, 0); | ||
11540 | } | ||
11502 | } | 11541 | } |
11503 | 11542 | ||
11504 | /* called with rtnl_lock */ | 11543 | /* called with rtnl_lock */ |
@@ -13676,3 +13715,125 @@ int bnx2x_vfpf_set_mac(struct bnx2x *bp) | |||
13676 | 13715 | ||
13677 | return 0; | 13716 | return 0; |
13678 | } | 13717 | } |
13718 | |||
13719 | int bnx2x_vfpf_set_mcast(struct net_device *dev) | ||
13720 | { | ||
13721 | struct bnx2x *bp = netdev_priv(dev); | ||
13722 | struct vfpf_set_q_filters_tlv *req = &bp->vf2pf_mbox->req.set_q_filters; | ||
13723 | struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp; | ||
13724 | int rc, i = 0; | ||
13725 | struct netdev_hw_addr *ha; | ||
13726 | |||
13727 | if (bp->state != BNX2X_STATE_OPEN) { | ||
13728 | DP(NETIF_MSG_IFUP, "state is %x, returning\n", bp->state); | ||
13729 | return -EINVAL; | ||
13730 | } | ||
13731 | |||
13732 | /* clear mailbox and prep first tlv */ | ||
13733 | bnx2x_vfpf_prep(bp, &req->first_tlv, CHANNEL_TLV_SET_Q_FILTERS, | ||
13734 | sizeof(*req)); | ||
13735 | |||
13736 | /* Get Rx mode requested */ | ||
13737 | DP(NETIF_MSG_IFUP, "dev->flags = %x\n", dev->flags); | ||
13738 | |||
13739 | netdev_for_each_mc_addr(ha, dev) { | ||
13740 | DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n", | ||
13741 | bnx2x_mc_addr(ha)); | ||
13742 | memcpy(req->multicast[i], bnx2x_mc_addr(ha), ETH_ALEN); | ||
13743 | i++; | ||
13744 | } | ||
13745 | |||
13746 | /* We support four PFVF_MAX_MULTICAST_PER_VF mcast | ||
13747 | * addresses tops | ||
13748 | */ | ||
13749 | if (i >= PFVF_MAX_MULTICAST_PER_VF) { | ||
13750 | DP(NETIF_MSG_IFUP, | ||
13751 | "VF supports not more than %d multicast MAC addresses\n", | ||
13752 | PFVF_MAX_MULTICAST_PER_VF); | ||
13753 | return -EINVAL; | ||
13754 | } | ||
13755 | |||
13756 | req->n_multicast = i; | ||
13757 | req->flags |= VFPF_SET_Q_FILTERS_MULTICAST_CHANGED; | ||
13758 | req->vf_qid = 0; | ||
13759 | |||
13760 | /* add list termination tlv */ | ||
13761 | bnx2x_add_tlv(bp, req, req->first_tlv.tl.length, CHANNEL_TLV_LIST_END, | ||
13762 | sizeof(struct channel_list_end_tlv)); | ||
13763 | |||
13764 | /* output tlvs list */ | ||
13765 | bnx2x_dp_tlv_list(bp, req); | ||
13766 | |||
13767 | rc = bnx2x_send_msg2pf(bp, &resp->hdr.status, bp->vf2pf_mbox_mapping); | ||
13768 | if (rc) { | ||
13769 | BNX2X_ERR("Sending a message failed: %d\n", rc); | ||
13770 | return rc; | ||
13771 | } | ||
13772 | |||
13773 | if (resp->hdr.status != PFVF_STATUS_SUCCESS) { | ||
13774 | BNX2X_ERR("Set Rx mode/multicast failed: %d\n", | ||
13775 | resp->hdr.status); | ||
13776 | return -EINVAL; | ||
13777 | } | ||
13778 | |||
13779 | return 0; | ||
13780 | } | ||
13781 | |||
13782 | int bnx2x_vfpf_storm_rx_mode(struct bnx2x *bp) | ||
13783 | { | ||
13784 | int mode = bp->rx_mode; | ||
13785 | struct vfpf_set_q_filters_tlv *req = &bp->vf2pf_mbox->req.set_q_filters; | ||
13786 | struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp; | ||
13787 | int rc; | ||
13788 | |||
13789 | /* clear mailbox and prep first tlv */ | ||
13790 | bnx2x_vfpf_prep(bp, &req->first_tlv, CHANNEL_TLV_SET_Q_FILTERS, | ||
13791 | sizeof(*req)); | ||
13792 | |||
13793 | DP(NETIF_MSG_IFUP, "Rx mode is %d\n", mode); | ||
13794 | |||
13795 | switch (mode) { | ||
13796 | case BNX2X_RX_MODE_NONE: /* no Rx */ | ||
13797 | req->rx_mask = VFPF_RX_MASK_ACCEPT_NONE; | ||
13798 | break; | ||
13799 | case BNX2X_RX_MODE_NORMAL: | ||
13800 | req->rx_mask = VFPF_RX_MASK_ACCEPT_MATCHED_MULTICAST; | ||
13801 | req->rx_mask |= VFPF_RX_MASK_ACCEPT_MATCHED_UNICAST; | ||
13802 | req->rx_mask |= VFPF_RX_MASK_ACCEPT_BROADCAST; | ||
13803 | break; | ||
13804 | case BNX2X_RX_MODE_ALLMULTI: | ||
13805 | req->rx_mask = VFPF_RX_MASK_ACCEPT_ALL_MULTICAST; | ||
13806 | req->rx_mask |= VFPF_RX_MASK_ACCEPT_MATCHED_UNICAST; | ||
13807 | req->rx_mask |= VFPF_RX_MASK_ACCEPT_BROADCAST; | ||
13808 | break; | ||
13809 | case BNX2X_RX_MODE_PROMISC: | ||
13810 | req->rx_mask = VFPF_RX_MASK_ACCEPT_ALL_UNICAST; | ||
13811 | req->rx_mask |= VFPF_RX_MASK_ACCEPT_ALL_MULTICAST; | ||
13812 | req->rx_mask |= VFPF_RX_MASK_ACCEPT_BROADCAST; | ||
13813 | break; | ||
13814 | default: | ||
13815 | BNX2X_ERR("BAD rx mode (%d)\n", mode); | ||
13816 | return -EINVAL; | ||
13817 | } | ||
13818 | |||
13819 | req->flags |= VFPF_SET_Q_FILTERS_RX_MASK_CHANGED; | ||
13820 | req->vf_qid = 0; | ||
13821 | |||
13822 | /* add list termination tlv */ | ||
13823 | bnx2x_add_tlv(bp, req, req->first_tlv.tl.length, CHANNEL_TLV_LIST_END, | ||
13824 | sizeof(struct channel_list_end_tlv)); | ||
13825 | |||
13826 | /* output tlvs list */ | ||
13827 | bnx2x_dp_tlv_list(bp, req); | ||
13828 | |||
13829 | rc = bnx2x_send_msg2pf(bp, &resp->hdr.status, bp->vf2pf_mbox_mapping); | ||
13830 | if (rc) | ||
13831 | BNX2X_ERR("Sending a message failed: %d\n", rc); | ||
13832 | |||
13833 | if (resp->hdr.status != PFVF_STATUS_SUCCESS) { | ||
13834 | BNX2X_ERR("Set Rx mode failed: %d\n", resp->hdr.status); | ||
13835 | return -EINVAL; | ||
13836 | } | ||
13837 | |||
13838 | return rc; | ||
13839 | } | ||
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h index ed4a61815175..bf11e084c215 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h | |||
@@ -54,6 +54,13 @@ struct hw_sb_info { | |||
54 | #define VFPF_QUEUE_DROP_TTL0 (1 << 2) | 54 | #define VFPF_QUEUE_DROP_TTL0 (1 << 2) |
55 | #define VFPF_QUEUE_DROP_UDP_CS_ERR (1 << 3) | 55 | #define VFPF_QUEUE_DROP_UDP_CS_ERR (1 << 3) |
56 | 56 | ||
57 | #define VFPF_RX_MASK_ACCEPT_NONE 0x00000000 | ||
58 | #define VFPF_RX_MASK_ACCEPT_MATCHED_UNICAST 0x00000001 | ||
59 | #define VFPF_RX_MASK_ACCEPT_MATCHED_MULTICAST 0x00000002 | ||
60 | #define VFPF_RX_MASK_ACCEPT_ALL_UNICAST 0x00000004 | ||
61 | #define VFPF_RX_MASK_ACCEPT_ALL_MULTICAST 0x00000008 | ||
62 | #define VFPF_RX_MASK_ACCEPT_BROADCAST 0x00000010 | ||
63 | |||
57 | enum { | 64 | enum { |
58 | PFVF_STATUS_WAITING = 0, | 65 | PFVF_STATUS_WAITING = 0, |
59 | PFVF_STATUS_SUCCESS, | 66 | PFVF_STATUS_SUCCESS, |