This pair of function is implemented on top of spin_lock_bh() that is
going to handle a softirq mask in order to apply finegrained vector
disablement. The lock function is going to return the previous vectors
enabled mask prior to the last call to local_bh_disable(), following a
similar model to that of local_irq_save/restore. Subsequent calls to
local_bh_disable() and friends can then stack up:

        bh = local_bh_disable(vec_mask);
                bh1 = local_bh_disable(vec_mask1);
                        bh2 = spin_lock_bh(vec_mask2);
                                netif_tx_lock_bh(vec_mask3) {
                                        bh3 = spin_lock_bh(vec_mask3)
                                        return bh3;
                                }
                                ...
                                netif_tx_unlock_bh(bh3, ...) {
                                        spin_unlock_bh(bh3, ...);
                                }
                        spin_unlock_bh(bh2, ...);
                local_bh_enable(bh1);
        local_bh_enable(bh);

To prepare for that, make netif_tx_lock_bh() able to return a saved vector
enabled mask and pass it back to netif_tx_unlock_bh(). We'll plug it
to spin_[un]lock_bh() in a subsequent patch.

Signed-off-by: Frederic Weisbecker <frede...@kernel.org>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Sebastian Andrzej Siewior <bige...@linutronix.de>
Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Linus Torvalds <torva...@linux-foundation.org>
Cc: David S. Miller <da...@davemloft.net>
Cc: Mauro Carvalho Chehab <mche...@s-opensource.com>
Cc: Paul E. McKenney <paul...@linux.vnet.ibm.com>
---
 drivers/infiniband/ulp/ipoib/ipoib_cm.c            | 42 ++++++++++++----------
 drivers/infiniband/ulp/ipoib/ipoib_ib.c            |  5 +--
 drivers/infiniband/ulp/ipoib/ipoib_main.c          |  9 ++---
 drivers/infiniband/ulp/ipoib/ipoib_multicast.c     | 19 +++++-----
 drivers/net/ethernet/aurora/nb8800.c               |  5 +--
 drivers/net/ethernet/chelsio/cxgb4/sge.c           |  5 +--
 drivers/net/ethernet/freescale/fec_main.c          | 34 ++++++++++--------
 drivers/net/ethernet/ibm/emac/core.c               | 15 ++++----
 drivers/net/ethernet/marvell/mv643xx_eth.c         |  5 +--
 drivers/net/ethernet/marvell/skge.c                |  5 +--
 drivers/net/ethernet/mellanox/mlx4/en_netdev.c     |  5 +--
 drivers/net/ethernet/mellanox/mlx5/core/en_main.c  |  5 +--
 drivers/net/ethernet/nvidia/forcedeth.c            | 40 ++++++++++++---------
 drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c |  7 ++--
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c     |  7 ++--
 drivers/net/ethernet/qualcomm/qca_spi.c            | 10 +++---
 drivers/net/ethernet/sfc/falcon/selftest.c         | 10 +++---
 drivers/net/ethernet/sfc/selftest.c                | 10 +++---
 drivers/net/hamradio/6pack.c                       | 10 +++---
 drivers/net/hamradio/mkiss.c                       | 10 +++---
 drivers/net/usb/cdc_ncm.c                          | 15 ++++----
 include/linux/netdevice.h                          | 18 +++++++---
 net/atm/clip.c                                     |  5 +--
 net/sched/sch_generic.c                            |  5 +--
 24 files changed, 181 insertions(+), 120 deletions(-)

diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c 
b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 3d5424f..de6cb14 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -983,6 +983,7 @@ void ipoib_cm_dev_stop(struct net_device *dev)
 static int ipoib_cm_rep_handler(struct ib_cm_id *cm_id,
                                const struct ib_cm_event *event)
 {
+       unsigned int bh;
        struct ipoib_cm_tx *p = cm_id->context;
        struct ipoib_dev_priv *priv = ipoib_priv(p->dev);
        struct ipoib_cm_data *data = event->private_data;
@@ -1027,14 +1028,14 @@ static int ipoib_cm_rep_handler(struct ib_cm_id *cm_id,
 
        skb_queue_head_init(&skqueue);
 
-       netif_tx_lock_bh(p->dev);
+       bh = netif_tx_lock_bh(p->dev);
        spin_lock_irq(&priv->lock);
        set_bit(IPOIB_FLAG_OPER_UP, &p->flags);
        if (p->neigh)
                while ((skb = __skb_dequeue(&p->neigh->queue)))
                        __skb_queue_tail(&skqueue, skb);
        spin_unlock_irq(&priv->lock);
-       netif_tx_unlock_bh(p->dev);
+       netif_tx_unlock_bh(p->dev, bh);
 
        while ((skb = __skb_dequeue(&skqueue))) {
                skb->dev = p->dev;
@@ -1201,6 +1202,7 @@ static int ipoib_cm_tx_init(struct ipoib_cm_tx *p, u32 
qpn,
 
 static void ipoib_cm_tx_destroy(struct ipoib_cm_tx *p)
 {
+       unsigned int bh;
        struct ipoib_dev_priv *priv = ipoib_priv(p->dev);
        struct ipoib_tx_buf *tx_req;
        unsigned long begin;
@@ -1231,14 +1233,14 @@ static void ipoib_cm_tx_destroy(struct ipoib_cm_tx *p)
                tx_req = &p->tx_ring[p->tx_tail & (ipoib_sendq_size - 1)];
                ipoib_dma_unmap_tx(priv, tx_req);
                dev_kfree_skb_any(tx_req->skb);
-               netif_tx_lock_bh(p->dev);
+               bh = netif_tx_lock_bh(p->dev);
                ++p->tx_tail;
                ++priv->tx_tail;
                if (unlikely(priv->tx_head - priv->tx_tail == ipoib_sendq_size 
>> 1) &&
                    netif_queue_stopped(p->dev) &&
                    test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
                        netif_wake_queue(p->dev);
-               netif_tx_unlock_bh(p->dev);
+               netif_tx_unlock_bh(p->dev, bh);
        }
 
        if (p->qp)
@@ -1251,6 +1253,7 @@ static void ipoib_cm_tx_destroy(struct ipoib_cm_tx *p)
 static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id,
                               const struct ib_cm_event *event)
 {
+       unsigned int bh;
        struct ipoib_cm_tx *tx = cm_id->context;
        struct ipoib_dev_priv *priv = ipoib_priv(tx->dev);
        struct net_device *dev = priv->dev;
@@ -1274,7 +1277,7 @@ static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id,
        case IB_CM_REJ_RECEIVED:
        case IB_CM_TIMEWAIT_EXIT:
                ipoib_dbg(priv, "CM error %d.\n", event->event);
-               netif_tx_lock_bh(dev);
+               bh = netif_tx_lock_bh(dev);
                spin_lock_irqsave(&priv->lock, flags);
                neigh = tx->neigh;
 
@@ -1291,7 +1294,7 @@ static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id,
                }
 
                spin_unlock_irqrestore(&priv->lock, flags);
-               netif_tx_unlock_bh(dev);
+               netif_tx_unlock_bh(dev, bh);
                break;
        default:
                break;
@@ -1339,6 +1342,7 @@ void ipoib_cm_destroy_tx(struct ipoib_cm_tx *tx)
 
 static void ipoib_cm_tx_start(struct work_struct *work)
 {
+       unsigned int bh;
        struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
                                                   cm.start_task);
        struct net_device *dev = priv->dev;
@@ -1351,7 +1355,7 @@ static void ipoib_cm_tx_start(struct work_struct *work)
        struct sa_path_rec pathrec;
        u32 qpn;
 
-       netif_tx_lock_bh(dev);
+       bh = netif_tx_lock_bh(dev);
        spin_lock_irqsave(&priv->lock, flags);
 
        while (!list_empty(&priv->cm.start_list)) {
@@ -1374,11 +1378,11 @@ static void ipoib_cm_tx_start(struct work_struct *work)
                memcpy(&pathrec, &p->path->pathrec, sizeof(pathrec));
 
                spin_unlock_irqrestore(&priv->lock, flags);
-               netif_tx_unlock_bh(dev);
+               netif_tx_unlock_bh(dev, bh);
 
                ret = ipoib_cm_tx_init(p, qpn, &pathrec);
 
-               netif_tx_lock_bh(dev);
+               bh = netif_tx_lock_bh(dev);
                spin_lock_irqsave(&priv->lock, flags);
 
                if (ret) {
@@ -1394,36 +1398,38 @@ static void ipoib_cm_tx_start(struct work_struct *work)
        }
 
        spin_unlock_irqrestore(&priv->lock, flags);
-       netif_tx_unlock_bh(dev);
+       netif_tx_unlock_bh(dev, bh);
 }
 
 static void ipoib_cm_tx_reap(struct work_struct *work)
 {
+       unsigned int bh;
        struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
                                                   cm.reap_task);
        struct net_device *dev = priv->dev;
        struct ipoib_cm_tx *p;
        unsigned long flags;
 
-       netif_tx_lock_bh(dev);
+       bh = netif_tx_lock_bh(dev);
        spin_lock_irqsave(&priv->lock, flags);
 
        while (!list_empty(&priv->cm.reap_list)) {
                p = list_entry(priv->cm.reap_list.next, typeof(*p), list);
                list_del_init(&p->list);
                spin_unlock_irqrestore(&priv->lock, flags);
-               netif_tx_unlock_bh(dev);
+               netif_tx_unlock_bh(dev, bh);
                ipoib_cm_tx_destroy(p);
-               netif_tx_lock_bh(dev);
+               bh = netif_tx_lock_bh(dev);
                spin_lock_irqsave(&priv->lock, flags);
        }
 
        spin_unlock_irqrestore(&priv->lock, flags);
-       netif_tx_unlock_bh(dev);
+       netif_tx_unlock_bh(dev, bh);
 }
 
 static void ipoib_cm_skb_reap(struct work_struct *work)
 {
+       unsigned int bh;
        struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
                                                   cm.skb_task);
        struct net_device *dev = priv->dev;
@@ -1431,12 +1437,12 @@ static void ipoib_cm_skb_reap(struct work_struct *work)
        unsigned long flags;
        unsigned int mtu = priv->mcast_mtu;
 
-       netif_tx_lock_bh(dev);
+       bh = netif_tx_lock_bh(dev);
        spin_lock_irqsave(&priv->lock, flags);
 
        while ((skb = skb_dequeue(&priv->cm.skb_queue))) {
                spin_unlock_irqrestore(&priv->lock, flags);
-               netif_tx_unlock_bh(dev);
+               netif_tx_unlock_bh(dev, bh);
 
                if (skb->protocol == htons(ETH_P_IP))
                        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, 
htonl(mtu));
@@ -1446,12 +1452,12 @@ static void ipoib_cm_skb_reap(struct work_struct *work)
 #endif
                dev_kfree_skb_any(skb);
 
-               netif_tx_lock_bh(dev);
+               bh = netif_tx_lock_bh(dev);
                spin_lock_irqsave(&priv->lock, flags);
        }
 
        spin_unlock_irqrestore(&priv->lock, flags);
-       netif_tx_unlock_bh(dev);
+       netif_tx_unlock_bh(dev, bh);
 }
 
 void ipoib_cm_skb_too_long(struct net_device *dev, struct sk_buff *skb,
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c 
b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 9006a13..87f2a5c 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -667,12 +667,13 @@ int ipoib_send(struct net_device *dev, struct sk_buff 
*skb,
 
 static void __ipoib_reap_ah(struct net_device *dev)
 {
+       unsigned int bh;
        struct ipoib_dev_priv *priv = ipoib_priv(dev);
        struct ipoib_ah *ah, *tah;
        LIST_HEAD(remove_list);
        unsigned long flags;
 
-       netif_tx_lock_bh(dev);
+       bh = netif_tx_lock_bh(dev);
        spin_lock_irqsave(&priv->lock, flags);
 
        list_for_each_entry_safe(ah, tah, &priv->dead_ahs, list)
@@ -683,7 +684,7 @@ static void __ipoib_reap_ah(struct net_device *dev)
                }
 
        spin_unlock_irqrestore(&priv->lock, flags);
-       netif_tx_unlock_bh(dev);
+       netif_tx_unlock_bh(dev, bh);
 }
 
 void ipoib_reap_ah(struct work_struct *work)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c 
b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index e3d28f9..eaefa43 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -709,12 +709,13 @@ static void push_pseudo_header(struct sk_buff *skb, const 
char *daddr)
 
 void ipoib_flush_paths(struct net_device *dev)
 {
+       unsigned int bh;
        struct ipoib_dev_priv *priv = ipoib_priv(dev);
        struct ipoib_path *path, *tp;
        LIST_HEAD(remove_list);
        unsigned long flags;
 
-       netif_tx_lock_bh(dev);
+       bh = netif_tx_lock_bh(dev);
        spin_lock_irqsave(&priv->lock, flags);
 
        list_splice_init(&priv->path_list, &remove_list);
@@ -726,15 +727,15 @@ void ipoib_flush_paths(struct net_device *dev)
                if (path->query)
                        ib_sa_cancel_query(path->query_id, path->query);
                spin_unlock_irqrestore(&priv->lock, flags);
-               netif_tx_unlock_bh(dev);
+               netif_tx_unlock_bh(dev, bh);
                wait_for_completion(&path->done);
                path_free(dev, path);
-               netif_tx_lock_bh(dev);
+               bh = netif_tx_lock_bh(dev);
                spin_lock_irqsave(&priv->lock, flags);
        }
 
        spin_unlock_irqrestore(&priv->lock, flags);
-       netif_tx_unlock_bh(dev);
+       netif_tx_unlock_bh(dev, bh);
 }
 
 static void path_rec_completion(int status,
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c 
b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index b9e9562..26a4b01 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -111,6 +111,7 @@ static void __ipoib_mcast_schedule_join_thread(struct 
ipoib_dev_priv *priv,
 
 static void ipoib_mcast_free(struct ipoib_mcast *mcast)
 {
+       unsigned int bh;
        struct net_device *dev = mcast->dev;
        int tx_dropped = 0;
 
@@ -128,9 +129,9 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
                dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
        }
 
-       netif_tx_lock_bh(dev);
+       bh = netif_tx_lock_bh(dev);
        dev->stats.tx_dropped += tx_dropped;
-       netif_tx_unlock_bh(dev);
+       netif_tx_unlock_bh(dev, bh);
 
        kfree(mcast);
 }
@@ -211,6 +212,7 @@ static int __ipoib_mcast_add(struct net_device *dev, struct 
ipoib_mcast *mcast)
 static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
                                   struct ib_sa_mcmember_rec *mcmember)
 {
+       unsigned int bh;
        struct net_device *dev = mcast->dev;
        struct ipoib_dev_priv *priv = ipoib_priv(dev);
        struct rdma_netdev *rn = netdev_priv(dev);
@@ -304,11 +306,11 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast 
*mcast,
                        mcast->mcmember.sl);
 
        /* actually send any queued packets */
-       netif_tx_lock_bh(dev);
+       bh = netif_tx_lock_bh(dev);
        while (!skb_queue_empty(&mcast->pkt_queue)) {
                struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue);
 
-               netif_tx_unlock_bh(dev);
+               netif_tx_unlock_bh(dev, bh);
 
                skb->dev = dev;
 
@@ -316,9 +318,9 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast 
*mcast,
                if (ret)
                        ipoib_warn(priv, "%s:dev_queue_xmit failed to re-queue 
packet, ret:%d\n",
                                   __func__, ret);
-               netif_tx_lock_bh(dev);
+               bh = netif_tx_lock_bh(dev);
        }
