Skip to content

Commit 1d6f3cd

Browse files
Dmitry Kravkovdavem330
authored andcommitted
bnx2x: Prevent VF race
The mail box containing the Vf-Pf messages is susceptible to a race - it's possible for 2 flows to try and write commands, causing one to override the other's message. Use a mutex to synchronize the access, preventing said race. Signed-off-by: Dmitry Kravkov <[email protected]> Signed-off-by: Yuval Mintz <[email protected]> Signed-off-by: Ariel Elior <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2177653 commit 1d6f3cd

File tree

5 files changed

+82
-34
lines changed

5 files changed

+82
-34
lines changed

drivers/net/ethernet/broadcom/bnx2x/bnx2x.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,6 +1277,8 @@ struct bnx2x {
12771277
#define BP_FW_MB_IDX(bp) BP_FW_MB_IDX_VN(bp, BP_VN(bp))
12781278

12791279
#ifdef CONFIG_BNX2X_SRIOV
1280+
/* protects vf2pf mailbox from simultaneous access */
1281+
struct mutex vf2pf_mutex;
12801282
/* vf pf channel mailbox contains request and response buffers */
12811283
struct bnx2x_vf_mbx_msg *vf2pf_mbox;
12821284
dma_addr_t vf2pf_mbox_mapping;

drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12521,7 +12521,8 @@ static int bnx2x_init_one(struct pci_dev *pdev,
1252112521
* l2 connections.
1252212522
*/
1252312523
if (IS_VF(bp)) {
12524-
bnx2x_vf_map_doorbells(bp);
12524+
bp->doorbells = bnx2x_vf_doorbells(bp);
12525+
mutex_init(&bp->vf2pf_mutex);
1252512526
rc = bnx2x_vf_pci_alloc(bp);
1252612527
if (rc)
1252712528
goto init_one_exit;

drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2388,8 +2388,8 @@ int bnx2x_iov_eq_sp_event(struct bnx2x *bp, union event_ring_elem *elem)
23882388
goto get_vf;
23892389
case EVENT_RING_OPCODE_MALICIOUS_VF:
23902390
abs_vfid = elem->message.data.malicious_vf_event.vf_id;
2391-
DP(BNX2X_MSG_IOV, "Got VF MALICIOUS notification abs_vfid=%d\n",
2392-
abs_vfid);
2391+
DP(BNX2X_MSG_IOV, "Got VF MALICIOUS notification abs_vfid=%d err_id=0x%x\n",
2392+
abs_vfid, elem->message.data.malicious_vf_event.err_id);
23932393
goto get_vf;
23942394
default:
23952395
return 1;
@@ -2446,8 +2446,8 @@ int bnx2x_iov_eq_sp_event(struct bnx2x *bp, union event_ring_elem *elem)
24462446
/* Do nothing for now */
24472447
break;
24482448
case EVENT_RING_OPCODE_MALICIOUS_VF:
2449-
DP(BNX2X_MSG_IOV, "got VF [%d] MALICIOUS notification\n",
2450-
vf->abs_vfid);
2449+
DP(BNX2X_MSG_IOV, "Got VF MALICIOUS notification abs_vfid=%d error id %x\n",
2450+
abs_vfid, elem->message.data.malicious_vf_event.err_id);
24512451
/* Do nothing for now */
24522452
break;
24532453
}
@@ -3417,10 +3417,10 @@ enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp)
34173417
return PFVF_BULLETIN_UPDATED;
34183418
}
34193419

3420-
void bnx2x_vf_map_doorbells(struct bnx2x *bp)
3420+
void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp)
34213421
{
34223422
/* vf doorbells are embedded within the regview */
3423-
bp->doorbells = bp->regview + PXP_VF_ADDR_DB_START;
3423+
return bp->regview + PXP_VF_ADDR_DB_START;
34243424
}
34253425

34263426
int bnx2x_vf_pci_alloc(struct bnx2x *bp)

drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,7 @@ void bnx2x_add_tlv(struct bnx2x *bp, void *tlvs_list, u16 offset, u16 type,
713713
u16 length);
714714
void bnx2x_vfpf_prep(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv,
715715
u16 type, u16 length);
716+
void bnx2x_vfpf_finalize(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv);
716717
void bnx2x_dp_tlv_list(struct bnx2x *bp, void *tlvs_list);
717718

718719
bool bnx2x_tlv_supported(u16 tlvtype);
@@ -751,7 +752,7 @@ static inline int bnx2x_vf_ustorm_prods_offset(struct bnx2x *bp,
751752
}
752753

753754
enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp);
754-
void bnx2x_vf_map_doorbells(struct bnx2x *bp);
755+
void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp);
755756
int bnx2x_vf_pci_alloc(struct bnx2x *bp);
756757
int bnx2x_enable_sriov(struct bnx2x *bp);
757758
void bnx2x_disable_sriov(struct bnx2x *bp);
@@ -808,7 +809,11 @@ static inline enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp
808809
return PFVF_BULLETIN_UNCHANGED;
809810
}
810811

