aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAriel Elior <ariele@broadcom.com>2013-01-01 00:22:43 -0500
committerDavid S. Miller <davem@davemloft.net>2013-01-02 04:45:07 -0500
commitabc5a021ba645cd162205209bd5664a0d4b866a6 (patch)
tree8dafb2e16c204c01f7387f454d32c40ae8c2e00f /drivers
parentd16132cef8a72ff7563aff95f03bf505779fe3e6 (diff)
bnx2x: Support PF <-> VF Bulletin Board
The PF <-> VF Bulletin Board is a simple interface between the PF and the VF. The main reason for the Bulletin Board is to allow the PF to be the initiator. The VF publishes at 'acquire' stage the GPA of a Bulletin Board structure it has allocated. The PF notes this GPA in the VF database. The VF samples the Bulletin Board periodically for new messages. The latest version of the BB is always used. 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')
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x.h6
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c87
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c94
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c13
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h18
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c65
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h37
8 files changed, 320 insertions, 2 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 2431ffd784ea..335b536d3671 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1259,6 +1259,12 @@ struct bnx2x {
1259 /* we set aside a copy of the acquire response */ 1259 /* we set aside a copy of the acquire response */
1260 struct pfvf_acquire_resp_tlv acquire_resp; 1260 struct pfvf_acquire_resp_tlv acquire_resp;
1261 1261
1262 /* bulletin board for messages from pf to vf */
1263 union pf_vf_bulletin *pf2vf_bulletin;
1264 dma_addr_t pf2vf_bulletin_mapping;
1265
1266 struct pf_vf_bulletin_content old_bulletin;
1267
1262 struct net_device *dev; 1268 struct net_device *dev;
1263 struct pci_dev *pdev; 1269 struct pci_dev *pdev;
1264 1270
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index cdb073a6297e..f9a15cbf73ef 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -3793,6 +3793,93 @@ int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)
3793 return 0; 3793 return 0;
3794} 3794}
3795 3795
3796/* New mac for VF. Consider these cases:
3797 * 1. VF hasn't been acquired yet - save the mac in local bulletin board and
3798 * supply at acquire.
3799 * 2. VF has already been acquired but has not yet initialized - store in local
3800 * bulletin board. mac will be posted on VF bulletin board after VF init. VF
3801 * will configure this mac when it is ready.
3802 * 3. VF has already initialized but has not yet setup a queue - post the new
3803 * mac on VF's bulletin board right now. VF will configure this mac when it
3804 * is ready.
3805 * 4. VF has already set a queue - delete any macs already configured for this
3806 * queue and manually config the new mac.
3807 * In any event, once this function has been called refuse any attempts by the
3808 * VF to configure any mac for itself except for this mac. In case of a race
3809 * where the VF fails to see the new post on its bulletin board before sending a
3810 * mac configuration request, the PF will simply fail the request and VF can try
3811 * again after consulting its bulletin board
3812 */
3813int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac)
3814{
3815 struct bnx2x *bp = netdev_priv(dev);
3816 int rc, q_logical_state, vfidx = queue;
3817 struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
3818 struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
3819
3820 /* if SRIOV is disabled there is nothing to do (and somewhere, someone
3821 * has erred).
3822 */
3823 if (!IS_SRIOV(bp)) {
3824 BNX2X_ERR("bnx2x_set_vf_mac called though sriov is disabled\n");
3825 return -EINVAL;
3826 }
3827
3828 if (!is_valid_ether_addr(mac)) {
3829 BNX2X_ERR("mac address invalid\n");
3830 return -EINVAL;
3831 }
3832
3833 /* update PF's copy of the VF's bulletin. will no longer accept mac
3834 * configuration requests from vf unless match this mac
3835 */
3836 bulletin->valid_bitmap |= 1 << MAC_ADDR_VALID;
3837 memcpy(bulletin->mac, mac, ETH_ALEN);
3838
3839 /* Post update on VF's bulletin board */
3840 rc = bnx2x_post_vf_bulletin(bp, vfidx);
3841 if (rc) {
3842 BNX2X_ERR("failed to update VF[%d] bulletin\n", vfidx);
3843 return rc;
3844 }
3845
3846 /* is vf initialized and queue set up? */
3847 q_logical_state =
3848 bnx2x_get_q_logical_state(bp, &bnx2x_vfq(vf, 0, sp_obj));
3849 if (vf->state == VF_ENABLED &&
3850 q_logical_state == BNX2X_Q_LOGICAL_STATE_ACTIVE) {
3851 /* configure the mac in device on this vf's queue */
3852 unsigned long flags = 0;
3853 struct bnx2x_vlan_mac_obj *mac_obj = &bnx2x_vfq(vf, 0, mac_obj);
3854
3855 /* must lock vfpf channel to protect against vf flows */
3856 bnx2x_lock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_MAC);
3857
3858 /* remove existing eth macs */
3859 rc = bnx2x_del_all_macs(bp, mac_obj, BNX2X_ETH_MAC, true);
3860 if (rc) {
3861 BNX2X_ERR("failed to delete eth macs\n");
3862 return -EINVAL;
3863 }
3864
3865 /* remove existing uc list macs */
3866 rc = bnx2x_del_all_macs(bp, mac_obj, BNX2X_UC_LIST_MAC, true);
3867 if (rc) {
3868 BNX2X_ERR("failed to delete uc_list macs\n");
3869 return -EINVAL;
3870 }
3871
3872 /* configure the new mac to device */
3873 __set_bit(RAMROD_COMP_WAIT, &flags);
3874 bnx2x_set_mac_one(bp, (u8 *)&bulletin->mac, mac_obj, true,
3875 BNX2X_ETH_MAC, &flags);
3876
3877 bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_MAC);
3878 }
3879
3880 return rc;
3881}
3882
3796/* called with rtnl_lock */ 3883/* called with rtnl_lock */
3797int bnx2x_change_mac_addr(struct net_device *dev, void *p) 3884int bnx2x_change_mac_addr(struct net_device *dev, void *p)
3798{ 3885{
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index cd1eaff842e1..23a1fa9a4cb3 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -496,6 +496,8 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev);
496/* setup_tc callback */ 496/* setup_tc callback */
497int bnx2x_setup_tc(struct net_device *dev, u8 num_tc); 497int bnx2x_setup_tc(struct net_device *dev, u8 num_tc);
498 498
499int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac);
500
499/* select_queue callback */ 501/* select_queue callback */
500u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb); 502u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb);
501 503
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 00c110e62993..216802a5176d 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -5248,6 +5248,61 @@ void bnx2x_drv_pulse(struct bnx2x *bp)
5248 bp->fw_drv_pulse_wr_seq); 5248 bp->fw_drv_pulse_wr_seq);
5249} 5249}
5250 5250
5251/* crc is the first field in the bulletin board. compute the crc over the
5252 * entire bulletin board excluding the crc field itself
5253 */
5254u32 bnx2x_crc_vf_bulletin(struct bnx2x *bp,
5255 struct pf_vf_bulletin_content *bulletin)
5256{
5257 return crc32(BULLETIN_CRC_SEED,
5258 ((u8 *)bulletin) + sizeof(bulletin->crc),
5259 BULLETIN_CONTENT_SIZE - sizeof(bulletin->crc));
5260}
5261
5262/* Check for new posts on the bulletin board */
5263enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp)
5264{
5265 struct pf_vf_bulletin_content bulletin = bp->pf2vf_bulletin->content;
5266 int attempts;
5267
5268 /* bulletin board hasn't changed since last sample */
5269 if (bp->old_bulletin.version == bulletin.version)
5270 return PFVF_BULLETIN_UNCHANGED;
5271
5272 /* validate crc of new bulletin board */
5273 if (bp->old_bulletin.version != bp->pf2vf_bulletin->content.version) {
5274 /* sampling structure in mid post may result with corrupted data
5275 * validate crc to ensure coherency.
5276 */
5277 for (attempts = 0; attempts < BULLETIN_ATTEMPTS; attempts++) {
5278 bulletin = bp->pf2vf_bulletin->content;
5279 if (bulletin.crc == bnx2x_crc_vf_bulletin(bp,
5280 &bulletin))
5281 break;
5282
5283 BNX2X_ERR("bad crc on bulletin board. contained %x computed %x\n",
5284 bulletin.crc,
5285 bnx2x_crc_vf_bulletin(bp, &bulletin));
5286 }
5287 if (attempts >= BULLETIN_ATTEMPTS) {
5288 BNX2X_ERR("pf to vf bulletin board crc was wrong %d consecutive times. Aborting\n",
5289 attempts);
5290 return PFVF_BULLETIN_CRC_ERR;
5291 }
5292 }
5293
5294 /* the mac address in bulletin board is valid and is new */
5295 if (bulletin.valid_bitmap & 1 << MAC_ADDR_VALID &&
5296 memcmp(bulletin.mac, bp->old_bulletin.mac, ETH_ALEN)) {
5297 /* update new mac to net device */
5298 memcpy(bp->dev->dev_addr, bulletin.mac, ETH_ALEN);
5299 }
5300
5301 /* copy new bulletin board to bp */
5302 bp->old_bulletin = bulletin;
5303
5304 return PFVF_BULLETIN_UPDATED;
5305}
5251 5306
5252static void bnx2x_timer(unsigned long data) 5307static void bnx2x_timer(unsigned long data)
5253{ 5308{
@@ -5284,6 +5339,10 @@ static void bnx2x_timer(unsigned long data)
5284 if (bp->state == BNX2X_STATE_OPEN) 5339 if (bp->state == BNX2X_STATE_OPEN)
5285 bnx2x_stats_handle(bp, STATS_EVENT_UPDATE); 5340 bnx2x_stats_handle(bp, STATS_EVENT_UPDATE);
5286 5341
5342 /* sample pf vf bulletin board for new posts from pf */
5343 if (IS_VF(bp))
5344 bnx2x_sample_bulletin(bp);
5345
5287 mod_timer(&bp->timer, jiffies + bp->current_interval); 5346 mod_timer(&bp->timer, jiffies + bp->current_interval);
5288} 5347}
5289 5348
@@ -11660,7 +11719,7 @@ static const struct net_device_ops bnx2x_netdev_ops = {
11660 .ndo_poll_controller = poll_bnx2x, 11719 .ndo_poll_controller = poll_bnx2x,
11661#endif 11720#endif
11662 .ndo_setup_tc = bnx2x_setup_tc, 11721 .ndo_setup_tc = bnx2x_setup_tc,
11663 11722 .ndo_set_vf_mac = bnx2x_set_vf_mac,
11664#ifdef NETDEV_FCOE_WWNN 11723#ifdef NETDEV_FCOE_WWNN
11665 .ndo_fcoe_get_wwn = bnx2x_fcoe_get_wwn, 11724 .ndo_fcoe_get_wwn = bnx2x_fcoe_get_wwn,
11666#endif 11725#endif
@@ -12321,6 +12380,11 @@ static int bnx2x_init_one(struct pci_dev *pdev,
12321 /* allocate vf2pf mailbox for vf to pf channel */ 12380 /* allocate vf2pf mailbox for vf to pf channel */
12322 BNX2X_PCI_ALLOC(bp->vf2pf_mbox, &bp->vf2pf_mbox_mapping, 12381 BNX2X_PCI_ALLOC(bp->vf2pf_mbox, &bp->vf2pf_mbox_mapping,
12323 sizeof(struct bnx2x_vf_mbx_msg)); 12382 sizeof(struct bnx2x_vf_mbx_msg));
12383
12384 /* allocate pf 2 vf bulletin board */
12385 BNX2X_PCI_ALLOC(bp->pf2vf_bulletin, &bp->pf2vf_bulletin_mapping,
12386 sizeof(union pf_vf_bulletin));
12387
12324 } else { 12388 } else {
12325 doorbell_size = BNX2X_L2_MAX_CID(bp) * (1 << BNX2X_DB_SHIFT); 12389 doorbell_size = BNX2X_L2_MAX_CID(bp) * (1 << BNX2X_DB_SHIFT);
12326 if (doorbell_size > pci_resource_len(pdev, 2)) { 12390 if (doorbell_size > pci_resource_len(pdev, 2)) {
@@ -13379,6 +13443,9 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
13379 req->resc_request.num_mac_filters = VF_ACQUIRE_MAC_FILTERS; 13443 req->resc_request.num_mac_filters = VF_ACQUIRE_MAC_FILTERS;
13380 req->resc_request.num_mc_filters = VF_ACQUIRE_MC_FILTERS; 13444 req->resc_request.num_mc_filters = VF_ACQUIRE_MC_FILTERS;
13381 13445
13446 /* pf 2 vf bulletin board address */
13447 req->bulletin_addr = bp->pf2vf_bulletin_mapping;
13448
13382 /* add list termination tlv */ 13449 /* add list termination tlv */
13383 bnx2x_add_tlv(bp, req, req->first_tlv.tl.length, CHANNEL_TLV_LIST_END, 13450 bnx2x_add_tlv(bp, req, req->first_tlv.tl.length, CHANNEL_TLV_LIST_END,
13384 sizeof(struct channel_list_end_tlv)); 13451 sizeof(struct channel_list_end_tlv));
@@ -13701,6 +13768,7 @@ int bnx2x_vfpf_teardown_queue(struct bnx2x *bp, int qidx)
13701 return rc; 13768 return rc;
13702 } 13769 }
13703 13770
13771 /* PF failed the transaction */
13704 if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 13772 if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
13705 BNX2X_ERR("TEARDOWN for queue %d failed: %d\n", qidx, 13773 BNX2X_ERR("TEARDOWN for queue %d failed: %d\n", qidx,
13706 resp->hdr.status); 13774 resp->hdr.status);
@@ -13727,6 +13795,9 @@ int bnx2x_vfpf_set_mac(struct bnx2x *bp)
13727 req->filters[0].flags = 13795 req->filters[0].flags =
13728 VFPF_Q_FILTER_DEST_MAC_VALID | VFPF_Q_FILTER_SET_MAC; 13796 VFPF_Q_FILTER_DEST_MAC_VALID | VFPF_Q_FILTER_SET_MAC;
13729 13797
13798 /* sample bulletin board for new mac */
13799 bnx2x_sample_bulletin(bp);
13800
13730 /* copy mac from device to request */ 13801 /* copy mac from device to request */
13731 memcpy(req->filters[0].mac, bp->dev->dev_addr, ETH_ALEN); 13802 memcpy(req->filters[0].mac, bp->dev->dev_addr, ETH_ALEN);
13732 13803
@@ -13744,7 +13815,26 @@ int bnx2x_vfpf_set_mac(struct bnx2x *bp)
13744 return rc; 13815 return rc;
13745 } 13816 }
13746 13817
13747 /* PF failed the transaction */ 13818 /* failure may mean PF was configured with a new mac for us */
13819 while (resp->hdr.status == PFVF_STATUS_FAILURE) {
13820 DP(BNX2X_MSG_IOV,
13821 "vfpf SET MAC failed. Check bulletin board for new posts\n");
13822
13823 /* check if bulletin board was updated */
13824 if (bnx2x_sample_bulletin(bp) == PFVF_BULLETIN_UPDATED) {
13825 /* copy mac from device to request */
13826 memcpy(req->filters[0].mac, bp->dev->dev_addr,
13827 ETH_ALEN);
13828
13829 /* send message to pf */
13830 rc = bnx2x_send_msg2pf(bp, &resp->hdr.status,
13831 bp->vf2pf_mbox_mapping);
13832 } else {
13833 /* no new info in bulletin */
13834 break;
13835 }
13836 }
13837
13748 if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 13838 if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
13749 BNX2X_ERR("vfpf SET MAC failed: %d\n", resp->hdr.status); 13839 BNX2X_ERR("vfpf SET MAC failed: %d\n", resp->hdr.status);
13750 return -EINVAL; 13840 return -EINVAL;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index c96ce5bbf446..1f1e823b7bdf 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -2058,6 +2058,10 @@ void bnx2x_iov_free_mem(struct bnx2x *bp)
2058 BNX2X_PCI_FREE(BP_VF_MBX_DMA(bp)->addr, 2058 BNX2X_PCI_FREE(BP_VF_MBX_DMA(bp)->addr,
2059 BP_VF_MBX_DMA(bp)->mapping, 2059 BP_VF_MBX_DMA(bp)->mapping,
2060 BP_VF_MBX_DMA(bp)->size); 2060 BP_VF_MBX_DMA(bp)->size);
2061
2062 BNX2X_PCI_FREE(BP_VF_BULLETIN_DMA(bp)->addr,
2063 BP_VF_BULLETIN_DMA(bp)->mapping,
2064 BP_VF_BULLETIN_DMA(bp)->size);
2061} 2065}
2062 2066
2063int bnx2x_iov_alloc_mem(struct bnx2x *bp) 2067int bnx2x_iov_alloc_mem(struct bnx2x *bp)
@@ -2097,6 +2101,12 @@ int bnx2x_iov_alloc_mem(struct bnx2x *bp)
2097 tot_size); 2101 tot_size);
2098 BP_VF_MBX_DMA(bp)->size = tot_size; 2102 BP_VF_MBX_DMA(bp)->size = tot_size;
2099 2103
2104 /* allocate local bulletin boards */
2105 tot_size = BNX2X_NR_VIRTFN(bp) * BULLETIN_CONTENT_SIZE;
2106 BNX2X_PCI_ALLOC(BP_VF_BULLETIN_DMA(bp)->addr,
2107 &BP_VF_BULLETIN_DMA(bp)->mapping, tot_size);
2108 BP_VF_BULLETIN_DMA(bp)->size = tot_size;
2109
2100 return 0; 2110 return 0;
2101 2111
2102alloc_mem_err: 2112alloc_mem_err:
@@ -2810,6 +2820,9 @@ int bnx2x_vf_init(struct bnx2x *bp, struct bnx2x_virtf *vf, dma_addr_t *sb_map)
2810 2820
2811 vf->state = VF_ENABLED; 2821 vf->state = VF_ENABLED;
2812 2822
2823 /* update vf bulletin board */
2824 bnx2x_post_vf_bulletin(bp, vf->index);
2825
2813 return 0; 2826 return 0;
2814} 2827}
2815 2828
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
index 25396fa3da1c..aab2a0525c26 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
@@ -378,6 +378,12 @@ struct bnx2x_vfdb {
378 struct bnx2x_vf_mbx mbxs[BNX2X_MAX_NUM_OF_VFS]; 378 struct bnx2x_vf_mbx mbxs[BNX2X_MAX_NUM_OF_VFS];
379#define BP_VF_MBX(bp, vfid) (&((bp)->vfdb->mbxs[(vfid)])) 379#define BP_VF_MBX(bp, vfid) (&((bp)->vfdb->mbxs[(vfid)]))
380 380
381 struct hw_dma bulletin_dma;
382#define BP_VF_BULLETIN_DMA(bp) (&((bp)->vfdb->bulletin_dma))
383#define BP_VF_BULLETIN(bp, vf) \
384 (((struct pf_vf_bulletin_content *)(BP_VF_BULLETIN_DMA(bp)->addr)) \
385 + (vf))
386
381 struct hw_dma sp_dma; 387 struct hw_dma sp_dma;
382#define bnx2x_vf_sp(bp, vf, field) ((bp)->vfdb->sp_dma.addr + \ 388#define bnx2x_vf_sp(bp, vf, field) ((bp)->vfdb->sp_dma.addr + \
383 (vf)->index * sizeof(struct bnx2x_vf_sp) + \ 389 (vf)->index * sizeof(struct bnx2x_vf_sp) + \
@@ -702,4 +708,16 @@ void bnx2x_dp_tlv_list(struct bnx2x *bp, void *tlvs_list);
702 708
703bool bnx2x_tlv_supported(u16 tlvtype); 709bool bnx2x_tlv_supported(u16 tlvtype);
704 710
711u32 bnx2x_crc_vf_bulletin(struct bnx2x *bp,
712 struct pf_vf_bulletin_content *bulletin);
713int bnx2x_post_vf_bulletin(struct bnx2x *bp, int vf);
714
715enum sample_bulletin_result {
716 PFVF_BULLETIN_UNCHANGED,
717 PFVF_BULLETIN_UPDATED,
718 PFVF_BULLETIN_CRC_ERR
719};
720
721enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp);
722
705#endif /* bnx2x_sriov.h */ 723#endif /* bnx2x_sriov.h */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
index ba8b95d016b0..b410b9fff209 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
@@ -297,6 +297,10 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
297 resc->num_mc_filters = 0; 297 resc->num_mc_filters = 0;
298 298
299 if (status == PFVF_STATUS_SUCCESS) { 299 if (status == PFVF_STATUS_SUCCESS) {
300 /* fill in the allocated resources */
301 struct pf_vf_bulletin_content *bulletin =
302 BP_VF_BULLETIN(bp, vf->index);
303
300 for_each_vfq(vf, i) 304 for_each_vfq(vf, i)
301 resc->hw_qid[i] = 305 resc->hw_qid[i] =
302 vfq_qzone_id(vf, vfq_get(vf, i)); 306 vfq_qzone_id(vf, vfq_get(vf, i));
@@ -305,6 +309,12 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
305 resc->hw_sbs[i].hw_sb_id = vf_igu_sb(vf, i); 309 resc->hw_sbs[i].hw_sb_id = vf_igu_sb(vf, i);
306 resc->hw_sbs[i].sb_qid = vf_hc_qzone(vf, i); 310 resc->hw_sbs[i].sb_qid = vf_hc_qzone(vf, i);
307 } 311 }
312
313 /* if a mac has been set for this vf, supply it */
314 if (bulletin->valid_bitmap & 1 << MAC_ADDR_VALID) {
315 memcpy(resc->current_mac_addr, bulletin->mac,
316 ETH_ALEN);
317 }
308 } 318 }
309 } 319 }
310 320
@@ -356,6 +366,9 @@ static void bnx2x_vf_mbx_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
356 /* acquire the resources */ 366 /* acquire the resources */
357 rc = bnx2x_vf_acquire(bp, vf, &acquire->resc_request); 367 rc = bnx2x_vf_acquire(bp, vf, &acquire->resc_request);
358 368
369 /* store address of vf's bulletin board */
370 vf->bulletin_map = acquire->bulletin_addr;
371
359 /* response */ 372 /* response */
360 bnx2x_vf_mbx_acquire_resp(bp, vf, mbx, rc); 373 bnx2x_vf_mbx_acquire_resp(bp, vf, mbx, rc);
361} 374}
@@ -766,11 +779,37 @@ static void bnx2x_vf_mbx_set_q_filters(struct bnx2x *bp,
766 struct bnx2x_vf_mbx *mbx) 779 struct bnx2x_vf_mbx *mbx)
767{ 780{
768 struct vfpf_set_q_filters_tlv *filters = &mbx->msg->req.set_q_filters; 781 struct vfpf_set_q_filters_tlv *filters = &mbx->msg->req.set_q_filters;
782 struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vf->index);
769 struct bnx2x_vfop_cmd cmd = { 783 struct bnx2x_vfop_cmd cmd = {
770 .done = bnx2x_vf_mbx_resp, 784 .done = bnx2x_vf_mbx_resp,
771 .block = false, 785 .block = false,
772 }; 786 };
773 787
788 /* if a mac was already set for this VF via the set vf mac ndo, we only
789 * accept mac configurations of that mac. Why accept them at all?
790 * because PF may have been unable to configure the mac at the time
791 * since queue was not set up.
792 */
793 if (bulletin->valid_bitmap & 1 << MAC_ADDR_VALID) {
794 /* once a mac was set by ndo can only accept a single mac... */
795 if (filters->n_mac_vlan_filters > 1) {
796 BNX2X_ERR("VF[%d] requested the addition of multiple macs after set_vf_mac ndo was called\n",
797 vf->abs_vfid);
798 vf->op_rc = -EPERM;
799 goto response;
800 }
801
802 /* ...and only the mac set by the ndo */
803 if (filters->n_mac_vlan_filters == 1 &&
804 memcmp(filters->filters->mac, bulletin->mac, ETH_ALEN)) {
805 BNX2X_ERR("VF[%d] requested the addition of a mac address not matching the one configured by set_vf_mac ndo\n",
806 vf->abs_vfid);
807
808 vf->op_rc = -EPERM;
809 goto response;
810 }
811 }
812
774 /* verify vf_qid */ 813 /* verify vf_qid */
775 if (filters->vf_qid > vf_rxq_count(vf)) 814 if (filters->vf_qid > vf_rxq_count(vf))
776 goto response; 815 goto response;
@@ -968,3 +1007,29 @@ mbx_error:
968mbx_done: 1007mbx_done:
969 return; 1008 return;
970} 1009}
1010
1011/* propagate local bulletin board to vf */
1012int bnx2x_post_vf_bulletin(struct bnx2x *bp, int vf)
1013{
1014 struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vf);
1015 dma_addr_t pf_addr = BP_VF_BULLETIN_DMA(bp)->mapping +
1016 vf * BULLETIN_CONTENT_SIZE;
1017 dma_addr_t vf_addr = bnx2x_vf(bp, vf, bulletin_map);
1018 u32 len = BULLETIN_CONTENT_SIZE;
1019 int rc;
1020
1021 /* can only update vf after init took place */
1022 if (bnx2x_vf(bp, vf, state) != VF_ENABLED &&
1023 bnx2x_vf(bp, vf, state) != VF_ACQUIRED)
1024 return 0;
1025
1026 /* increment bulletin board version and compute crc */
1027 bulletin->version++;
1028 bulletin->crc = bnx2x_crc_vf_bulletin(bp, bulletin);
1029
1030 /* propagate bulletin board via dmae to vm memory */
1031 rc = bnx2x_copy32_vf_dmae(bp, false, pf_addr,
1032 bnx2x_vf(bp, vf, abs_vfid), U64_HI(vf_addr),
1033 U64_LO(vf_addr), len/4);
1034 return rc;
1035}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
index 554c11911533..9f07adaf06f4 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
@@ -37,6 +37,7 @@ struct hw_sb_info {
37 * A.K.A VF-PF mailbox 37 * A.K.A VF-PF mailbox
38 */ 38 */
39#define TLV_BUFFER_SIZE 1024 39#define TLV_BUFFER_SIZE 1024
40#define PF_VF_BULLETIN_SIZE 512
40 41
41#define VFPF_QUEUE_FLG_TPA 0x0001 42#define VFPF_QUEUE_FLG_TPA 0x0001
42#define VFPF_QUEUE_FLG_TPA_IPV6 0x0002 43#define VFPF_QUEUE_FLG_TPA_IPV6 0x0002
@@ -60,6 +61,9 @@ struct hw_sb_info {
60#define VFPF_RX_MASK_ACCEPT_ALL_UNICAST 0x00000004 61#define VFPF_RX_MASK_ACCEPT_ALL_UNICAST 0x00000004
61#define VFPF_RX_MASK_ACCEPT_ALL_MULTICAST 0x00000008 62#define VFPF_RX_MASK_ACCEPT_ALL_MULTICAST 0x00000008
62#define VFPF_RX_MASK_ACCEPT_BROADCAST 0x00000010 63#define VFPF_RX_MASK_ACCEPT_BROADCAST 0x00000010
64#define BULLETIN_CONTENT_SIZE (sizeof(struct pf_vf_bulletin_content))
65#define BULLETIN_ATTEMPTS 5 /* crc failures before throwing towel */
66#define BULLETIN_CRC_SEED 0
63 67
64enum { 68enum {
65 PFVF_STATUS_WAITING = 0, 69 PFVF_STATUS_WAITING = 0,
@@ -299,6 +303,38 @@ union pfvf_tlvs {
299 struct tlv_buffer_size tlv_buf_size; 303 struct tlv_buffer_size tlv_buf_size;
300}; 304};
301 305
306/* This is a structure which is allocated in the VF, which the PF may update
307 * when it deems it necessary to do so. The bulletin board is sampled
308 * periodically by the VF. A copy per VF is maintained in the PF (to prevent
309 * loss of data upon multiple updates (or the need for read modify write)).
310 */
311struct pf_vf_bulletin_size {
312 u8 size[PF_VF_BULLETIN_SIZE];
313};
314
315struct pf_vf_bulletin_content {
316 u32 crc; /* crc of structure to ensure is not in
317 * mid-update
318 */
319 u32 version;
320
321 aligned_u64 valid_bitmap; /* bitmap indicating which fields
322 * hold valid values
323 */
324
325#define MAC_ADDR_VALID 0 /* alert the vf that a new mac address
326 * is available for it
327 */
328
329 u8 mac[ETH_ALEN];
330 u8 padding[2];
331};
332
333union pf_vf_bulletin {
334 struct pf_vf_bulletin_content content;
335 struct pf_vf_bulletin_size size;
336};
337
302#define MAX_TLVS_IN_LIST 50 338#define MAX_TLVS_IN_LIST 50
303 339
304enum channel_tlvs { 340enum channel_tlvs {
@@ -313,6 +349,7 @@ enum channel_tlvs {
313 CHANNEL_TLV_PF_RELEASE_VF, 349 CHANNEL_TLV_PF_RELEASE_VF,
314 CHANNEL_TLV_LIST_END, 350 CHANNEL_TLV_LIST_END,
315 CHANNEL_TLV_FLR, 351 CHANNEL_TLV_FLR,
352 CHANNEL_TLV_PF_SET_MAC,
316 CHANNEL_TLV_MAX 353 CHANNEL_TLV_MAX
317}; 354};
318 355