-       netif_tx_unlock_bh(dev);
+       netif_tx_unlock_bh(dev, bh);
 
        return 0;
 }
@@ -367,6 +369,7 @@ void ipoib_mcast_carrier_on_task(struct work_struct *work)
 static int ipoib_mcast_join_complete(int status,
                                     struct ib_sa_multicast *multicast)
 {
+       unsigned int bh;
        struct ipoib_mcast *mcast = multicast->context;
        struct net_device *dev = mcast->dev;
        struct ipoib_dev_priv *priv = ipoib_priv(dev);
@@ -435,12 +438,12 @@ static int ipoib_mcast_join_complete(int status,
                         * is why the join thread ignores this group.
                         */
                        mcast->backoff = 1;
-                       netif_tx_lock_bh(dev);
+                       bh = netif_tx_lock_bh(dev);
                        while (!skb_queue_empty(&mcast->pkt_queue)) {
                                ++dev->stats.tx_dropped;
                                
dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
                        }
-                       netif_tx_unlock_bh(dev);
+                       netif_tx_unlock_bh(dev, bh);
                } else {
                        spin_lock_irq(&priv->lock);
                        /* Requeue this join task with a backoff delay */
diff --git a/drivers/net/ethernet/aurora/nb8800.c 
b/drivers/net/ethernet/aurora/nb8800.c
index c8d1f8f..77e116a 100644
--- a/drivers/net/ethernet/aurora/nb8800.c
+++ b/drivers/net/ethernet/aurora/nb8800.c
@@ -629,6 +629,7 @@ static void nb8800_mac_config(struct net_device *dev)
 
 static void nb8800_pause_config(struct net_device *dev)
 {
+       unsigned int bh;
        struct nb8800_priv *priv = netdev_priv(dev);
        struct phy_device *phydev = dev->phydev;
        u32 rxcr;
@@ -649,11 +650,11 @@ static void nb8800_pause_config(struct net_device *dev)
 
        if (netif_running(dev)) {
                napi_disable(&priv->napi);
-               netif_tx_lock_bh(dev);
+               bh = netif_tx_lock_bh(dev);
                nb8800_dma_stop(dev);
                nb8800_modl(priv, NB8800_RXC_CR, RCR_FL, priv->pause_tx);
                nb8800_start_rx(dev);
-               netif_tx_unlock_bh(dev);
+               netif_tx_unlock_bh(dev, bh);
                napi_enable(&priv->napi);
        } else {
                nb8800_modl(priv, NB8800_RXC_CR, RCR_FL, priv->pause_tx);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c 
b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index 6807bc3..a9799ce 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -3829,6 +3829,7 @@ void t4_free_ofld_rxqs(struct adapter *adap, int n, 
struct sge_ofld_rxq *q)
  */
 void t4_free_sge_resources(struct adapter *adap)
 {
+       unsigned int bh;
        int i;
        struct sge_eth_rxq *eq;
        struct sge_eth_txq *etq;
@@ -3855,9 +3856,9 @@ void t4_free_sge_resources(struct adapter *adap)
                if (etq->q.desc) {
                        t4_eth_eq_free(adap, adap->mbox, adap->pf, 0,
                                       etq->q.cntxt_id);
-                       __netif_tx_lock_bh(etq->txq);
+                       bh = __netif_tx_lock_bh(etq->txq);
                        free_tx_desc(adap, &etq->q, etq->q.in_use, true);
-                       __netif_tx_unlock_bh(etq->txq);
+                       __netif_tx_unlock_bh(etq->txq, bh);
                        kfree(etq->q.sdesc);
                        free_txq(adap, &etq->q);
                }
diff --git a/drivers/net/ethernet/freescale/fec_main.c 
b/drivers/net/ethernet/freescale/fec_main.c
index 2708297..17cda1d 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1149,6 +1149,7 @@ fec_timeout(struct net_device *ndev)
 
 static void fec_enet_timeout_work(struct work_struct *work)
 {
+       unsigned int bh;
        struct fec_enet_private *fep =
                container_of(work, struct fec_enet_private, tx_timeout_work);
        struct net_device *ndev = fep->netdev;
@@ -1156,10 +1157,10 @@ static void fec_enet_timeout_work(struct work_struct 
*work)
        rtnl_lock();
        if (netif_device_present(ndev) || netif_running(ndev)) {
                napi_disable(&fep->napi);
-               netif_tx_lock_bh(ndev);
+               bh = netif_tx_lock_bh(ndev);
                fec_restart(ndev);
                netif_wake_queue(ndev);
-               netif_tx_unlock_bh(ndev);
+               netif_tx_unlock_bh(ndev, bh);
                napi_enable(&fep->napi);
        }
        rtnl_unlock();
@@ -1708,6 +1709,7 @@ static void fec_get_mac(struct net_device *ndev)
  */
 static void fec_enet_adjust_link(struct net_device *ndev)
 {
+       unsigned int bh;
        struct fec_enet_private *fep = netdev_priv(ndev);
        struct phy_device *phy_dev = ndev->phydev;
        int status_change = 0;
@@ -1744,18 +1746,18 @@ static void fec_enet_adjust_link(struct net_device 
*ndev)
                /* if any of the above changed restart the FEC */
                if (status_change) {
                        napi_disable(&fep->napi);
-                       netif_tx_lock_bh(ndev);
+                       bh = netif_tx_lock_bh(ndev);
                        fec_restart(ndev);
                        netif_wake_queue(ndev);
-                       netif_tx_unlock_bh(ndev);
+                       netif_tx_unlock_bh(ndev, bh);
                        napi_enable(&fep->napi);
                }
        } else {
                if (fep->link) {
                        napi_disable(&fep->napi);
-                       netif_tx_lock_bh(ndev);
+                       bh = netif_tx_lock_bh(ndev);
                        fec_stop(ndev);
-                       netif_tx_unlock_bh(ndev);
+                       netif_tx_unlock_bh(ndev, bh);
                        napi_enable(&fep->napi);
                        fep->link = phy_dev->link;
                        status_change = 1;
@@ -2213,6 +2215,7 @@ static void fec_enet_get_pauseparam(struct net_device 
*ndev,
 static int fec_enet_set_pauseparam(struct net_device *ndev,
                                   struct ethtool_pauseparam *pause)
 {
+       unsigned int bh;
        struct fec_enet_private *fep = netdev_priv(ndev);
 
        if (!ndev->phydev)
@@ -2245,10 +2248,10 @@ static int fec_enet_set_pauseparam(struct net_device 
*ndev,
        }
        if (netif_running(ndev)) {
                napi_disable(&fep->napi);
-               netif_tx_lock_bh(ndev);
+               bh = netif_tx_lock_bh(ndev);
                fec_restart(ndev);
                netif_wake_queue(ndev);
-               netif_tx_unlock_bh(ndev);
+               netif_tx_unlock_bh(ndev, bh);
                napi_enable(&fep->napi);
        }
 
@@ -3072,17 +3075,18 @@ static inline void fec_enet_set_netdev_features(struct 
net_device *netdev,
 static int fec_set_features(struct net_device *netdev,
        netdev_features_t features)
 {
+       unsigned int bh;
        struct fec_enet_private *fep = netdev_priv(netdev);
        netdev_features_t changed = features ^ netdev->features;
 
        if (netif_running(netdev) && changed & NETIF_F_RXCSUM) {
                napi_disable(&fep->napi);
-               netif_tx_lock_bh(netdev);
+               bh = netif_tx_lock_bh(netdev);
                fec_stop(netdev);
                fec_enet_set_netdev_features(netdev, features);
                fec_restart(netdev);
                netif_tx_wake_all_queues(netdev);
-               netif_tx_unlock_bh(netdev);
+               netif_tx_unlock_bh(netdev, bh);
                napi_enable(&fep->napi);
        } else {
                fec_enet_set_netdev_features(netdev, features);
@@ -3609,6 +3613,7 @@ fec_drv_remove(struct platform_device *pdev)
 
 static int __maybe_unused fec_suspend(struct device *dev)
 {
+       unsigned int bh;
        struct net_device *ndev = dev_get_drvdata(dev);
        struct fec_enet_private *fep = netdev_priv(ndev);
 
@@ -3618,9 +3623,9 @@ static int __maybe_unused fec_suspend(struct device *dev)
                        fep->wol_flag |= FEC_WOL_FLAG_SLEEP_ON;
                phy_stop(ndev->phydev);
                napi_disable(&fep->napi);
-               netif_tx_lock_bh(ndev);
+               bh = netif_tx_lock_bh(ndev);
                netif_device_detach(ndev);
-               netif_tx_unlock_bh(ndev);
+               netif_tx_unlock_bh(ndev, bh);
                fec_stop(ndev);
                fec_enet_clk_enable(ndev, false);
                if (!(fep->wol_flag & FEC_WOL_FLAG_ENABLE))
@@ -3642,6 +3647,7 @@ static int __maybe_unused fec_suspend(struct device *dev)
 
 static int __maybe_unused fec_resume(struct device *dev)
 {
+       unsigned int bh;
        struct net_device *ndev = dev_get_drvdata(dev);
        struct fec_enet_private *fep = netdev_priv(ndev);
        struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
@@ -3672,9 +3678,9 @@ static int __maybe_unused fec_resume(struct device *dev)
                        pinctrl_pm_select_default_state(&fep->pdev->dev);
                }
                fec_restart(ndev);
-               netif_tx_lock_bh(ndev);
+               bh = netif_tx_lock_bh(ndev);
                netif_device_attach(ndev);
-               netif_tx_unlock_bh(ndev);
+               netif_tx_unlock_bh(ndev, bh);
                napi_enable(&fep->napi);
                phy_start(ndev->phydev);
        }
diff --git a/drivers/net/ethernet/ibm/emac/core.c 
b/drivers/net/ethernet/ibm/emac/core.c
index 3726646..3f65b2c 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -296,11 +296,12 @@ static void emac_rx_disable(struct emac_instance *dev)
 
 static inline void emac_netif_stop(struct emac_instance *dev)
 {
-       netif_tx_lock_bh(dev->ndev);
+       unsigned int bh;
+       bh = netif_tx_lock_bh(dev->ndev);
        netif_addr_lock(dev->ndev);
        dev->no_mcast = 1;
        netif_addr_unlock(dev->ndev);
-       netif_tx_unlock_bh(dev->ndev);
+       netif_tx_unlock_bh(dev->ndev, bh);
        netif_trans_update(dev->ndev);  /* prevent tx timeout */
        mal_poll_disable(dev->mal, &dev->commac);
        netif_tx_disable(dev->ndev);
@@ -308,13 +309,14 @@ static inline void emac_netif_stop(struct emac_instance 
*dev)
 
 static inline void emac_netif_start(struct emac_instance *dev)
 {
-       netif_tx_lock_bh(dev->ndev);
+       unsigned int bh;
+       bh = netif_tx_lock_bh(dev->ndev);
        netif_addr_lock(dev->ndev);
        dev->no_mcast = 0;
        if (dev->mcast_pending && netif_running(dev->ndev))
                __emac_set_multicast_list(dev);
        netif_addr_unlock(dev->ndev);
-       netif_tx_unlock_bh(dev->ndev);
+       netif_tx_unlock_bh(dev->ndev, bh);
 
        netif_wake_queue(dev->ndev);
 
@@ -1607,6 +1609,7 @@ static void emac_parse_tx_error(struct emac_instance 
*dev, u16 ctrl)
 
 static void emac_poll_tx(void *param)
 {
+       unsigned int bh;
        struct emac_instance *dev = param;
        u32 bad_mask;
 
@@ -1617,7 +1620,7 @@ static void emac_poll_tx(void *param)
        else
                bad_mask = EMAC_IS_BAD_TX;
 
-       netif_tx_lock_bh(dev->ndev);
+       bh = netif_tx_lock_bh(dev->ndev);
        if (dev->tx_cnt) {
                u16 ctrl;
                int slot = dev->ack_slot, n = 0;
@@ -1648,7 +1651,7 @@ static void emac_poll_tx(void *param)
                        DBG2(dev, "tx %d pkts" NL, n);
                }
        }
-       netif_tx_unlock_bh(dev->ndev);
+       netif_tx_unlock_bh(dev->ndev, bh);
 }
 
 static inline void emac_recycle_rx_skb(struct emac_instance *dev, int slot,
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c 
b/drivers/net/ethernet/marvell/mv643xx_eth.c
index 62f204f..56c74c2 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -1071,11 +1071,12 @@ static void txq_kick(struct tx_queue *txq)
 
 static int txq_reclaim(struct tx_queue *txq, int budget, int force)
 {
+       unsigned int bh;
        struct mv643xx_eth_private *mp = txq_to_mp(txq);
        struct netdev_queue *nq = netdev_get_tx_queue(mp->dev, txq->index);
        int reclaimed;
 
-       __netif_tx_lock_bh(nq);
+       bh = __netif_tx_lock_bh(nq);
 
        reclaimed = 0;
        while (reclaimed < budget && txq->tx_desc_count > 0) {
@@ -1131,7 +1132,7 @@ static int txq_reclaim(struct tx_queue *txq, int budget, 
int force)
 
        }
 
-       __netif_tx_unlock_bh(nq);
+       __netif_tx_unlock_bh(nq, bh);
 
        if (reclaimed < budget)
                mp->work_tx &= ~(1 << txq->index);
diff --git a/drivers/net/ethernet/marvell/skge.c 
b/drivers/net/ethernet/marvell/skge.c
index 9c08c36..506087a 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -2653,6 +2653,7 @@ static void skge_rx_stop(struct skge_hw *hw, int port)
 
 static int skge_down(struct net_device *dev)
 {
+       unsigned int bh;
        struct skge_port *skge = netdev_priv(dev);
        struct skge_hw *hw = skge->hw;
        int port = skge->port;
@@ -2718,9 +2719,9 @@ static int skge_down(struct net_device *dev)
 
        skge_led(skge, LED_MODE_OFF);
 
-       netif_tx_lock_bh(dev);
+       bh = netif_tx_lock_bh(dev);
        skge_tx_clean(dev);
-       netif_tx_unlock_bh(dev);
+       netif_tx_unlock_bh(dev, bh);
 
        skge_rx_clean(skge);
 
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c 
b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 6785661..666708a 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -1878,6 +1878,7 @@ int mlx4_en_start_port(struct net_device *dev)
 
 void mlx4_en_stop_port(struct net_device *dev, int detach)
 {
+       unsigned int bh;
        struct mlx4_en_priv *priv = netdev_priv(dev);
        struct mlx4_en_dev *mdev = priv->mdev;
        struct mlx4_en_mc_list *mclist, *tmp;
@@ -1894,11 +1895,11 @@ void mlx4_en_stop_port(struct net_device *dev, int 
detach)
        mlx4_CLOSE_PORT(mdev->dev, priv->port);
 
        /* Synchronize with tx routine */
-       netif_tx_lock_bh(dev);
+       bh = netif_tx_lock_bh(dev);
        if (detach)
                netif_device_detach(dev);
        netif_tx_stop_all_queues(dev);
-       netif_tx_unlock_bh(dev);
+       netif_tx_unlock_bh(dev, bh);
 
        netif_tx_disable(dev);
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c 
b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 5a7939e..6d66d1c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -1349,9 +1349,10 @@ static void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq)
 
 static inline void netif_tx_disable_queue(struct netdev_queue *txq)
 {
-       __netif_tx_lock_bh(txq);
+       unsigned int bh;
+       bh = __netif_tx_lock_bh(txq);
        netif_tx_stop_queue(txq);
-       __netif_tx_unlock_bh(txq);
+       __netif_tx_unlock_bh(txq, bh);
 }
 
 static void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq)
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c 
b/drivers/net/ethernet/nvidia/forcedeth.c
index 1d9b0d4..7b5ac16 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -3028,6 +3028,7 @@ static void set_bufsize(struct net_device *dev)
  */
 static int nv_change_mtu(struct net_device *dev, int new_mtu)
 {
+       unsigned int bh;
        struct fe_priv *np = netdev_priv(dev);
        int old_mtu;
 
@@ -3049,7 +3050,7 @@ static int nv_change_mtu(struct net_device *dev, int 
new_mtu)
                 */
                nv_disable_irq(dev);
                nv_napi_disable(dev);
-               netif_tx_lock_bh(dev);
+               bh = netif_tx_lock_bh(dev);
                netif_addr_lock(dev);
                spin_lock(&np->lock);
                /* stop engines */
@@ -3076,7 +3077,7 @@ static int nv_change_mtu(struct net_device *dev, int 
new_mtu)
                nv_start_rxtx(dev);
                spin_unlock(&np->lock);
                netif_addr_unlock(dev);
-               netif_tx_unlock_bh(dev);
+               netif_tx_unlock_bh(dev, bh);
                nv_napi_enable(dev);
                nv_enable_irq(dev);
        }
@@ -3102,6 +3103,7 @@ static void nv_copy_mac_to_hw(struct net_device *dev)
  */
 static int nv_set_mac_address(struct net_device *dev, void *addr)
 {
+       unsigned int bh;
        struct fe_priv *np = netdev_priv(dev);
        struct sockaddr *macaddr = (struct sockaddr *)addr;
 
@@ -3112,7 +3114,7 @@ static int nv_set_mac_address(struct net_device *dev, 
void *addr)
        memcpy(dev->dev_addr, macaddr->sa_data, ETH_ALEN);
 
        if (netif_running(dev)) {
-               netif_tx_lock_bh(dev);
+               bh = netif_tx_lock_bh(dev);
                netif_addr_lock(dev);
                spin_lock_irq(&np->lock);
 
@@ -3126,7 +3128,7 @@ static int nv_set_mac_address(struct net_device *dev, 
void *addr)
                nv_start_rx(dev);
                spin_unlock_irq(&np->lock);
                netif_addr_unlock(dev);
-               netif_tx_unlock_bh(dev);
+               netif_tx_unlock_bh(dev, bh);
        } else {
                nv_copy_mac_to_hw(dev);
        }
@@ -4088,6 +4090,7 @@ static void nv_free_irq(struct net_device *dev)
 
 static void nv_do_nic_poll(struct timer_list *t)
 {
+       unsigned int bh;
        struct fe_priv *np = from_timer(np, t, nic_poll);
        struct net_device *dev = np->dev;
        u8 __iomem *base = get_hwbase(dev);
@@ -4129,7 +4132,7 @@ static void nv_do_nic_poll(struct timer_list *t)
                np->recover_error = 0;
                netdev_info(dev, "MAC in recoverable error state\n");
                if (netif_running(dev)) {
-                       netif_tx_lock_bh(dev);
+                       bh = netif_tx_lock_bh(dev);
                        netif_addr_lock(dev);
                        spin_lock(&np->lock);
                        /* stop engines */
@@ -4163,7 +4166,7 @@ static void nv_do_nic_poll(struct timer_list *t)
                        nv_start_rxtx(dev);
                        spin_unlock(&np->lock);
                        netif_addr_unlock(dev);
-                       netif_tx_unlock_bh(dev);
+                       netif_tx_unlock_bh(dev, bh);
                }
        }
 
@@ -4346,6 +4349,7 @@ static int nv_get_link_ksettings(struct net_device *dev,
 static int nv_set_link_ksettings(struct net_device *dev,
                                 const struct ethtool_link_ksettings *cmd)
 {
+       unsigned int bh;
        struct fe_priv *np = netdev_priv(dev);
        u32 speed = cmd->base.speed;
        u32 advertising;
@@ -4389,7 +4393,7 @@ static int nv_set_link_ksettings(struct net_device *dev,
                unsigned long flags;
 
                nv_disable_irq(dev);
-               netif_tx_lock_bh(dev);
+               bh = netif_tx_lock_bh(dev);
                netif_addr_lock(dev);
                /* with plain spinlock lockdep complains */
                spin_lock_irqsave(&np->lock, flags);
@@ -4405,7 +4409,7 @@ static int nv_set_link_ksettings(struct net_device *dev,
                nv_stop_rxtx(dev);
                spin_unlock_irqrestore(&np->lock, flags);
                netif_addr_unlock(dev);
-               netif_tx_unlock_bh(dev);
+               netif_tx_unlock_bh(dev, bh);
        }
 
        if (cmd->base.autoneg == AUTONEG_ENABLE) {
@@ -4540,6 +4544,7 @@ static void nv_get_regs(struct net_device *dev, struct 
ethtool_regs *regs, void
 
 static int nv_nway_reset(struct net_device *dev)
 {
+       unsigned int bh;
        struct fe_priv *np = netdev_priv(dev);
        int ret;
 
@@ -4549,14 +4554,14 @@ static int nv_nway_reset(struct net_device *dev)
                netif_carrier_off(dev);
                if (netif_running(dev)) {
                        nv_disable_irq(dev);
-                       netif_tx_lock_bh(dev);
+                       bh = netif_tx_lock_bh(dev);
                        netif_addr_lock(dev);
                        spin_lock(&np->lock);
                        /* stop engines */
                        nv_stop_rxtx(dev);
                        spin_unlock(&np->lock);
                        netif_addr_unlock(dev);
-                       netif_tx_unlock_bh(dev);
+                       netif_tx_unlock_bh(dev, bh);
                        netdev_info(dev, "link down\n");
                }
 
@@ -4598,6 +4603,7 @@ static void nv_get_ringparam(struct net_device *dev, 
struct ethtool_ringparam* r
 
 static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* 
ring)
 {
+       unsigned int bh;
        struct fe_priv *np = netdev_priv(dev);
        u8 __iomem *base = get_hwbase(dev);
        u8 *rxtx_ring, *rx_skbuff, *tx_skbuff;
@@ -4660,7 +4666,7 @@ static int nv_set_ringparam(struct net_device *dev, 
struct ethtool_ringparam* ri
        if (netif_running(dev)) {
                nv_disable_irq(dev);
                nv_napi_disable(dev);
-               netif_tx_lock_bh(dev);
+               bh = netif_tx_lock_bh(dev);
                netif_addr_lock(dev);
                spin_lock(&np->lock);
                /* stop engines */
@@ -4711,7 +4717,7 @@ static int nv_set_ringparam(struct net_device *dev, 
struct ethtool_ringparam* ri
                nv_start_rxtx(dev);
                spin_unlock(&np->lock);
                netif_addr_unlock(dev);
-               netif_tx_unlock_bh(dev);
+               netif_tx_unlock_bh(dev, bh);
                nv_napi_enable(dev);
                nv_enable_irq(dev);
        }
@@ -4731,6 +4737,7 @@ static void nv_get_pauseparam(struct net_device *dev, 
struct ethtool_pauseparam*
 
 static int nv_set_pauseparam(struct net_device *dev, struct 
ethtool_pauseparam* pause)
 {
+       unsigned int bh;
        struct fe_priv *np = netdev_priv(dev);
        int adv, bmcr;
 
@@ -4747,14 +4754,14 @@ static int nv_set_pauseparam(struct net_device *dev, 
struct ethtool_pauseparam*
        netif_carrier_off(dev);
        if (netif_running(dev)) {
                nv_disable_irq(dev);
-               netif_tx_lock_bh(dev);
+               bh = netif_tx_lock_bh(dev);
                netif_addr_lock(dev);
                spin_lock(&np->lock);
                /* stop engines */
                nv_stop_rxtx(dev);
                spin_unlock(&np->lock);
                netif_addr_unlock(dev);
-               netif_tx_unlock_bh(dev);
+               netif_tx_unlock_bh(dev, bh);
        }
 
        np->pause_flags &= ~(NV_PAUSEFRAME_RX_REQ|NV_PAUSEFRAME_TX_REQ);
@@ -5190,6 +5197,7 @@ static int nv_loopback_test(struct net_device *dev)
 
 static void nv_self_test(struct net_device *dev, struct ethtool_test *test, 
u64 *buffer)
 {
+       unsigned int bh;
        struct fe_priv *np = netdev_priv(dev);
        u8 __iomem *base = get_hwbase(dev);
        int result, count;
@@ -5206,7 +5214,7 @@ static void nv_self_test(struct net_device *dev, struct 
ethtool_test *test, u64
                if (netif_running(dev)) {
                        netif_stop_queue(dev);
                        nv_napi_disable(dev);
-                       netif_tx_lock_bh(dev);
+                       bh = netif_tx_lock_bh(dev);
                        netif_addr_lock(dev);
                        spin_lock_irq(&np->lock);
                        nv_disable_hw_interrupts(dev, np->irqmask);
@@ -5221,7 +5229,7 @@ static void nv_self_test(struct net_device *dev, struct 
ethtool_test *test, u64
                        nv_drain_rxtx(dev);
                        spin_unlock_irq(&np->lock);
                        netif_addr_unlock(dev);
-                       netif_tx_unlock_bh(dev);
+                       netif_tx_unlock_bh(dev, bh);
                }
 
                if (!nv_register_test(dev)) {
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c 
b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c
index 52ad806..b39e0e81 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c
@@ -566,6 +566,7 @@ static int
 netxen_send_cmd_descs(struct netxen_adapter *adapter,
                struct cmd_desc_type0 *cmd_desc_arr, int nr_desc)
 {
+       unsigned int bh;
        u32 i, producer;
        struct netxen_cmd_buffer *pbuf;
        struct nx_host_tx_ring *tx_ring;
@@ -576,7 +577,7 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter,
                return -EIO;
 
        tx_ring = adapter->tx_ring;
-       __netif_tx_lock_bh(tx_ring->txq);
+       bh = __netif_tx_lock_bh(tx_ring->txq);
 
        producer = tx_ring->producer;
 
@@ -587,7 +588,7 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter,
                        if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH)
                                netif_tx_wake_queue(tx_ring->txq);
                } else {
-                       __netif_tx_unlock_bh(tx_ring->txq);
+                       __netif_tx_unlock_bh(tx_ring->txq, bh);
                        return -EBUSY;
                }
        }
@@ -609,7 +610,7 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter,
 
        netxen_nic_update_cmd_producer(adapter, tx_ring);
 
-       __netif_tx_unlock_bh(tx_ring->txq);
+       __netif_tx_unlock_bh(tx_ring->txq, bh);
 
        return 0;
 }
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c 
b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 822aa39..3991ad0 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -382,6 +382,7 @@ static int
 qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,
                struct cmd_desc_type0 *cmd_desc_arr, int nr_desc)
 {
+       unsigned int bh;
        u32 i, producer;
        struct qlcnic_cmd_buffer *pbuf;
        struct cmd_desc_type0 *cmd_desc;
@@ -393,7 +394,7 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,
                return -EIO;
 
        tx_ring = &adapter->tx_ring[0];
-       __netif_tx_lock_bh(tx_ring->txq);
+       bh = __netif_tx_lock_bh(tx_ring->txq);
 
        producer = tx_ring->producer;
 
@@ -405,7 +406,7 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,
                                netif_tx_wake_queue(tx_ring->txq);
                } else {
                        adapter->stats.xmit_off++;
-                       __netif_tx_unlock_bh(tx_ring->txq);
+                       __netif_tx_unlock_bh(tx_ring->txq, bh);
                        return -EBUSY;
                }
        }
@@ -429,7 +430,7 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,
 
        qlcnic_update_cmd_producer(tx_ring);
 
-       __netif_tx_unlock_bh(tx_ring->txq);
+       __netif_tx_unlock_bh(tx_ring->txq, bh);
 
        return 0;
 }
diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c 
b/drivers/net/ethernet/qualcomm/qca_spi.c
index 66b775d..31dbd19 100644
--- a/drivers/net/ethernet/qualcomm/qca_spi.c
+++ b/drivers/net/ethernet/qualcomm/qca_spi.c
@@ -272,6 +272,7 @@ qcaspi_tx_frame(struct qcaspi *qca, struct sk_buff *skb)
 static int
 qcaspi_transmit(struct qcaspi *qca)
 {
+       unsigned int bh;
        struct net_device_stats *n_stats = &qca->net_dev->stats;
        u16 available = 0;
        u32 pkt_len;
@@ -306,7 +307,7 @@ qcaspi_transmit(struct qcaspi *qca)
                /* XXX After inconsistent lock states netif_tx_lock()
                 * has been replaced by netif_tx_lock_bh() and so on.
                 */
-               netif_tx_lock_bh(qca->net_dev);
+               bh = netif_tx_lock_bh(qca->net_dev);
                dev_kfree_skb(qca->txr.skb[qca->txr.head]);
                qca->txr.skb[qca->txr.head] = NULL;
                qca->txr.size -= pkt_len;
@@ -316,7 +317,7 @@ qcaspi_transmit(struct qcaspi *qca)
                qca->txr.head = new_head;
                if (netif_queue_stopped(qca->net_dev))
                        netif_wake_queue(qca->net_dev);
-               netif_tx_unlock_bh(qca->net_dev);
+               netif_tx_unlock_bh(qca->net_dev, bh);
        }
 
        return 0;
@@ -450,12 +451,13 @@ qcaspi_tx_ring_has_space(struct tx_ring *txr)
 static void
 qcaspi_flush_tx_ring(struct qcaspi *qca)
 {
+       unsigned int bh;
        int i;
 
        /* XXX After inconsistent lock states netif_tx_lock()
         * has been replaced by netif_tx_lock_bh() and so on.
         */
-       netif_tx_lock_bh(qca->net_dev);
+       bh = netif_tx_lock_bh(qca->net_dev);
        for (i = 0; i < TX_RING_MAX_LEN; i++) {
                if (qca->txr.skb[i]) {
                        dev_kfree_skb(qca->txr.skb[i]);
@@ -466,7 +468,7 @@ qcaspi_flush_tx_ring(struct qcaspi *qca)
        qca->txr.tail = 0;
        qca->txr.head = 0;
        qca->txr.size = 0;
-       netif_tx_unlock_bh(qca->net_dev);
+       netif_tx_unlock_bh(qca->net_dev, bh);
 }
 
 static void
diff --git a/drivers/net/ethernet/sfc/falcon/selftest.c 
b/drivers/net/ethernet/sfc/falcon/selftest.c
index 55c0fbb..ab223e6 100644
--- a/drivers/net/ethernet/sfc/falcon/selftest.c
+++ b/drivers/net/ethernet/sfc/falcon/selftest.c
@@ -412,6 +412,7 @@ static void ef4_iterate_state(struct ef4_nic *efx)
 
 static int ef4_begin_loopback(struct ef4_tx_queue *tx_queue)
 {
+       unsigned int bh;
        struct ef4_nic *efx = tx_queue->efx;
        struct ef4_loopback_state *state = efx->loopback_selftest;
        struct ef4_loopback_payload *payload;
@@ -439,9 +440,9 @@ static int ef4_begin_loopback(struct ef4_tx_queue *tx_queue)
                 * interrupt handler. */
                smp_wmb();
 
-               netif_tx_lock_bh(efx->net_dev);
+               bh = netif_tx_lock_bh(efx->net_dev);
                rc = ef4_enqueue_skb(tx_queue, skb);
-               netif_tx_unlock_bh(efx->net_dev);
+               netif_tx_unlock_bh(efx->net_dev, bh);
 
                if (rc != NETDEV_TX_OK) {
                        netif_err(efx, drv, efx->net_dev,
@@ -469,13 +470,14 @@ static int ef4_poll_loopback(struct ef4_nic *efx)
 static int ef4_end_loopback(struct ef4_tx_queue *tx_queue,
                            struct ef4_loopback_self_tests *lb_tests)
 {
+       unsigned int bh;
        struct ef4_nic *efx = tx_queue->efx;
        struct ef4_loopback_state *state = efx->loopback_selftest;
        struct sk_buff *skb;
        int tx_done = 0, rx_good, rx_bad;
        int i, rc = 0;
 
-       netif_tx_lock_bh(efx->net_dev);
+       bh = netif_tx_lock_bh(efx->net_dev);
 
        /* Count the number of tx completions, and decrement the refcnt. Any
         * skbs not already completed will be free'd when the queue is flushed 
*/
@@ -486,7 +488,7 @@ static int ef4_end_loopback(struct ef4_tx_queue *tx_queue,
                dev_kfree_skb(skb);
        }
 
-       netif_tx_unlock_bh(efx->net_dev);
+       netif_tx_unlock_bh(efx->net_dev, bh);
 
        /* Check TX completion and received packet counts */
        rx_good = atomic_read(&state->rx_good);
diff --git a/drivers/net/ethernet/sfc/selftest.c 
b/drivers/net/ethernet/sfc/selftest.c
index f693694..59e4d35 100644
--- a/drivers/net/ethernet/sfc/selftest.c
+++ b/drivers/net/ethernet/sfc/selftest.c
@@ -412,6 +412,7 @@ static void efx_iterate_state(struct efx_nic *efx)
 
 static int efx_begin_loopback(struct efx_tx_queue *tx_queue)
 {
+       unsigned int bh;
        struct efx_nic *efx = tx_queue->efx;
        struct efx_loopback_state *state = efx->loopback_selftest;
        struct efx_loopback_payload *payload;
@@ -439,9 +440,9 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue)
                 * interrupt handler. */
                smp_wmb();
 
-               netif_tx_lock_bh(efx->net_dev);
+               bh = netif_tx_lock_bh(efx->net_dev);
                rc = efx_enqueue_skb(tx_queue, skb);
-               netif_tx_unlock_bh(efx->net_dev);
+               netif_tx_unlock_bh(efx->net_dev, bh);
 
                if (rc != NETDEV_TX_OK) {
                        netif_err(efx, drv, efx->net_dev,
@@ -469,13 +470,14 @@ static int efx_poll_loopback(struct efx_nic *efx)
 static int efx_end_loopback(struct efx_tx_queue *tx_queue,
                            struct efx_loopback_self_tests *lb_tests)
 {
+       unsigned int bh;
        struct efx_nic *efx = tx_queue->efx;
        struct efx_loopback_state *state = efx->loopback_selftest;
        struct sk_buff *skb;
        int tx_done = 0, rx_good, rx_bad;
        int i, rc = 0;
 
-       netif_tx_lock_bh(efx->net_dev);
+       bh = netif_tx_lock_bh(efx->net_dev);
 
        /* Count the number of tx completions, and decrement the refcnt. Any
         * skbs not already completed will be free'd when the queue is flushed 
*/
@@ -486,7 +488,7 @@ static int efx_end_loopback(struct efx_tx_queue *tx_queue,
                dev_kfree_skb(skb);
        }
 
-       netif_tx_unlock_bh(efx->net_dev);
+       netif_tx_unlock_bh(efx->net_dev, bh);
 
        /* Check TX completion and received packet counts */
        rx_good = atomic_read(&state->rx_good);
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index d79a69d..efc5c22 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -289,13 +289,14 @@ static int sp_close(struct net_device *dev)
 
 static int sp_set_mac_address(struct net_device *dev, void *addr)
 {
+       unsigned int bh;
        struct sockaddr_ax25 *sa = addr;
 
-       netif_tx_lock_bh(dev);
+       bh = netif_tx_lock_bh(dev);
        netif_addr_lock(dev);
        memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
        netif_addr_unlock(dev);
-       netif_tx_unlock_bh(dev);
+       netif_tx_unlock_bh(dev, bh);
 
        return 0;
 }
@@ -693,6 +694,7 @@ static void sixpack_close(struct tty_struct *tty)
 static int sixpack_ioctl(struct tty_struct *tty, struct file *file,
        unsigned int cmd, unsigned long arg)
 {
+       unsigned int bh;
        struct sixpack *sp = sp_get(tty);
        struct net_device *dev;
        unsigned int tmp, err;
@@ -735,9 +737,9 @@ static int sixpack_ioctl(struct tty_struct *tty, struct 
file *file,
                                break;
                        }
 
-                       netif_tx_lock_bh(dev);
+                       bh = netif_tx_lock_bh(dev);
                        memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN);
-                       netif_tx_unlock_bh(dev);
+                       netif_tx_unlock_bh(dev, bh);
 
                        err = 0;
                        break;
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 13e4c1e..3397dda 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -350,13 +350,14 @@ static void kiss_unesc(struct mkiss *ax, unsigned char s)
 
 static int ax_set_mac_address(struct net_device *dev, void *addr)
 {
+       unsigned int bh;
        struct sockaddr_ax25 *sa = addr;
 
-       netif_tx_lock_bh(dev);
+       bh = netif_tx_lock_bh(dev);
        netif_addr_lock(dev);
        memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
        netif_addr_unlock(dev);
-       netif_tx_unlock_bh(dev);
+       netif_tx_unlock_bh(dev, bh);
 
        return 0;
 }
@@ -816,6 +817,7 @@ static void mkiss_close(struct tty_struct *tty)
 static int mkiss_ioctl(struct tty_struct *tty, struct file *file,
        unsigned int cmd, unsigned long arg)
 {
+       unsigned int bh;
        struct mkiss *ax = mkiss_get(tty);
        struct net_device *dev;
        unsigned int tmp, err;
@@ -859,9 +861,9 @@ static int mkiss_ioctl(struct tty_struct *tty, struct file 
*file,
                        break;
                }
 
-               netif_tx_lock_bh(dev);
+               bh = netif_tx_lock_bh(dev);
                memcpy(dev->dev_addr, addr, AX25_ADDR_LEN);
-               netif_tx_unlock_bh(dev);
+               netif_tx_unlock_bh(dev, bh);
 
                err = 0;
                break;
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 1eaec64..b4b8a61 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -296,6 +296,7 @@ static ssize_t ndp_to_end_show(struct device *d, struct 
device_attribute *attr,
 
 static ssize_t ndp_to_end_store(struct device *d,  struct device_attribute 
*attr, const char *buf, size_t len)
 {
+       unsigned int bh;
        struct usbnet *dev = netdev_priv(to_net_dev(d));
        struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
        bool enable;
@@ -314,7 +315,7 @@ static ssize_t ndp_to_end_store(struct device *d,  struct 
device_attribute *attr
        }
 
        /* flush pending data before changing flag */
-       netif_tx_lock_bh(dev->net);
+       bh = netif_tx_lock_bh(dev->net);
        usbnet_start_xmit(NULL, dev->net);
        spin_lock_bh(&ctx->mtx);
        if (enable)
@@ -322,7 +323,7 @@ static ssize_t ndp_to_end_store(struct device *d,  struct 
device_attribute *attr
        else
                ctx->drvflags &= ~CDC_NCM_FLAG_NDP_TO_END;
        spin_unlock_bh(&ctx->mtx);
-       netif_tx_unlock_bh(dev->net);
+       netif_tx_unlock_bh(dev->net, bh);
 
        return len;
 }
@@ -375,6 +376,7 @@ static const struct attribute_group 
cdc_ncm_sysfs_attr_group = {
 /* handle rx_max and tx_max changes */
 static void cdc_ncm_update_rxtx_max(struct usbnet *dev, u32 new_rx, u32 new_tx)
 {
+       unsigned int bh;
        struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
        u8 iface_no = ctx->control->cur_altsetting->desc.bInterfaceNumber;
        u32 val;
@@ -421,7 +423,7 @@ static void cdc_ncm_update_rxtx_max(struct usbnet *dev, u32 
new_rx, u32 new_tx)
 
        /* we might need to flush any pending tx buffers if running */
        if (netif_running(dev->net) && val > ctx->tx_max) {
-               netif_tx_lock_bh(dev->net);
+               bh = netif_tx_lock_bh(dev->net);
                usbnet_start_xmit(NULL, dev->net);
                /* make sure tx_curr_skb is reallocated if it was empty */
                if (ctx->tx_curr_skb) {
@@ -429,7 +431,7 @@ static void cdc_ncm_update_rxtx_max(struct usbnet *dev, u32 
new_rx, u32 new_tx)
                        ctx->tx_curr_skb = NULL;
                }
                ctx->tx_max = val;
-               netif_tx_unlock_bh(dev->net);
+               netif_tx_unlock_bh(dev->net, bh);
        } else {
                ctx->tx_max = val;
        }
@@ -1359,6 +1361,7 @@ static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct 
hrtimer *timer)
 
 static void cdc_ncm_txpath_bh(unsigned long param)
 {
+       unsigned int bh;
        struct usbnet *dev = (struct usbnet *)param;
        struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
 
@@ -1370,9 +1373,9 @@ static void cdc_ncm_txpath_bh(unsigned long param)
        } else if (dev->net != NULL) {
                ctx->tx_reason_timeout++;       /* count reason for 
transmitting */
                spin_unlock_bh(&ctx->mtx);
-               netif_tx_lock_bh(dev->net);
+               bh = netif_tx_lock_bh(dev->net);
                usbnet_start_xmit(NULL, dev->net);
-               netif_tx_unlock_bh(dev->net);
+               netif_tx_unlock_bh(dev->net, bh);
        } else {
                spin_unlock_bh(&ctx->mtx);
        }
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index ca5ab98..b3617fe 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3794,10 +3794,14 @@ static inline void __netif_tx_release(struct 
netdev_queue *txq)
        __release(&txq->_xmit_lock);
 }
 
-static inline void __netif_tx_lock_bh(struct netdev_queue *txq)
+static inline unsigned int __netif_tx_lock_bh(struct netdev_queue *txq)
 {
+       unsigned int bh = 0;
+
        spin_lock_bh(&txq->_xmit_lock);
        txq->xmit_lock_owner = smp_processor_id();
+
+       return bh;
 }
 
 static inline bool __netif_tx_trylock(struct netdev_queue *txq)
@@ -3814,7 +3818,8 @@ static inline void __netif_tx_unlock(struct netdev_queue 
*txq)
        spin_unlock(&txq->_xmit_lock);
 }
 
-static inline void __netif_tx_unlock_bh(struct netdev_queue *txq)
+static inline void __netif_tx_unlock_bh(struct netdev_queue *txq,
+                                       unsigned int bh)
 {
        txq->xmit_lock_owner = -1;
        spin_unlock_bh(&txq->_xmit_lock);
@@ -3863,10 +3868,14 @@ static inline void netif_tx_lock(struct net_device *dev)
        }
 }
 
-static inline void netif_tx_lock_bh(struct net_device *dev)
+static inline unsigned int netif_tx_lock_bh(struct net_device *dev)
 {
+       unsigned int bh = 0;
+
        local_bh_disable();
        netif_tx_lock(dev);
+
+       return bh;
 }
 
 static inline void netif_tx_unlock(struct net_device *dev)
@@ -3886,7 +3895,8 @@ static inline void netif_tx_unlock(struct net_device *dev)
        spin_unlock(&dev->tx_global_lock);
 }
 
-static inline void netif_tx_unlock_bh(struct net_device *dev)
+static inline void netif_tx_unlock_bh(struct net_device *dev,
+                                     unsigned int bh)
 {
        netif_tx_unlock(dev);
        local_bh_enable();
diff --git a/net/atm/clip.c b/net/atm/clip.c
index d795b9c..5fddf85 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -84,6 +84,7 @@ static void link_vcc(struct clip_vcc *clip_vcc, struct 
atmarp_entry *entry)
 
 static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
 {
+       unsigned int bh;
        struct atmarp_entry *entry = clip_vcc->entry;
        struct clip_vcc **walk;
 
@@ -91,7 +92,7 @@ static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
                pr_crit("!clip_vcc->entry (clip_vcc %p)\n", clip_vcc);
                return;
        }
-       netif_tx_lock_bh(entry->neigh->dev);    /* block clip_start_xmit() */
+       bh = netif_tx_lock_bh(entry->neigh->dev);       /* block 
clip_start_xmit() */
        entry->neigh->used = jiffies;
        for (walk = &entry->vccs; *walk; walk = &(*walk)->next)
                if (*walk == clip_vcc) {
@@ -113,7 +114,7 @@ static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
                }
        pr_crit("ATMARP: failed (entry %p, vcc 0x%p)\n", entry, clip_vcc);
 out:
-       netif_tx_unlock_bh(entry->neigh->dev);
+       netif_tx_unlock_bh(entry->neigh->dev, bh);
 }
 
 /* The neighbour entry n->lock is held. */
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 69078c8..2266f1f 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -490,10 +490,11 @@ static void dev_watchdog_up(struct net_device *dev)
 
 static void dev_watchdog_down(struct net_device *dev)
 {
-       netif_tx_lock_bh(dev);
+       unsigned int bh;
+       bh = netif_tx_lock_bh(dev);
        if (del_timer(&dev->watchdog_timer))
                dev_put(dev);
-       netif_tx_unlock_bh(dev);
+       netif_tx_unlock_bh(dev, bh);
 }
 
 /**
-- 
2.7.4

Reply via email to