811-
static inline int bnx2x_vf_map_doorbells(struct bnx2x *bp) {return 0; }
812+
static inline void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp)
813+
{
814+
return NULL;
815+
}
816+
812817
static inline int bnx2x_vf_pci_alloc(struct bnx2x *bp) {return 0; }
813818
static inline void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp) {}
814819
static inline int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs) {return 0; }

drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c

Lines changed: 65 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ void bnx2x_add_tlv(struct bnx2x *bp, void *tlvs_list, u16 offset, u16 type,
3636
void bnx2x_vfpf_prep(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv,
3737
u16 type, u16 length)
3838
{
39+
mutex_lock(&bp->vf2pf_mutex);
40+
3941
DP(BNX2X_MSG_IOV, "preparing to send %d tlv over vf pf channel\n",
4042
type);
4143

@@ -49,6 +51,15 @@ void bnx2x_vfpf_prep(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv,
4951
first_tlv->resp_msg_offset = sizeof(bp->vf2pf_mbox->req);
5052
}
5153

54+
/* releases the mailbox */
55+
void bnx2x_vfpf_finalize(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv)
56+
{
57+
DP(BNX2X_MSG_IOV, "done sending [%d] tlv over vf pf channel\n",
58+
first_tlv->tl.type);
59+
60+
mutex_unlock(&bp->vf2pf_mutex);
61+
}
62+
5263
/* list the types and lengths of the tlvs on the buffer */
5364
void bnx2x_dp_tlv_list(struct bnx2x *bp, void *tlvs_list)
5465
{
@@ -181,8 +192,10 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
181192
/* clear mailbox and prep first tlv */
182193
bnx2x_vfpf_prep(bp, &req->first_tlv, CHANNEL_TLV_ACQUIRE, sizeof(*req));
183194

184-
if (bnx2x_get_vf_id(bp, &vf_id))
185-
return -EAGAIN;
195+
if (bnx2x_get_vf_id(bp, &vf_id)) {
196+
rc = -EAGAIN;
197+
goto out;
198+
}
186199

187200
req->vfdev_info.vf_id = vf_id;
188201
req->vfdev_info.vf_os = 0;
@@ -213,7 +226,7 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
213226

214227
/* PF timeout */
215228
if (rc)
216-
return rc;
229+
goto out;
217230

218231
/* copy acquire response from buffer to bp */
219232
memcpy(&bp->acquire_resp, resp, sizeof(bp->acquire_resp));
@@ -253,7 +266,8 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
253266
/* PF reports error */
254267
BNX2X_ERR("Failed to get the requested amount of resources: %d. Breaking...\n",
255268
bp->acquire_resp.hdr.status);
256-
return -EAGAIN;
269+
rc = -EAGAIN;
270+
goto out;
257271
}
258272
}
259273

@@ -279,20 +293,24 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
279293
bp->acquire_resp.resc.current_mac_addr,
280294
ETH_ALEN);
281295

282-
return 0;
296+
out:
297+
bnx2x_vfpf_finalize(bp, &req->first_tlv);
298+
return rc;
283299
}
284300

285301
int bnx2x_vfpf_release(struct bnx2x *bp)
286302
{
287303
struct vfpf_release_tlv *req = &bp->vf2pf_mbox->req.release;
288304
struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp;
289-
u32 rc = 0, vf_id;
305+
u32 rc, vf_id;
290306

291307
/* clear mailbox and prep first tlv */
292308
bnx2x_vfpf_prep(bp, &req->first_tlv, CHANNEL_TLV_RELEASE, sizeof(*req));
293309

294-
if (bnx2x_get_vf_id(bp, &vf_id))
295-
return -EAGAIN;
310+
if (bnx2x_get_vf_id(bp, &vf_id)) {
311+
rc = -EAGAIN;
312+
goto out;
313+
}
296314

297315
req->vf_id = vf_id;
298316

@@ -308,18 +326,22 @@ int bnx2x_vfpf_release(struct bnx2x *bp)
308326

309327
if (rc)
310328
/* PF timeout */
311-
return rc;
329+
goto out;
330+
312331
if (resp->hdr.status == PFVF_STATUS_SUCCESS) {
313332
/* PF released us */
314333
DP(BNX2X_MSG_SP, "vf released\n");
315334
} else {
316335
/* PF reports error */
317336
BNX2X_ERR("PF failed our release request - are we out of sync? response status: %d\n",
318337
resp->hdr.status);
319-
return -EAGAIN;
338+
rc = -EAGAIN;
339+
goto out;
320340
}
341+
out:
342+
bnx2x_vfpf_finalize(bp, &req->first_tlv);
321343

322-
return 0;
344+
return rc;
323345
}
324346

325347
/* Tell PF about SB addresses */
@@ -350,16 +372,20 @@ int bnx2x_vfpf_init(struct bnx2x *bp)
350372

351373
rc = bnx2x_send_msg2pf(bp, &resp->hdr.status, bp->vf2pf_mbox_mapping);
352374
if (rc)
353-
return rc;
375+
goto out;
354376

355377
if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
356378
BNX2X_ERR("INIT VF failed: %d. Breaking...\n",
357379
resp->hdr.status);
358-
return -EAGAIN;
380+
rc = -EAGAIN;
381+
goto out;
359382
}
360383

