octeontx2-pf: Fix ndo_set_rx_mode
authorSunil Goutham <sgoutham@marvell.com>
Wed, 25 Mar 2020 11:41:17 +0000 (17:11 +0530)
committerDavid S. Miller <davem@davemloft.net>
Wed, 25 Mar 2020 19:20:00 +0000 (12:20 -0700)
Since set_rx_mode takes a mutex lock for sending mailbox
message to admin function to set the mode, moved logic
to a workqueue.

Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c

index eaff5f6..018c283 100644 (file)
@@ -243,6 +243,8 @@ struct otx2_nic {
        struct workqueue_struct *flr_wq;
        struct flr_work         *flr_wrk;
        struct refill_work      *refill_wrk;
+       struct workqueue_struct *otx2_wq;
+       struct work_struct      rx_mode_work;
 
        /* Ethtool stuff */
        u32                     msg_enable;
index 4618c90..411e5ea 100644 (file)
@@ -1679,6 +1679,14 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev)
 static void otx2_set_rx_mode(struct net_device *netdev)
 {
        struct otx2_nic *pf = netdev_priv(netdev);
+
+       queue_work(pf->otx2_wq, &pf->rx_mode_work);
+}
+
+static void otx2_do_set_rx_mode(struct work_struct *work)
+{
+       struct otx2_nic *pf = container_of(work, struct otx2_nic, rx_mode_work);
+       struct net_device *netdev = pf->netdev;
        struct nix_rx_mode *req;
 
        if (!(netdev->flags & IFF_UP))
@@ -1740,6 +1748,17 @@ static const struct net_device_ops otx2_netdev_ops = {
        .ndo_get_stats64        = otx2_get_stats64,
 };
 
+static int otx2_wq_init(struct otx2_nic *pf)
+{
+       pf->otx2_wq = create_singlethread_workqueue("otx2_wq");
+       if (!pf->otx2_wq)
+               return -ENOMEM;
+
+       INIT_WORK(&pf->rx_mode_work, otx2_do_set_rx_mode);
+       INIT_WORK(&pf->reset_task, otx2_reset_task);
+       return 0;
+}
+
 static int otx2_check_pf_usable(struct otx2_nic *nic)
 {
        u64 rev;
@@ -1924,14 +1943,16 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        netdev->min_mtu = OTX2_MIN_MTU;
        netdev->max_mtu = OTX2_MAX_MTU;
 
-       INIT_WORK(&pf->reset_task, otx2_reset_task);
-
        err = register_netdev(netdev);
        if (err) {
                dev_err(dev, "Failed to register netdevice\n");
                goto err_detach_rsrc;
        }
 
+       err = otx2_wq_init(pf);
+       if (err)
+               goto err_unreg_netdev;
+
        otx2_set_ethtool_ops(netdev);
 
        /* Enable link notifications */
@@ -1943,6 +1964,8 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        return 0;
 
+err_unreg_netdev:
+       unregister_netdev(netdev);
 err_detach_rsrc:
        otx2_detach_resources(&pf->mbox);
 err_disable_mbox_intr:
@@ -2089,6 +2112,8 @@ static void otx2_remove(struct pci_dev *pdev)
 
        unregister_netdev(netdev);
        otx2_sriov_disable(pf->pdev);
+       if (pf->otx2_wq)
+               destroy_workqueue(pf->otx2_wq);
 
        otx2_detach_resources(&pf->mbox);
        otx2_disable_mbox_intr(pf);