aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAriel Elior <ariele@broadcom.com>2013-01-01 00:22:35 -0500
committerDavid S. Miller <davem@davemloft.net>2013-01-02 04:45:06 -0500
commitb93288d5e7efc57628c59fe3f1844fb87982b409 (patch)
treebf97f3de00393a948d3d4a27f0c9ce267b2daa7b
parent8ca5e17e58c953b9a9dbd4974c554b25c6d70b1a (diff)
bnx2x: Support of PF driver of a VF init request
The VF driver will send an 'init' request as part of its nic load flow. This message is used by the VF to publish the GPA's of its status blocks, slow path ring and statistics buffer. The PF driver notes all this down in the VF database, and also uses this message to transfer the VF to VF_INIT state internally. 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.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h4
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c159
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h8
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c18
6 files changed, 190 insertions, 3 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 5219373ecaf1..d096e3e85287 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1852,6 +1852,8 @@ int bnx2x_del_all_macs(struct bnx2x *bp,
1852 1852
1853/* Init Function API */ 1853/* Init Function API */
1854void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p); 1854void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p);
1855void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid,
1856 u8 vf_valid, int fw_sb_id, int igu_sb_id);
1855u32 bnx2x_get_pretend_reg(struct bnx2x *bp); 1857u32 bnx2x_get_pretend_reg(struct bnx2x *bp);
1856int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port); 1858int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port);
1857int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port); 1859int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index e6738f6984ad..0fae563e9633 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -5420,7 +5420,7 @@ static void bnx2x_map_sb_state_machines(struct hc_index_data *index_data)
5420 SM_TX_ID << HC_INDEX_DATA_SM_ID_SHIFT; 5420 SM_TX_ID << HC_INDEX_DATA_SM_ID_SHIFT;
5421} 5421}
5422 5422
5423static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid, 5423void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid,
5424 u8 vf_valid, int fw_sb_id, int igu_sb_id) 5424 u8 vf_valid, int fw_sb_id, int igu_sb_id)
5425{ 5425{
5426 int igu_seg_id; 5426 int igu_seg_id;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
index cefe4480e587..1008d3f9fd64 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
@@ -3726,6 +3726,10 @@
3726#define PXP_REG_HST_DISCARD_INTERNAL_WRITES_STATUS 0x10309c 3726#define PXP_REG_HST_DISCARD_INTERNAL_WRITES_STATUS 0x10309c
3727/* [WB 160] Used for initialization of the inbound interrupts memory */ 3727/* [WB 160] Used for initialization of the inbound interrupts memory */
3728#define PXP_REG_HST_INBOUND_INT 0x103800 3728#define PXP_REG_HST_INBOUND_INT 0x103800
3729/* [RW 7] Indirect access to the permission table. The fields are : {Valid;
3730 * VFID[5:0]}
3731 */
3732#define PXP_REG_HST_ZONE_PERMISSION_TABLE 0x103400
3729/* [RW 32] Interrupt mask register #0 read/write */ 3733/* [RW 32] Interrupt mask register #0 read/write */
3730#define PXP_REG_PXP_INT_MASK_0 0x103074 3734#define PXP_REG_PXP_INT_MASK_0 0x103074
3731#define PXP_REG_PXP_INT_MASK_1 0x103084 3735#define PXP_REG_PXP_INT_MASK_1 0x103084
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index de42f665c1fa..14e49bc455df 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -66,6 +66,41 @@ struct bnx2x_virtf *bnx2x_vf_by_abs_fid(struct bnx2x *bp, u16 abs_vfid)
66 return (idx < BNX2X_NR_VIRTFN(bp)) ? BP_VF(bp, idx) : NULL; 66 return (idx < BNX2X_NR_VIRTFN(bp)) ? BP_VF(bp, idx) : NULL;
67} 67}
68 68
69static void bnx2x_vf_igu_ack_sb(struct bnx2x *bp, struct bnx2x_virtf *vf,
70 u8 igu_sb_id, u8 segment, u16 index, u8 op,
71 u8 update)
72{
73 /* acking a VF sb through the PF - use the GRC */
74 u32 ctl;
75 u32 igu_addr_data = IGU_REG_COMMAND_REG_32LSB_DATA;
76 u32 igu_addr_ctl = IGU_REG_COMMAND_REG_CTRL;
77 u32 func_encode = vf->abs_vfid;
78 u32 addr_encode = IGU_CMD_E2_PROD_UPD_BASE + igu_sb_id;
79 struct igu_regular cmd_data = {0};
80
81 cmd_data.sb_id_and_flags =
82 ((index << IGU_REGULAR_SB_INDEX_SHIFT) |
83 (segment << IGU_REGULAR_SEGMENT_ACCESS_SHIFT) |
84 (update << IGU_REGULAR_BUPDATE_SHIFT) |
85 (op << IGU_REGULAR_ENABLE_INT_SHIFT));
86
87 ctl = addr_encode << IGU_CTRL_REG_ADDRESS_SHIFT |
88 func_encode << IGU_CTRL_REG_FID_SHIFT |
89 IGU_CTRL_CMD_TYPE_WR << IGU_CTRL_REG_TYPE_SHIFT;
90
91 DP(NETIF_MSG_HW, "write 0x%08x to IGU(via GRC) addr 0x%x\n",
92 cmd_data.sb_id_and_flags, igu_addr_data);
93 REG_WR(bp, igu_addr_data, cmd_data.sb_id_and_flags);
94 mmiowb();
95 barrier();
96
97 DP(NETIF_MSG_HW, "write 0x%08x to IGU(via GRC) addr 0x%x\n",
98 ctl, igu_addr_ctl);
99 REG_WR(bp, igu_addr_ctl, ctl);
100 mmiowb();
101 barrier();
102}
103
69static int bnx2x_ari_enabled(struct pci_dev *dev) 104static int bnx2x_ari_enabled(struct pci_dev *dev)
70{ 105{
71 return dev->bus->self && dev->bus->self->ari_enabled; 106 return dev->bus->self && dev->bus->self->ari_enabled;
@@ -364,6 +399,52 @@ static void bnx2x_vf_pglue_clear_err(struct bnx2x *bp, u8 abs_vfid)
364 REG_WR(bp, was_err_reg, 1 << (abs_vfid & 0x1f)); 399 REG_WR(bp, was_err_reg, 1 << (abs_vfid & 0x1f));
365} 400}
366 401
402static void bnx2x_vf_igu_reset(struct bnx2x *bp, struct bnx2x_virtf *vf)
403{
404 int i;
405 u32 val;
406
407 /* Set VF masks and configuration - pretend */
408 bnx2x_pretend_func(bp, HW_VF_HANDLE(bp, vf->abs_vfid));
409
410 REG_WR(bp, IGU_REG_SB_INT_BEFORE_MASK_LSB, 0);
411 REG_WR(bp, IGU_REG_SB_INT_BEFORE_MASK_MSB, 0);
412 REG_WR(bp, IGU_REG_SB_MASK_LSB, 0);
413 REG_WR(bp, IGU_REG_SB_MASK_MSB, 0);
414 REG_WR(bp, IGU_REG_PBA_STATUS_LSB, 0);
415 REG_WR(bp, IGU_REG_PBA_STATUS_MSB, 0);
416
417 val = REG_RD(bp, IGU_REG_VF_CONFIGURATION);
418 val |= (IGU_VF_CONF_FUNC_EN | IGU_VF_CONF_MSI_MSIX_EN);
419 if (vf->cfg_flags & VF_CFG_INT_SIMD)
420 val |= IGU_VF_CONF_SINGLE_ISR_EN;
421 val &= ~IGU_VF_CONF_PARENT_MASK;
422 val |= BP_FUNC(bp) << IGU_VF_CONF_PARENT_SHIFT; /* parent PF */
423 REG_WR(bp, IGU_REG_VF_CONFIGURATION, val);
424
425 DP(BNX2X_MSG_IOV,
426 "value in IGU_REG_VF_CONFIGURATION of vf %d after write %x\n",
427 vf->abs_vfid, REG_RD(bp, IGU_REG_VF_CONFIGURATION));
428
429 bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
430
431 /* iterate over all queues, clear sb consumer */
432 for (i = 0; i < vf_sb_count(vf); i++) {
433 u8 igu_sb_id = vf_igu_sb(vf, i);
434
435 /* zero prod memory */
436 REG_WR(bp, IGU_REG_PROD_CONS_MEMORY + igu_sb_id * 4, 0);
437
438 /* clear sb state machine */
439 bnx2x_igu_clear_sb_gen(bp, vf->abs_vfid, igu_sb_id,
440 false /* VF */);
441
442 /* disable + update */
443 bnx2x_vf_igu_ack_sb(bp, vf, igu_sb_id, USTORM_ID, 0,
444 IGU_INT_DISABLE, 1);
445 }
446}
447
367void bnx2x_vf_enable_access(struct bnx2x *bp, u8 abs_vfid) 448void bnx2x_vf_enable_access(struct bnx2x *bp, u8 abs_vfid)
368{ 449{
369 /* set the VF-PF association in the FW */ 450 /* set the VF-PF association in the FW */
@@ -381,6 +462,17 @@ void bnx2x_vf_enable_access(struct bnx2x *bp, u8 abs_vfid)
381 bnx2x_pretend_func(bp, BP_ABS_FUNC(bp)); 462 bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
382} 463}
383 464
465static void bnx2x_vf_enable_traffic(struct bnx2x *bp, struct bnx2x_virtf *vf)
466{
467 /* Reset vf in IGU interrupts are still disabled */
468 bnx2x_vf_igu_reset(bp, vf);
469
470 /* pretend to enable the vf with the PBF */
471 bnx2x_pretend_func(bp, HW_VF_HANDLE(bp, vf->abs_vfid));
472 REG_WR(bp, PBF_REG_DISABLE_VF, 0);
473 bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
474}
475
384static u8 bnx2x_vf_is_pcie_pending(struct bnx2x *bp, u8 abs_vfid) 476static u8 bnx2x_vf_is_pcie_pending(struct bnx2x *bp, u8 abs_vfid)
385{ 477{
386 struct pci_dev *dev; 478 struct pci_dev *dev;
@@ -997,6 +1089,14 @@ void bnx2x_iov_sp_task(struct bnx2x *bp)
997 } 1089 }
998 } 1090 }
999} 1091}
1092static void bnx2x_vf_qtbl_set_q(struct bnx2x *bp, u8 abs_vfid, u8 qid,
1093 u8 enable)
1094{
1095 u32 reg = PXP_REG_HST_ZONE_PERMISSION_TABLE + qid * 4;
1096 u32 val = enable ? (abs_vfid | (1 << 6)) : 0;
1097
1098 REG_WR(bp, reg, val);
1099}
1000 1100
1001u8 bnx2x_vf_max_queue_cnt(struct bnx2x *bp, struct bnx2x_virtf *vf) 1101u8 bnx2x_vf_max_queue_cnt(struct bnx2x *bp, struct bnx2x_virtf *vf)
1002{ 1102{
@@ -1108,6 +1208,65 @@ int bnx2x_vf_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
1108 return 0; 1208 return 0;
1109} 1209}
1110 1210
1211int bnx2x_vf_init(struct bnx2x *bp, struct bnx2x_virtf *vf, dma_addr_t *sb_map)
1212{
1213 struct bnx2x_func_init_params func_init = {0};
1214 u16 flags = 0;
1215 int i;
1216
1217 /* the sb resources are initialized at this point, do the
1218 * FW/HW initializations
1219 */
1220 for_each_vf_sb(vf, i)
1221 bnx2x_init_sb(bp, (dma_addr_t)sb_map[i], vf->abs_vfid, true,
1222 vf_igu_sb(vf, i), vf_igu_sb(vf, i));
1223
1224 /* Sanity checks */
1225 if (vf->state != VF_ACQUIRED) {
1226 DP(BNX2X_MSG_IOV, "VF[%d] is not in VF_ACQUIRED, but %d\n",
1227 vf->abs_vfid, vf->state);
1228 return -EINVAL;
1229 }
1230 /* FLR cleanup epilogue */
1231 if (bnx2x_vf_flr_clnup_epilog(bp, vf->abs_vfid))
1232 return -EBUSY;
1233
1234 /* reset IGU VF statistics: MSIX */
1235 REG_WR(bp, IGU_REG_STATISTIC_NUM_MESSAGE_SENT + vf->abs_vfid * 4 , 0);
1236
1237 /* vf init */
1238 if (vf->cfg_flags & VF_CFG_STATS)
1239 flags |= (FUNC_FLG_STATS | FUNC_FLG_SPQ);
1240
1241 if (vf->cfg_flags & VF_CFG_TPA)
1242 flags |= FUNC_FLG_TPA;
1243
1244 if (is_vf_multi(vf))
1245 flags |= FUNC_FLG_RSS;
1246
1247 /* function setup */
1248 func_init.func_flgs = flags;
1249 func_init.pf_id = BP_FUNC(bp);
1250 func_init.func_id = FW_VF_HANDLE(vf->abs_vfid);
1251 func_init.fw_stat_map = vf->fw_stat_map;
1252 func_init.spq_map = vf->spq_map;
1253 func_init.spq_prod = 0;
1254 bnx2x_func_init(bp, &func_init);
1255
1256 /* Enable the vf */
1257 bnx2x_vf_enable_access(bp, vf->abs_vfid);
1258 bnx2x_vf_enable_traffic(bp, vf);
1259
1260 /* queue protection table */
1261 for_each_vfq(vf, i)
1262 bnx2x_vf_qtbl_set_q(bp, vf->abs_vfid,
1263 vfq_qzone_id(vf, vfq_get(vf, i)), true);
1264
1265 vf->state = VF_ENABLED;
1266
1267 return 0;
1268}
1269
1111void bnx2x_lock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf, 1270void bnx2x_lock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf,
1112 enum channel_tlvs tlv) 1271 enum channel_tlvs tlv)
1113{ 1272{
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
index 5248ebe207f8..6dac57e8ba9e 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
@@ -267,6 +267,8 @@ struct bnx2x_virtf {
267#define for_each_vf_sb(vf, var) \ 267#define for_each_vf_sb(vf, var) \
268 for ((var) = 0; (var) < vf_sb_count(vf); (var)++) 268 for ((var) = 0; (var) < vf_sb_count(vf); (var)++)
269 269
270#define is_vf_multi(vf) (vf_rxq_count(vf) > 1)
271
270#define HW_VF_HANDLE(bp, abs_vfid) \ 272#define HW_VF_HANDLE(bp, abs_vfid) \
271 (u16)(BP_ABS_FUNC((bp)) | (1<<3) | ((u16)(abs_vfid) << 4)) 273 (u16)(BP_ABS_FUNC((bp)) | (1<<3) | ((u16)(abs_vfid) << 4))
272 274
@@ -427,8 +429,10 @@ void bnx2x_vf_mbx(struct bnx2x *bp, struct vf_pf_event_data *vfpf_event);
427void bnx2x_vf_enable_mbx(struct bnx2x *bp, u8 abs_vfid); 429void bnx2x_vf_enable_mbx(struct bnx2x *bp, u8 abs_vfid);
428/* acquire */ 430/* acquire */
429int bnx2x_vf_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf, 431int bnx2x_vf_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
430 struct vf_pf_resc_request *resc); 432 struct vf_pf_resc_request *resc);
431 433/* init */
434int bnx2x_vf_init(struct bnx2x *bp, struct bnx2x_virtf *vf,
435 dma_addr_t *sb_map);
432static inline struct bnx2x_vfop *bnx2x_vfop_cur(struct bnx2x *bp, 436static inline struct bnx2x_vfop *bnx2x_vfop_cur(struct bnx2x *bp,
433 struct bnx2x_virtf *vf) 437 struct bnx2x_virtf *vf)
434{ 438{
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
index 3b6b577a28ce..7aa0e4f5346a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
@@ -19,6 +19,7 @@
19 19
20#include "bnx2x.h" 20#include "bnx2x.h"
21#include "bnx2x_sriov.h" 21#include "bnx2x_sriov.h"
22#include <linux/crc32.h>
22 23
23/* place a given tlv on the tlv buffer at a given offset */ 24/* place a given tlv on the tlv buffer at a given offset */
24void bnx2x_add_tlv(struct bnx2x *bp, void *tlvs_list, u16 offset, u16 type, 25void bnx2x_add_tlv(struct bnx2x *bp, void *tlvs_list, u16 offset, u16 type,
@@ -355,6 +356,20 @@ static void bnx2x_vf_mbx_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
355 bnx2x_vf_mbx_acquire_resp(bp, vf, mbx, rc); 356 bnx2x_vf_mbx_acquire_resp(bp, vf, mbx, rc);
356} 357}
357 358
359static void bnx2x_vf_mbx_init_vf(struct bnx2x *bp, struct bnx2x_virtf *vf,
360 struct bnx2x_vf_mbx *mbx)
361{
362 struct vfpf_init_tlv *init = &mbx->msg->req.init;
363
364 /* record ghost addresses from vf message */
365 vf->spq_map = init->spq_addr;
366 vf->fw_stat_map = init->stats_addr;
367 vf->op_rc = bnx2x_vf_init(bp, vf, (dma_addr_t *)init->sb_addr);
368
369 /* response */
370 bnx2x_vf_mbx_resp(bp, vf);
371}
372
358/* dispatch request */ 373/* dispatch request */
359static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf, 374static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
360 struct bnx2x_vf_mbx *mbx) 375 struct bnx2x_vf_mbx *mbx)
@@ -373,6 +388,9 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
373 case CHANNEL_TLV_ACQUIRE: 388 case CHANNEL_TLV_ACQUIRE:
374 bnx2x_vf_mbx_acquire(bp, vf, mbx); 389 bnx2x_vf_mbx_acquire(bp, vf, mbx);
375 break; 390 break;
391 case CHANNEL_TLV_INIT:
392 bnx2x_vf_mbx_init_vf(bp, vf, mbx);
393 break;
376 } 394 }
377 } else { 395 } else {
378 /* unknown TLV - this may belong to a VF driver from the future 396 /* unknown TLV - this may belong to a VF driver from the future