361384
DP(BNX2X_MSG_SP, "INIT VF Succeeded\n");
362-
return 0;
385+
out:
386+
bnx2x_vfpf_finalize(bp, &req->first_tlv);
387+
388+
return rc;
363389
}
364390

365391
/* CLOSE VF - opposite to INIT_VF */
@@ -401,6 +427,8 @@ void bnx2x_vfpf_close_vf(struct bnx2x *bp)
401427
BNX2X_ERR("Sending CLOSE failed: pf response was %d\n",
402428
resp->hdr.status);
403429

430+
bnx2x_vfpf_finalize(bp, &req->first_tlv);
431+
404432
free_irq:
405433
/* Disable HW interrupts, NAPI */
406434
bnx2x_netif_stop(bp, 0);
@@ -485,8 +513,11 @@ int bnx2x_vfpf_setup_q(struct bnx2x *bp, int fp_idx)
485513
if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
486514
BNX2X_ERR("Status of SETUP_Q for queue[%d] is %d\n",
487515
fp_idx, resp->hdr.status);
488-
return -EINVAL;
516+
rc = -EINVAL;
489517
}
518+
519+
bnx2x_vfpf_finalize(bp, &req->first_tlv);
520+
490521
return rc;
491522
}
492523

@@ -514,25 +545,27 @@ int bnx2x_vfpf_teardown_queue(struct bnx2x *bp, int qidx)
514545
if (rc) {
515546
BNX2X_ERR("Sending TEARDOWN for queue %d failed: %d\n", qidx,
516547
rc);
517-
return rc;
548+
goto out;
518549
}
519550

520551
/* PF failed the transaction */
521552
if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
522553
BNX2X_ERR("TEARDOWN for queue %d failed: %d\n", qidx,
523554
resp->hdr.status);
524-
return -EINVAL;
555+
rc = -EINVAL;
525556
}
526557

527-
return 0;
558+
out:
559+
bnx2x_vfpf_finalize(bp, &req->first_tlv);
560+
return rc;
528561
}
529562

530563
/* request pf to add a mac for the vf */
531564
int bnx2x_vfpf_set_mac(struct bnx2x *bp)
532565
{
533566
struct vfpf_set_q_filters_tlv *req = &bp->vf2pf_mbox->req.set_q_filters;
534567
struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp;
535-
int rc;
568+
int rc = 0;
536569

537570
/* clear mailbox and prep first tlv */
538571
bnx2x_vfpf_prep(bp, &req->first_tlv, CHANNEL_TLV_SET_Q_FILTERS,
@@ -561,7 +594,7 @@ int bnx2x_vfpf_set_mac(struct bnx2x *bp)
561594
rc = bnx2x_send_msg2pf(bp, &resp->hdr.status, bp->vf2pf_mbox_mapping);
562595
if (rc) {
563596
BNX2X_ERR("failed to send message to pf. rc was %d\n", rc);
564-
return rc;
597+
goto out;
565598
}
566599

567600
/* failure may mean PF was configured with a new mac for us */
@@ -586,8 +619,10 @@ int bnx2x_vfpf_set_mac(struct bnx2x *bp)
586619

587620
if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
588621
BNX2X_ERR("vfpf SET MAC failed: %d\n", resp->hdr.status);
589-
return -EINVAL;
622+
rc = -EINVAL;
590623
}
624+
out:
625+
bnx2x_vfpf_finalize(bp, &req->first_tlv);
591626

592627
return 0;
593628
}
@@ -642,14 +677,16 @@ int bnx2x_vfpf_set_mcast(struct net_device *dev)
642677
rc = bnx2x_send_msg2pf(bp, &resp->hdr.status, bp->vf2pf_mbox_mapping);
643678
if (rc) {
644679
BNX2X_ERR("Sending a message failed: %d\n", rc);
645-
return rc;
680+
goto out;
646681
}
647682

648683
if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
649684
BNX2X_ERR("Set Rx mode/multicast failed: %d\n",
650685
resp->hdr.status);
651-
return -EINVAL;
686+
rc = -EINVAL;
652687
}
688+
out:
689+
bnx2x_vfpf_finalize(bp, &req->first_tlv);
653690

654691
return 0;
655692
}
@@ -688,7 +725,8 @@ int bnx2x_vfpf_storm_rx_mode(struct bnx2x *bp)
688725
break;
689726
default:
690727
BNX2X_ERR("BAD rx mode (%d)\n", mode);
691-
return -EINVAL;
728+
rc = -EINVAL;
729+
goto out;
692730
}
693731

694732
req->flags |= VFPF_SET_Q_FILTERS_RX_MASK_CHANGED;
@@ -707,8 +745,10 @@ int bnx2x_vfpf_storm_rx_mode(struct bnx2x *bp)
707745

708746
if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
709747
BNX2X_ERR("Set Rx mode failed: %d\n", resp->hdr.status);
710-
return -EINVAL;
748+
rc = -EINVAL;
711749
}
750+
out:
751+
bnx2x_vfpf_finalize(bp, &req->first_tlv);
712752

713753
return rc;
714754
}

0 commit comments

Comments
 (0)