diff options
author | Roland Dreier <rolandd@cisco.com> | 2008-09-30 13:36:21 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2008-09-30 13:36:21 -0400 |
commit | 943c246e9ba9078a61b6bcc5b4a8131ce8befb64 (patch) | |
tree | 5be6015188c06d14ff39ac85f28f58834d001d05 /drivers/infiniband/ulp/ipoib/ipoib_cm.c | |
parent | c9da4bad5b80c3d9884e2c6ad8d2091252c32d5e (diff) |
IPoIB: Use netif_tx_lock() and get rid of private tx_lock, LLTX
Currently, IPoIB is an LLTX driver that uses its own IRQ-disabling
tx_lock. Not only do we want to get rid of LLTX, this actually causes
problems because of the skb_orphan() done with this tx_lock held: some
skb destructors expect to be run with interrupts enabled.
The simplest fix for this is to get rid of the driver-private tx_lock
and stop using LLTX. We kill off priv->tx_lock and use
netif_tx_lock[_bh]() instead; the patch to do this is a tiny bit
tricky because we need to update places that take priv->lock inside
the tx_lock to disable IRQs, rather than relying on tx_lock having
already disabled IRQs.
Also, there are a couple of places where we need to disable BHs to
make sure we have a consistent context to call netif_tx_lock() (since
we no longer can use _irqsave() variants), and we also have to change
ipoib_send_comp_handler() to call drain_tx_cq() through a timer rather
than directly, because ipoib_send_comp_handler() runs in interrupt
context and drain_tx_cq() must run in BH context so it can call
netif_tx_lock().
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/ulp/ipoib/ipoib_cm.c')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_cm.c | 88 |
1 files changed, 52 insertions, 36 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 341ffedafed6..7b14c2c39500 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c | |||
@@ -786,7 +786,8 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) | |||
786 | 786 | ||
787 | dev_kfree_skb_any(tx_req->skb); | 787 | dev_kfree_skb_any(tx_req->skb); |
788 | 788 | ||
789 | spin_lock_irqsave(&priv->tx_lock, flags); | 789 | netif_tx_lock(dev); |
790 | |||
790 | ++tx->tx_tail; | 791 | ++tx->tx_tail; |
791 | if (unlikely(--priv->tx_outstanding == ipoib_sendq_size >> 1) && | 792 | if (unlikely(--priv->tx_outstanding == ipoib_sendq_size >> 1) && |
792 | netif_queue_stopped(dev) && | 793 | netif_queue_stopped(dev) && |
@@ -801,7 +802,7 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) | |||
801 | "(status=%d, wrid=%d vend_err %x)\n", | 802 | "(status=%d, wrid=%d vend_err %x)\n", |
802 | wc->status, wr_id, wc->vendor_err); | 803 | wc->status, wr_id, wc->vendor_err); |
803 | 804 | ||
804 | spin_lock(&priv->lock); | 805 | spin_lock_irqsave(&priv->lock, flags); |
805 | neigh = tx->neigh; | 806 | neigh = tx->neigh; |
806 | 807 | ||
807 | if (neigh) { | 808 | if (neigh) { |
@@ -821,10 +822,10 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) | |||
821 | 822 | ||
822 | clear_bit(IPOIB_FLAG_OPER_UP, &tx->flags); | 823 | clear_bit(IPOIB_FLAG_OPER_UP, &tx->flags); |
823 | 824 | ||
824 | spin_unlock(&priv->lock); | 825 | spin_unlock_irqrestore(&priv->lock, flags); |
825 | } | 826 | } |
826 | 827 | ||
827 | spin_unlock_irqrestore(&priv->tx_lock, flags); | 828 | netif_tx_unlock(dev); |
828 | } | 829 | } |
829 | 830 | ||
830 | int ipoib_cm_dev_open(struct net_device *dev) | 831 | int ipoib_cm_dev_open(struct net_device *dev) |
@@ -1149,7 +1150,6 @@ static void ipoib_cm_tx_destroy(struct ipoib_cm_tx *p) | |||
1149 | { | 1150 | { |
1150 | struct ipoib_dev_priv *priv = netdev_priv(p->dev); | 1151 | struct ipoib_dev_priv *priv = netdev_priv(p->dev); |
1151 | struct ipoib_cm_tx_buf *tx_req; | 1152 | struct ipoib_cm_tx_buf *tx_req; |
1152 | unsigned long flags; | ||
1153 | unsigned long begin; | 1153 | unsigned long begin; |
1154 | 1154 | ||
1155 | ipoib_dbg(priv, "Destroy active connection 0x%x head 0x%x tail 0x%x\n", | 1155 | ipoib_dbg(priv, "Destroy active connection 0x%x head 0x%x tail 0x%x\n", |
@@ -1180,12 +1180,12 @@ timeout: | |||
1180 | DMA_TO_DEVICE); | 1180 | DMA_TO_DEVICE); |
1181 | dev_kfree_skb_any(tx_req->skb); | 1181 | dev_kfree_skb_any(tx_req->skb); |
1182 | ++p->tx_tail; | 1182 | ++p->tx_tail; |
1183 | spin_lock_irqsave(&priv->tx_lock, flags); | 1183 | netif_tx_lock_bh(p->dev); |
1184 | if (unlikely(--priv->tx_outstanding == ipoib_sendq_size >> 1) && | 1184 | if (unlikely(--priv->tx_outstanding == ipoib_sendq_size >> 1) && |
1185 | netif_queue_stopped(p->dev) && | 1185 | netif_queue_stopped(p->dev) && |
1186 | test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) | 1186 | test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) |
1187 | netif_wake_queue(p->dev); | 1187 | netif_wake_queue(p->dev); |
1188 | spin_unlock_irqrestore(&priv->tx_lock, flags); | 1188 | netif_tx_unlock_bh(p->dev); |
1189 | } | 1189 | } |
1190 | 1190 | ||
1191 | if (p->qp) | 1191 | if (p->qp) |
@@ -1202,6 +1202,7 @@ static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id, | |||
1202 | struct ipoib_dev_priv *priv = netdev_priv(tx->dev); | 1202 | struct ipoib_dev_priv *priv = netdev_priv(tx->dev); |
1203 | struct net_device *dev = priv->dev; | 1203 | struct net_device *dev = priv->dev; |
1204 | struct ipoib_neigh *neigh; | 1204 | struct ipoib_neigh *neigh; |
1205 | unsigned long flags; | ||
1205 | int ret; | 1206 | int ret; |
1206 | 1207 | ||
1207 | switch (event->event) { | 1208 | switch (event->event) { |
@@ -1220,8 +1221,8 @@ static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id, | |||
1220 | case IB_CM_REJ_RECEIVED: | 1221 | case IB_CM_REJ_RECEIVED: |
1221 | case IB_CM_TIMEWAIT_EXIT: | 1222 | case IB_CM_TIMEWAIT_EXIT: |
1222 | ipoib_dbg(priv, "CM error %d.\n", event->event); | 1223 | ipoib_dbg(priv, "CM error %d.\n", event->event); |
1223 | spin_lock_irq(&priv->tx_lock); | 1224 | netif_tx_lock_bh(dev); |
1224 | spin_lock(&priv->lock); | 1225 | spin_lock_irqsave(&priv->lock, flags); |
1225 | neigh = tx->neigh; | 1226 | neigh = tx->neigh; |
1226 | 1227 | ||
1227 | if (neigh) { | 1228 | if (neigh) { |
@@ -1239,8 +1240,8 @@ static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id, | |||
1239 | queue_work(ipoib_workqueue, &priv->cm.reap_task); | 1240 | queue_work(ipoib_workqueue, &priv->cm.reap_task); |
1240 | } | 1241 | } |
1241 | 1242 | ||
1242 | spin_unlock(&priv->lock); | 1243 | spin_unlock_irqrestore(&priv->lock, flags); |
1243 | spin_unlock_irq(&priv->tx_lock); | 1244 | netif_tx_unlock_bh(dev); |
1244 | break; | 1245 | break; |
1245 | default: | 1246 | default: |
1246 | break; | 1247 | break; |
@@ -1294,19 +1295,24 @@ static void ipoib_cm_tx_start(struct work_struct *work) | |||
1294 | struct ib_sa_path_rec pathrec; | 1295 | struct ib_sa_path_rec pathrec; |
1295 | u32 qpn; | 1296 | u32 qpn; |
1296 | 1297 | ||
1297 | spin_lock_irqsave(&priv->tx_lock, flags); | 1298 | netif_tx_lock_bh(dev); |
1298 | spin_lock(&priv->lock); | 1299 | spin_lock_irqsave(&priv->lock, flags); |
1300 | |||
1299 | while (!list_empty(&priv->cm.start_list)) { | 1301 | while (!list_empty(&priv->cm.start_list)) { |
1300 | p = list_entry(priv->cm.start_list.next, typeof(*p), list); | 1302 | p = list_entry(priv->cm.start_list.next, typeof(*p), list); |
1301 | list_del_init(&p->list); | 1303 | list_del_init(&p->list); |
1302 | neigh = p->neigh; | 1304 | neigh = p->neigh; |
1303 | qpn = IPOIB_QPN(neigh->neighbour->ha); | 1305 | qpn = IPOIB_QPN(neigh->neighbour->ha); |
1304 | memcpy(&pathrec, &p->path->pathrec, sizeof pathrec); | 1306 | memcpy(&pathrec, &p->path->pathrec, sizeof pathrec); |
1305 | spin_unlock(&priv->lock); | 1307 | |
1306 | spin_unlock_irqrestore(&priv->tx_lock, flags); | 1308 | spin_unlock_irqrestore(&priv->lock, flags); |
1309 | netif_tx_unlock_bh(dev); | ||
1310 | |||
1307 | ret = ipoib_cm_tx_init(p, qpn, &pathrec); | 1311 | ret = ipoib_cm_tx_init(p, qpn, &pathrec); |
1308 | spin_lock_irqsave(&priv->tx_lock, flags); | 1312 | |
1309 | spin_lock(&priv->lock); | 1313 | netif_tx_lock_bh(dev); |
1314 | spin_lock_irqsave(&priv->lock, flags); | ||
1315 | |||
1310 | if (ret) { | 1316 | if (ret) { |
1311 | neigh = p->neigh; | 1317 | neigh = p->neigh; |
1312 | if (neigh) { | 1318 | if (neigh) { |
@@ -1320,44 +1326,52 @@ static void ipoib_cm_tx_start(struct work_struct *work) | |||
1320 | kfree(p); | 1326 | kfree(p); |
1321 | } | 1327 | } |
1322 | } | 1328 | } |
1323 | spin_unlock(&priv->lock); | 1329 | |
1324 | spin_unlock_irqrestore(&priv->tx_lock, flags); | 1330 | spin_unlock_irqrestore(&priv->lock, flags); |
1331 | netif_tx_unlock_bh(dev); | ||
1325 | } | 1332 | } |
1326 | 1333 | ||
1327 | static void ipoib_cm_tx_reap(struct work_struct *work) | 1334 | static void ipoib_cm_tx_reap(struct work_struct *work) |
1328 | { | 1335 | { |
1329 | struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv, | 1336 | struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv, |
1330 | cm.reap_task); | 1337 | cm.reap_task); |
1338 | struct net_device *dev = priv->dev; | ||
1331 | struct ipoib_cm_tx *p; | 1339 | struct ipoib_cm_tx *p; |
1340 | unsigned long flags; | ||
1341 | |||
1342 | netif_tx_lock_bh(dev); | ||
1343 | spin_lock_irqsave(&priv->lock, flags); | ||
1332 | 1344 | ||
1333 | spin_lock_irq(&priv->tx_lock); | ||
1334 | spin_lock(&priv->lock); | ||
1335 | while (!list_empty(&priv->cm.reap_list)) { | 1345 | while (!list_empty(&priv->cm.reap_list)) { |
1336 | p = list_entry(priv->cm.reap_list.next, typeof(*p), list); | 1346 | p = list_entry(priv->cm.reap_list.next, typeof(*p), list); |
1337 | list_del(&p->list); | 1347 | list_del(&p->list); |
1338 | spin_unlock(&priv->lock); | 1348 | spin_unlock_irqrestore(&priv->lock, flags); |
1339 | spin_unlock_irq(&priv->tx_lock); | 1349 | netif_tx_unlock_bh(dev); |
1340 | ipoib_cm_tx_destroy(p); | 1350 | ipoib_cm_tx_destroy(p); |
1341 | spin_lock_irq(&priv->tx_lock); | 1351 | netif_tx_lock_bh(dev); |
1342 | spin_lock(&priv->lock); | 1352 | spin_lock_irqsave(&priv->lock, flags); |
1343 | } | 1353 | } |
1344 | spin_unlock(&priv->lock); | 1354 | |
1345 | spin_unlock_irq(&priv->tx_lock); | 1355 | spin_unlock_irqrestore(&priv->lock, flags); |
1356 | netif_tx_unlock_bh(dev); | ||
1346 | } | 1357 | } |
1347 | 1358 | ||
1348 | static void ipoib_cm_skb_reap(struct work_struct *work) | 1359 | static void ipoib_cm_skb_reap(struct work_struct *work) |
1349 | { | 1360 | { |
1350 | struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv, | 1361 | struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv, |
1351 | cm.skb_task); | 1362 | cm.skb_task); |
1363 | struct net_device *dev = priv->dev; | ||
1352 | struct sk_buff *skb; | 1364 | struct sk_buff *skb; |
1353 | 1365 | unsigned long flags; | |
1354 | unsigned mtu = priv->mcast_mtu; | 1366 | unsigned mtu = priv->mcast_mtu; |
1355 | 1367 | ||
1356 | spin_lock_irq(&priv->tx_lock); | 1368 | netif_tx_lock_bh(dev); |
1357 | spin_lock(&priv->lock); | 1369 | spin_lock_irqsave(&priv->lock, flags); |
1370 | |||
1358 | while ((skb = skb_dequeue(&priv->cm.skb_queue))) { | 1371 | while ((skb = skb_dequeue(&priv->cm.skb_queue))) { |
1359 | spin_unlock(&priv->lock); | 1372 | spin_unlock_irqrestore(&priv->lock, flags); |
1360 | spin_unlock_irq(&priv->tx_lock); | 1373 | netif_tx_unlock_bh(dev); |
1374 | |||
1361 | if (skb->protocol == htons(ETH_P_IP)) | 1375 | if (skb->protocol == htons(ETH_P_IP)) |
1362 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); | 1376 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); |
1363 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 1377 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
@@ -1365,11 +1379,13 @@ static void ipoib_cm_skb_reap(struct work_struct *work) | |||
1365 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, priv->dev); | 1379 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, priv->dev); |
1366 | #endif | 1380 | #endif |
1367 | dev_kfree_skb_any(skb); | 1381 | dev_kfree_skb_any(skb); |
1368 | spin_lock_irq(&priv->tx_lock); | 1382 | |
1369 | spin_lock(&priv->lock); | 1383 | netif_tx_lock_bh(dev); |
1384 | spin_lock_irqsave(&priv->lock, flags); | ||
1370 | } | 1385 | } |
1371 | spin_unlock(&priv->lock); | 1386 | |
1372 | spin_unlock_irq(&priv->tx_lock); | 1387 | spin_unlock_irqrestore(&priv->lock, flags); |
1388 | netif_tx_unlock_bh(dev); | ||
1373 | } | 1389 | } |
1374 | 1390 | ||
1375 | void ipoib_cm_skb_too_long(struct net_device *dev, struct sk_buff *skb, | 1391 | void ipoib_cm_skb_too_long(struct net_device *dev, struct sk_buff *skb, |