aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAriel Elior <ariele@broadcom.com>2013-01-01 00:22:34 -0500
committerDavid S. Miller <davem@davemloft.net>2013-01-02 04:45:06 -0500
commit8ca5e17e58c953b9a9dbd4974c554b25c6d70b1a (patch)
treebfb964684236920270f74b165c69b55eebd90def
parentfd1fc79dd6deb88ebf38ae9673190da999b3209f (diff)
bnx2x: Support of PF driver of a VF acquire request
When a VF is probed by the VF driver, the VF driver sends an 'acquire' request over the VF <-> PF channel for the resources it needs to operate (interrupts, queues, etc). The PF driver either ratifies the request and allocates the resources, responds with the maximum values it will allow the VF to acquire, or fails the request entirely if there is a problem. 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>
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c28
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h9
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c13
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c199
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h43
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c195
6 files changed, 476 insertions, 11 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index e8bb146747ec..022c491cd0fb 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -85,6 +85,34 @@ static inline void bnx2x_move_fp(struct bnx2x *bp, int from, int to)
85 to_fp->txdata_ptr[0] = &bp->bnx2x_txq[new_txdata_index]; 85 to_fp->txdata_ptr[0] = &bp->bnx2x_txq[new_txdata_index];
86} 86}
87 87
88/**
89 * bnx2x_fill_fw_str - Fill buffer with FW version string.
90 *
91 * @bp: driver handle
92 * @buf: character buffer to fill with the fw name
93 * @buf_len: length of the above buffer
94 *
95 */
96void bnx2x_fill_fw_str(struct bnx2x *bp, char *buf, size_t buf_len)
97{
98 if (IS_PF(bp)) {
99 u8 phy_fw_ver[PHY_FW_VER_LEN];
100
101 phy_fw_ver[0] = '\0';
102 bnx2x_get_ext_phy_fw_version(&bp->link_params,
103 phy_fw_ver, PHY_FW_VER_LEN);
104 strlcpy(buf, bp->fw_ver, buf_len);
105 snprintf(buf + strlen(bp->fw_ver), 32 - strlen(bp->fw_ver),
106 "bc %d.%d.%d%s%s",
107 (bp->common.bc_ver & 0xff0000) >> 16,
108 (bp->common.bc_ver & 0xff00) >> 8,
109 (bp->common.bc_ver & 0xff),
110 ((phy_fw_ver[0] != '\0') ? " phy " : ""), phy_fw_ver);
111 } else {
112 strlcpy(buf, bp->acquire_resp.pfdev_info.fw_ver, buf_len);
113 }
114}
115
88int load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */ 116int load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */
89 117
90/* free skb in the packet ring at pos idx 118/* free skb in the packet ring at pos idx
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index 9ee67fa0dd94..cd1eaff842e1 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -1401,4 +1401,13 @@ static inline bool bnx2x_is_valid_ether_addr(struct bnx2x *bp, u8 *addr)
1401 return false; 1401 return false;
1402} 1402}
1403 1403
1404/**
1405 * bnx2x_fill_fw_str - Fill buffer with FW version string.
1406 *
1407 * @bp: driver handle
1408 * @buf: character buffer to fill with the fw name
1409 * @buf_len: length of the above buffer
1410 *
1411 */
1412void bnx2x_fill_fw_str(struct bnx2x *bp, char *buf, size_t buf_len);
1404#endif /* BNX2X_CMN_H */ 1413#endif /* BNX2X_CMN_H */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index b7c82f9e452a..292634f0e90b 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -817,21 +817,12 @@ static void bnx2x_get_drvinfo(struct net_device *dev,
817 struct ethtool_drvinfo *info) 817 struct ethtool_drvinfo *info)
818{ 818{
819 struct bnx2x *bp = netdev_priv(dev); 819 struct bnx2x *bp = netdev_priv(dev);
820 u8 phy_fw_ver[PHY_FW_VER_LEN];
821 820
822 strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver)); 821 strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
823 strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version)); 822 strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
824 823
825 phy_fw_ver[0] = '\0'; 824 bnx2x_fill_fw_str(bp, info->fw_version, sizeof(info->fw_version));
826 bnx2x_get_ext_phy_fw_version(&bp->link_params, 825
827 phy_fw_ver, PHY_FW_VER_LEN);
828 strlcpy(info->fw_version, bp->fw_ver, sizeof(info->fw_version));
829 snprintf(info->fw_version + strlen(bp->fw_ver), 32 - strlen(bp->fw_ver),
830 "bc %d.%d.%d%s%s",
831 (bp->common.bc_ver & 0xff0000) >> 16,
832 (bp->common.bc_ver & 0xff00) >> 8,
833 (bp->common.bc_ver & 0xff),
834 ((phy_fw_ver[0] != '\0') ? " phy " : ""), phy_fw_ver);
835 strlcpy(info->bus_info, pci_name(bp->pdev), sizeof(info->bus_info)); 826 strlcpy(info->bus_info, pci_name(bp->pdev), sizeof(info->bus_info));
836 info->n_stats = BNX2X_NUM_STATS; 827 info->n_stats = BNX2X_NUM_STATS;
837 info->testinfo_len = BNX2X_NUM_TESTS(bp); 828 info->testinfo_len = BNX2X_NUM_TESTS(bp);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index 9233117ea506..de42f665c1fa 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -593,6 +593,63 @@ alloc_mem_err:
593 return -ENOMEM; 593 return -ENOMEM;
594} 594}
595 595
596static void bnx2x_vfq_init(struct bnx2x *bp, struct bnx2x_virtf *vf,
597 struct bnx2x_vf_queue *q)
598{
599 u8 cl_id = vfq_cl_id(vf, q);
600 u8 func_id = FW_VF_HANDLE(vf->abs_vfid);
601 unsigned long q_type = 0;
602
603 set_bit(BNX2X_Q_TYPE_HAS_TX, &q_type);
604 set_bit(BNX2X_Q_TYPE_HAS_RX, &q_type);
605
606 /* Queue State object */
607 bnx2x_init_queue_obj(bp, &q->sp_obj,
608 cl_id, &q->cid, 1, func_id,
609 bnx2x_vf_sp(bp, vf, q_data),
610 bnx2x_vf_sp_map(bp, vf, q_data),
611 q_type);
612
613 DP(BNX2X_MSG_IOV,
614 "initialized vf %d's queue object. func id set to %d\n",
615 vf->abs_vfid, q->sp_obj.func_id);
616
617 /* mac/vlan objects are per queue, but only those
618 * that belong to the leading queue are initialized
619 */
620 if (vfq_is_leading(q)) {
621 /* mac */
622 bnx2x_init_mac_obj(bp, &q->mac_obj,
623 cl_id, q->cid, func_id,
624 bnx2x_vf_sp(bp, vf, mac_rdata),
625 bnx2x_vf_sp_map(bp, vf, mac_rdata),
626 BNX2X_FILTER_MAC_PENDING,
627 &vf->filter_state,
628 BNX2X_OBJ_TYPE_RX_TX,
629 &bp->macs_pool);
630 /* vlan */
631 bnx2x_init_vlan_obj(bp, &q->vlan_obj,
632 cl_id, q->cid, func_id,
633 bnx2x_vf_sp(bp, vf, vlan_rdata),
634 bnx2x_vf_sp_map(bp, vf, vlan_rdata),
635 BNX2X_FILTER_VLAN_PENDING,
636 &vf->filter_state,
637 BNX2X_OBJ_TYPE_RX_TX,
638 &bp->vlans_pool);
639
640 /* mcast */
641 bnx2x_init_mcast_obj(bp, &vf->mcast_obj, cl_id,
642 q->cid, func_id, func_id,
643 bnx2x_vf_sp(bp, vf, mcast_rdata),
644 bnx2x_vf_sp_map(bp, vf, mcast_rdata),
645 BNX2X_FILTER_MCAST_PENDING,
646 &vf->filter_state,
647 BNX2X_OBJ_TYPE_RX_TX);
648
649 vf->leading_rss = cl_id;
650 }
651}
652
596/* called by bnx2x_nic_load */ 653/* called by bnx2x_nic_load */
597int bnx2x_iov_nic_init(struct bnx2x *bp) 654int bnx2x_iov_nic_init(struct bnx2x *bp)
598{ 655{
@@ -940,3 +997,145 @@ void bnx2x_iov_sp_task(struct bnx2x *bp)
940 } 997 }
941 } 998 }
942} 999}
1000
1001u8 bnx2x_vf_max_queue_cnt(struct bnx2x *bp, struct bnx2x_virtf *vf)
1002{
1003 return min_t(u8, min_t(u8, vf_sb_count(vf), BNX2X_CIDS_PER_VF),
1004 BNX2X_VF_MAX_QUEUES);
1005}
1006
1007static
1008int bnx2x_vf_chk_avail_resc(struct bnx2x *bp, struct bnx2x_virtf *vf,
1009 struct vf_pf_resc_request *req_resc)
1010{
1011 u8 rxq_cnt = vf_rxq_count(vf) ? : bnx2x_vf_max_queue_cnt(bp, vf);
1012 u8 txq_cnt = vf_txq_count(vf) ? : bnx2x_vf_max_queue_cnt(bp, vf);
1013
1014 return ((req_resc->num_rxqs <= rxq_cnt) &&
1015 (req_resc->num_txqs <= txq_cnt) &&
1016 (req_resc->num_sbs <= vf_sb_count(vf)) &&
1017 (req_resc->num_mac_filters <= vf_mac_rules_cnt(vf)) &&
1018 (req_resc->num_vlan_filters <= vf_vlan_rules_cnt(vf)));
1019}
1020
1021/* CORE VF API */
1022int bnx2x_vf_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
1023 struct vf_pf_resc_request *resc)
1024{
1025 int base_vf_cid = (BP_VFDB(bp)->sriov.first_vf_in_pf + vf->index) *
1026 BNX2X_CIDS_PER_VF;
1027
1028 union cdu_context *base_cxt = (union cdu_context *)
1029 BP_VF_CXT_PAGE(bp, base_vf_cid/ILT_PAGE_CIDS)->addr +
1030 (base_vf_cid & (ILT_PAGE_CIDS-1));
1031 int i;
1032
1033 /* if state is 'acquired' the VF was not released or FLR'd, in
1034 * this case the returned resources match the acquired already
1035 * acquired resources. Verify that the requested numbers do
1036 * not exceed the already acquired numbers.
1037 */
1038 if (vf->state == VF_ACQUIRED) {
1039 DP(BNX2X_MSG_IOV, "VF[%d] Trying to re-acquire resources (VF was not released or FLR'd)\n",
1040 vf->abs_vfid);
1041
1042 if (!bnx2x_vf_chk_avail_resc(bp, vf, resc)) {
1043 BNX2X_ERR("VF[%d] When re-acquiring resources, requested numbers must be <= then previously acquired numbers\n",
1044 vf->abs_vfid);
1045 return -EINVAL;
1046 }
1047 return 0;
1048 }
1049
1050 /* Otherwise vf state must be 'free' or 'reset' */
1051 if (vf->state != VF_FREE && vf->state != VF_RESET) {
1052 BNX2X_ERR("VF[%d] Can not acquire a VF with state %d\n",
1053 vf->abs_vfid, vf->state);
1054 return -EINVAL;
1055 }
1056
1057 /* static allocation:
1058 * the global maximum number are fixed per VF. fail the request if
1059 * requested number exceed these globals
1060 */
1061 if (!bnx2x_vf_chk_avail_resc(bp, vf, resc)) {
1062 DP(BNX2X_MSG_IOV,
1063 "cannot fulfill vf resource request. Placing maximal available values in response\n");
1064 /* set the max resource in the vf */
1065 return -ENOMEM;
1066 }
1067
1068 /* Set resources counters - 0 request means max available */
1069 vf_sb_count(vf) = resc->num_sbs;
1070 vf_rxq_count(vf) = resc->num_rxqs ? : bnx2x_vf_max_queue_cnt(bp, vf);
1071 vf_txq_count(vf) = resc->num_txqs ? : bnx2x_vf_max_queue_cnt(bp, vf);
1072 if (resc->num_mac_filters)
1073 vf_mac_rules_cnt(vf) = resc->num_mac_filters;
1074 if (resc->num_vlan_filters)
1075 vf_vlan_rules_cnt(vf) = resc->num_vlan_filters;
1076
1077 DP(BNX2X_MSG_IOV,
1078 "Fulfilling vf request: sb count %d, tx_count %d, rx_count %d, mac_rules_count %d, vlan_rules_count %d\n",
1079 vf_sb_count(vf), vf_rxq_count(vf),
1080 vf_txq_count(vf), vf_mac_rules_cnt(vf),
1081 vf_vlan_rules_cnt(vf));
1082
1083 /* Initialize the queues */
1084 if (!vf->vfqs) {
1085 DP(BNX2X_MSG_IOV, "vf->vfqs was not allocated\n");
1086 return -EINVAL;
1087 }
1088
1089 for_each_vfq(vf, i) {
1090 struct bnx2x_vf_queue *q = vfq_get(vf, i);
1091
1092 if (!q) {
1093 DP(BNX2X_MSG_IOV, "q number %d was not allocated\n", i);
1094 return -EINVAL;
1095 }
1096
1097 q->index = i;
1098 q->cxt = &((base_cxt + i)->eth);
1099 q->cid = BNX2X_FIRST_VF_CID + base_vf_cid + i;
1100
1101 DP(BNX2X_MSG_IOV, "VFQ[%d:%d]: index %d, cid 0x%x, cxt %p\n",
1102 vf->abs_vfid, i, q->index, q->cid, q->cxt);
1103
1104 /* init SP objects */
1105 bnx2x_vfq_init(bp, vf, q);
1106 }
1107 vf->state = VF_ACQUIRED;
1108 return 0;
1109}
1110
1111void bnx2x_lock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf,
1112 enum channel_tlvs tlv)
1113{
1114 /* lock the channel */
1115 mutex_lock(&vf->op_mutex);
1116
1117 /* record the locking op */
1118 vf->op_current = tlv;
1119
1120 /* log the lock */
1121 DP(BNX2X_MSG_IOV, "VF[%d]: vf pf channel locked by %d\n",
1122 vf->abs_vfid, tlv);
1123}
1124
1125void bnx2x_unlock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf,
1126 enum channel_tlvs expected_tlv)
1127{
1128 WARN(expected_tlv != vf->op_current,
1129 "lock mismatch: expected %d found %d", expected_tlv,
1130 vf->op_current);
1131
1132 /* lock the channel */
1133 mutex_unlock(&vf->op_mutex);
1134
1135 /* log the unlock */
1136 DP(BNX2X_MSG_IOV, "VF[%d]: vf pf channel unlocked by %d\n",
1137 vf->abs_vfid, vf->op_current);
1138
1139 /* record the locking op */
1140 vf->op_current = CHANNEL_TLV_NONE;
1141}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
index 6af7bde74ddc..5248ebe207f8 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
@@ -19,9 +19,13 @@
19#ifndef BNX2X_SRIOV_H 19#ifndef BNX2X_SRIOV_H
20#define BNX2X_SRIOV_H 20#define BNX2X_SRIOV_H
21 21
22#include "bnx2x_vfpf.h"
23#include "bnx2x_cmn.h"
24
22/* The bnx2x device structure holds vfdb structure described below. 25/* The bnx2x device structure holds vfdb structure described below.
23 * The VF array is indexed by the relative vfid. 26 * The VF array is indexed by the relative vfid.
24 */ 27 */
28#define BNX2X_VF_MAX_QUEUES 16
25struct bnx2x_sriov { 29struct bnx2x_sriov {
26 u32 first_vf_in_pf; 30 u32 first_vf_in_pf;
27 31
@@ -257,6 +261,12 @@ struct bnx2x_virtf {
257#define for_each_vf(bp, var) \ 261#define for_each_vf(bp, var) \
258 for ((var) = 0; (var) < BNX2X_NR_VIRTFN(bp); (var)++) 262 for ((var) = 0; (var) < BNX2X_NR_VIRTFN(bp); (var)++)
259 263
264#define for_each_vfq(vf, var) \
265 for ((var) = 0; (var) < vf_rxq_count(vf); (var)++)
266
267#define for_each_vf_sb(vf, var) \
268 for ((var) = 0; (var) < vf_sb_count(vf); (var)++)
269
260#define HW_VF_HANDLE(bp, abs_vfid) \ 270#define HW_VF_HANDLE(bp, abs_vfid) \
261 (u16)(BP_ABS_FUNC((bp)) | (1<<3) | ((u16)(abs_vfid) << 4)) 271 (u16)(BP_ABS_FUNC((bp)) | (1<<3) | ((u16)(abs_vfid) << 4))
262 272
@@ -265,6 +275,13 @@ struct bnx2x_virtf {
265#define FW_VF_HANDLE(abs_vfid) \ 275#define FW_VF_HANDLE(abs_vfid) \
266 (abs_vfid + FW_PF_MAX_HANDLE) 276 (abs_vfid + FW_PF_MAX_HANDLE)
267 277
278/* locking and unlocking the channel mutex */
279void bnx2x_lock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf,
280 enum channel_tlvs tlv);
281
282void bnx2x_unlock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf,
283 enum channel_tlvs expected_tlv);
284
268/* VF mail box (aka vf-pf channel) */ 285/* VF mail box (aka vf-pf channel) */
269 286
270/* a container for the bi-directional vf<-->pf messages. 287/* a container for the bi-directional vf<-->pf messages.
@@ -365,11 +382,32 @@ static inline struct bnx2x_vf_queue *vfq_get(struct bnx2x_virtf *vf, u8 index)
365 return &(vf->vfqs[index]); 382 return &(vf->vfqs[index]);
366} 383}
367 384
385static inline bool vfq_is_leading(struct bnx2x_vf_queue *vfq)
386{
387 return (vfq->index == 0);
388}
389
390/* FW ids */
368static inline u8 vf_igu_sb(struct bnx2x_virtf *vf, u16 sb_idx) 391static inline u8 vf_igu_sb(struct bnx2x_virtf *vf, u16 sb_idx)
369{ 392{
370 return vf->igu_base_id + sb_idx; 393 return vf->igu_base_id + sb_idx;
371} 394}
372 395
396static inline u8 vf_hc_qzone(struct bnx2x_virtf *vf, u16 sb_idx)
397{
398 return vf_igu_sb(vf, sb_idx);
399}
400
401static u8 vfq_cl_id(struct bnx2x_virtf *vf, struct bnx2x_vf_queue *q)
402{
403 return vf->igu_base_id + q->index;
404}
405
406static inline u8 vfq_qzone_id(struct bnx2x_virtf *vf, struct bnx2x_vf_queue *q)
407{
408 return vfq_cl_id(vf, q);
409}
410
373/* global iov routines */ 411/* global iov routines */
374int bnx2x_iov_init_ilt(struct bnx2x *bp, u16 line); 412int bnx2x_iov_init_ilt(struct bnx2x *bp, u16 line);
375int bnx2x_iov_init_one(struct bnx2x *bp, int int_mode_param, int num_vfs_param); 413int bnx2x_iov_init_one(struct bnx2x *bp, int int_mode_param, int num_vfs_param);
@@ -387,6 +425,10 @@ void bnx2x_iov_sp_task(struct bnx2x *bp);
387/* global vf mailbox routines */ 425/* global vf mailbox routines */
388void bnx2x_vf_mbx(struct bnx2x *bp, struct vf_pf_event_data *vfpf_event); 426void bnx2x_vf_mbx(struct bnx2x *bp, struct vf_pf_event_data *vfpf_event);
389void bnx2x_vf_enable_mbx(struct bnx2x *bp, u8 abs_vfid); 427void bnx2x_vf_enable_mbx(struct bnx2x *bp, u8 abs_vfid);
428/* acquire */
429int bnx2x_vf_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
430 struct vf_pf_resc_request *resc);
431
390static inline struct bnx2x_vfop *bnx2x_vfop_cur(struct bnx2x *bp, 432static inline struct bnx2x_vfop *bnx2x_vfop_cur(struct bnx2x *bp,
391 struct bnx2x_virtf *vf) 433 struct bnx2x_virtf *vf)
392{ 434{
@@ -396,6 +438,7 @@ static inline struct bnx2x_vfop *bnx2x_vfop_cur(struct bnx2x *bp,
396} 438}
397 439
398int bnx2x_vf_idx_by_abs_fid(struct bnx2x *bp, u16 abs_vfid); 440int bnx2x_vf_idx_by_abs_fid(struct bnx2x *bp, u16 abs_vfid);
441u8 bnx2x_vf_max_queue_cnt(struct bnx2x *bp, struct bnx2x_virtf *vf);
399/* VF FLR helpers */ 442/* VF FLR helpers */
400int bnx2x_vf_flr_clnup_epilog(struct bnx2x *bp, u8 abs_vfid); 443int bnx2x_vf_flr_clnup_epilog(struct bnx2x *bp, u8 abs_vfid);
401void bnx2x_vf_enable_access(struct bnx2x *bp, u8 abs_vfid); 444void bnx2x_vf_enable_access(struct bnx2x *bp, u8 abs_vfid);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
index 6e5e0638ee81..3b6b577a28ce 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
@@ -185,6 +185,176 @@ static int bnx2x_copy32_vf_dmae(struct bnx2x *bp, u8 from_vf,
185 return bnx2x_issue_dmae_with_comp(bp, &dmae); 185 return bnx2x_issue_dmae_with_comp(bp, &dmae);
186} 186}
187 187
188static void bnx2x_vf_mbx_resp(struct bnx2x *bp, struct bnx2x_virtf *vf)
189{
190 struct bnx2x_vf_mbx *mbx = BP_VF_MBX(bp, vf->index);
191 u64 vf_addr;
192 dma_addr_t pf_addr;
193 u16 length, type;
194 int rc;
195 struct pfvf_general_resp_tlv *resp = &mbx->msg->resp.general_resp;
196
197 /* prepare response */
198 type = mbx->first_tlv.tl.type;
199 length = type == CHANNEL_TLV_ACQUIRE ?
200 sizeof(struct pfvf_acquire_resp_tlv) :
201 sizeof(struct pfvf_general_resp_tlv);
202 bnx2x_add_tlv(bp, resp, 0, type, length);
203 resp->hdr.status = bnx2x_pfvf_status_codes(vf->op_rc);
204 bnx2x_add_tlv(bp, resp, length, CHANNEL_TLV_LIST_END,
205 sizeof(struct channel_list_end_tlv));
206 bnx2x_dp_tlv_list(bp, resp);
207 DP(BNX2X_MSG_IOV, "mailbox vf address hi 0x%x, lo 0x%x, offset 0x%x\n",
208 mbx->vf_addr_hi, mbx->vf_addr_lo, mbx->first_tlv.resp_msg_offset);
209
210 /* send response */
211 vf_addr = HILO_U64(mbx->vf_addr_hi, mbx->vf_addr_lo) +
212 mbx->first_tlv.resp_msg_offset;
213 pf_addr = mbx->msg_mapping +
214 offsetof(struct bnx2x_vf_mbx_msg, resp);
215
216 /* copy the response body, if there is one, before the header, as the vf
217 * is sensitive to the header being written
218 */
219 if (resp->hdr.tl.length > sizeof(u64)) {
220 length = resp->hdr.tl.length - sizeof(u64);
221 vf_addr += sizeof(u64);
222 pf_addr += sizeof(u64);
223 rc = bnx2x_copy32_vf_dmae(bp, false, pf_addr, vf->abs_vfid,
224 U64_HI(vf_addr),
225 U64_LO(vf_addr),
226 length/4);
227 if (rc) {
228 BNX2X_ERR("Failed to copy response body to VF %d\n",
229 vf->abs_vfid);
230 return;
231 }
232 vf_addr -= sizeof(u64);
233 pf_addr -= sizeof(u64);
234 }
235
236 /* ack the FW */
237 storm_memset_vf_mbx_ack(bp, vf->abs_vfid);
238 mmiowb();
239
240 /* initiate dmae to send the response */
241 mbx->flags &= ~VF_MSG_INPROCESS;
242
243 /* copy the response header including status-done field,
244 * must be last dmae, must be after FW is acked
245 */
246 rc = bnx2x_copy32_vf_dmae(bp, false, pf_addr, vf->abs_vfid,
247 U64_HI(vf_addr),
248 U64_LO(vf_addr),
249 sizeof(u64)/4);
250
251 /* unlock channel mutex */
252 bnx2x_unlock_vf_pf_channel(bp, vf, mbx->first_tlv.tl.type);
253
254 if (rc) {
255 BNX2X_ERR("Failed to copy response status to VF %d\n",
256 vf->abs_vfid);
257 }
258 return;
259}
260
261static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
262 struct bnx2x_vf_mbx *mbx, int vfop_status)
263{
264 int i;
265 struct pfvf_acquire_resp_tlv *resp = &mbx->msg->resp.acquire_resp;
266 struct pf_vf_resc *resc = &resp->resc;
267 u8 status = bnx2x_pfvf_status_codes(vfop_status);
268
269 memset(resp, 0, sizeof(*resp));
270
271 /* fill in pfdev info */
272 resp->pfdev_info.chip_num = bp->common.chip_id;
273 resp->pfdev_info.db_size = (1 << BNX2X_DB_SHIFT);
274 resp->pfdev_info.indices_per_sb = HC_SB_MAX_INDICES_E2;
275 resp->pfdev_info.pf_cap = (PFVF_CAP_RSS |
276 /* PFVF_CAP_DHC |*/ PFVF_CAP_TPA);
277 bnx2x_fill_fw_str(bp, resp->pfdev_info.fw_ver,
278 sizeof(resp->pfdev_info.fw_ver));
279
280 if (status == PFVF_STATUS_NO_RESOURCE ||
281 status == PFVF_STATUS_SUCCESS) {
282 /* set resources numbers, if status equals NO_RESOURCE these
283 * are max possible numbers
284 */
285 resc->num_rxqs = vf_rxq_count(vf) ? :
286 bnx2x_vf_max_queue_cnt(bp, vf);
287 resc->num_txqs = vf_txq_count(vf) ? :
288 bnx2x_vf_max_queue_cnt(bp, vf);
289 resc->num_sbs = vf_sb_count(vf);
290 resc->num_mac_filters = vf_mac_rules_cnt(vf);
291 resc->num_vlan_filters = vf_vlan_rules_cnt(vf);
292 resc->num_mc_filters = 0;
293
294 if (status == PFVF_STATUS_SUCCESS) {
295 for_each_vfq(vf, i)
296 resc->hw_qid[i] =
297 vfq_qzone_id(vf, vfq_get(vf, i));
298
299 for_each_vf_sb(vf, i) {
300 resc->hw_sbs[i].hw_sb_id = vf_igu_sb(vf, i);
301 resc->hw_sbs[i].sb_qid = vf_hc_qzone(vf, i);
302 }
303 }
304 }
305
306 DP(BNX2X_MSG_IOV, "VF[%d] ACQUIRE_RESPONSE: pfdev_info- chip_num=0x%x, db_size=%d, idx_per_sb=%d, pf_cap=0x%x\n"
307 "resources- n_rxq-%d, n_txq-%d, n_sbs-%d, n_macs-%d, n_vlans-%d, n_mcs-%d, fw_ver: '%s'\n",
308 vf->abs_vfid,
309 resp->pfdev_info.chip_num,
310 resp->pfdev_info.db_size,
311 resp->pfdev_info.indices_per_sb,
312 resp->pfdev_info.pf_cap,
313 resc->num_rxqs,
314 resc->num_txqs,
315 resc->num_sbs,
316 resc->num_mac_filters,
317 resc->num_vlan_filters,
318 resc->num_mc_filters,
319 resp->pfdev_info.fw_ver);
320
321 DP_CONT(BNX2X_MSG_IOV, "hw_qids- [ ");
322 for (i = 0; i < vf_rxq_count(vf); i++)
323 DP_CONT(BNX2X_MSG_IOV, "%d ", resc->hw_qid[i]);
324 DP_CONT(BNX2X_MSG_IOV, "], sb_info- [ ");
325 for (i = 0; i < vf_sb_count(vf); i++)
326 DP_CONT(BNX2X_MSG_IOV, "%d:%d ",
327 resc->hw_sbs[i].hw_sb_id,
328 resc->hw_sbs[i].sb_qid);
329 DP_CONT(BNX2X_MSG_IOV, "]\n");
330
331 /* send the response */
332 vf->op_rc = vfop_status;
333 bnx2x_vf_mbx_resp(bp, vf);
334}
335
336static void bnx2x_vf_mbx_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
337 struct bnx2x_vf_mbx *mbx)
338{
339 int rc;
340 struct vfpf_acquire_tlv *acquire = &mbx->msg->req.acquire;
341
342 /* log vfdef info */
343 DP(BNX2X_MSG_IOV,
344 "VF[%d] ACQUIRE: vfdev_info- vf_id %d, vf_os %d resources- n_rxq-%d, n_txq-%d, n_sbs-%d, n_macs-%d, n_vlans-%d, n_mcs-%d\n",
345 vf->abs_vfid, acquire->vfdev_info.vf_id, acquire->vfdev_info.vf_os,
346 acquire->resc_request.num_rxqs, acquire->resc_request.num_txqs,
347 acquire->resc_request.num_sbs, acquire->resc_request.num_mac_filters,
348 acquire->resc_request.num_vlan_filters,
349 acquire->resc_request.num_mc_filters);
350
351 /* acquire the resources */
352 rc = bnx2x_vf_acquire(bp, vf, &acquire->resc_request);
353
354 /* response */
355 bnx2x_vf_mbx_acquire_resp(bp, vf, mbx, rc);
356}
357
188/* dispatch request */ 358/* dispatch request */
189static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf, 359static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
190 struct bnx2x_vf_mbx *mbx) 360 struct bnx2x_vf_mbx *mbx)
@@ -193,8 +363,16 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
193 363
194 /* check if tlv type is known */ 364 /* check if tlv type is known */
195 if (bnx2x_tlv_supported(mbx->first_tlv.tl.type)) { 365 if (bnx2x_tlv_supported(mbx->first_tlv.tl.type)) {
366 /* Lock the per vf op mutex and note the locker's identity.
367 * The unlock will take place in mbx response.
368 */
369 bnx2x_lock_vf_pf_channel(bp, vf, mbx->first_tlv.tl.type);
370
196 /* switch on the opcode */ 371 /* switch on the opcode */
197 switch (mbx->first_tlv.tl.type) { 372 switch (mbx->first_tlv.tl.type) {
373 case CHANNEL_TLV_ACQUIRE:
374 bnx2x_vf_mbx_acquire(bp, vf, mbx);
375 break;
198 } 376 }
199 } else { 377 } else {
200 /* unknown TLV - this may belong to a VF driver from the future 378 /* unknown TLV - this may belong to a VF driver from the future
@@ -208,6 +386,23 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
208 for (i = 0; i < 20; i++) 386 for (i = 0; i < 20; i++)
209 DP_CONT(BNX2X_MSG_IOV, "%x ", 387 DP_CONT(BNX2X_MSG_IOV, "%x ",
210 mbx->msg->req.tlv_buf_size.tlv_buffer[i]); 388 mbx->msg->req.tlv_buf_size.tlv_buffer[i]);
389
390 /* test whether we can respond to the VF (do we have an address
391 * for it?)
392 */
393 if (vf->state == VF_ACQUIRED) {
394 /* mbx_resp uses the op_rc of the VF */
395 vf->op_rc = PFVF_STATUS_NOT_SUPPORTED;
396
397 /* notify the VF that we do not support this request */
398 bnx2x_vf_mbx_resp(bp, vf);
399 } else {
400 /* can't send a response since this VF is unknown to us
401 * just unlock the channel and be done with.
402 */
403 bnx2x_unlock_vf_pf_channel(bp, vf,
404 mbx->first_tlv.tl.type);
405 }
211 } 406 }
212} 407}
213 408