In some cases it could happen that nicvf_send_msg_to_pf() could be called
concurrently for the same NIC VF, and thus re-writing mailbox contents and
breaking messaging sequence with PF by re-writing NICVF data.

This commit is to implement mutex for NICVF to protect mailbox registers
and NICVF messaging control data from concurrent access.

Signed-off-by: Vadim Lomovtsev <vlomovt...@marvell.com>
---
 drivers/net/ethernet/cavium/thunder/nic.h        |  2 ++
 drivers/net/ethernet/cavium/thunder/nicvf_main.c | 13 ++++++++++---
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/cavium/thunder/nic.h 
b/drivers/net/ethernet/cavium/thunder/nic.h
index 227343625e83..86cda3f4b37b 100644
--- a/drivers/net/ethernet/cavium/thunder/nic.h
+++ b/drivers/net/ethernet/cavium/thunder/nic.h
@@ -329,6 +329,8 @@ struct nicvf {
        spinlock_t              rx_mode_wq_lock;
        /* workqueue for handling kernel ndo_set_rx_mode() calls */
        struct workqueue_struct *nicvf_rx_mode_wq;
+       /* mutex to protect VF's mailbox contents from concurrent access */
+       struct mutex            rx_mode_mtx;
 
        /* PTP timestamp */
        struct cavium_ptp       *ptp_clock;
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c 
b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index da5986ca7bee..2332e3e95e0e 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -124,6 +124,9 @@ int nicvf_send_msg_to_pf(struct nicvf *nic, union nic_mbx 
*mbx)
 {
        int timeout = NIC_MBOX_MSG_TIMEOUT;
        int sleep = 10;
+       int ret = 0;
+
+       mutex_lock(&nic->rx_mode_mtx);
 
        nic->pf_acked = false;
        nic->pf_nacked = false;
@@ -136,7 +139,8 @@ int nicvf_send_msg_to_pf(struct nicvf *nic, union nic_mbx 
*mbx)
                        netdev_err(nic->netdev,
                                   "PF NACK to mbox msg 0x%02x from VF%d\n",
                                   (mbx->msg.msg & 0xFF), nic->vf_id);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       break;
                }
                msleep(sleep);
                if (nic->pf_acked)
@@ -146,10 +150,12 @@ int nicvf_send_msg_to_pf(struct nicvf *nic, union nic_mbx 
*mbx)
                        netdev_err(nic->netdev,
                                   "PF didn't ACK to mbox msg 0x%02x from 
VF%d\n",
                                   (mbx->msg.msg & 0xFF), nic->vf_id);
-                       return -EBUSY;
+                       ret = -EBUSY;
+                       break;
                }
        }
-       return 0;
+       mutex_unlock(&nic->rx_mode_mtx);
+       return ret;
 }
 
 /* Checks if VF is able to comminicate with PF
@@ -2208,6 +2214,7 @@ static int nicvf_probe(struct pci_dev *pdev, const struct 
pci_device_id *ent)
                                                        nic->vf_id);
        INIT_WORK(&nic->rx_mode_work.work, nicvf_set_rx_mode_task);
        spin_lock_init(&nic->rx_mode_wq_lock);
+       mutex_init(&nic->rx_mode_mtx);
 
        err = register_netdev(netdev);
        if (err) {
-- 
2.17.2

Reply via email to