diff options
author | Ben Dooks <ben-linux@fluff.org> | 2008-07-15 15:19:14 -0400 |
---|---|---|
committer | Ben Dooks <ben-linux@fluff.org> | 2008-07-15 15:19:14 -0400 |
commit | 0c17e4ceedd35c78b1c7413dbd16279a350be6bc (patch) | |
tree | 313b3b9ca04727f3704464e01d8dd97da1dd534b /drivers/infiniband/ulp/ipoib/ipoib_cm.c | |
parent | 19c1d6a34abf73d0baf8e325d018c920fa78dddc (diff) | |
parent | b9d2252c1e44fa83a4e65fdc9eb93db6297c55af (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into for-rmk
Diffstat (limited to 'drivers/infiniband/ulp/ipoib/ipoib_cm.c')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_cm.c | 104 |
1 files changed, 78 insertions, 26 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 97e67d36378f..0f2d3045061a 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c | |||
@@ -28,8 +28,6 @@ | |||
28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | 28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
30 | * SOFTWARE. | 30 | * SOFTWARE. |
31 | * | ||
32 | * $Id$ | ||
33 | */ | 31 | */ |
34 | 32 | ||
35 | #include <rdma/ib_cm.h> | 33 | #include <rdma/ib_cm.h> |
@@ -113,18 +111,20 @@ static int ipoib_cm_post_receive_srq(struct net_device *dev, int id) | |||
113 | } | 111 | } |
114 | 112 | ||
115 | static int ipoib_cm_post_receive_nonsrq(struct net_device *dev, | 113 | static int ipoib_cm_post_receive_nonsrq(struct net_device *dev, |
116 | struct ipoib_cm_rx *rx, int id) | 114 | struct ipoib_cm_rx *rx, |
115 | struct ib_recv_wr *wr, | ||
116 | struct ib_sge *sge, int id) | ||
117 | { | 117 | { |
118 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 118 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
119 | struct ib_recv_wr *bad_wr; | 119 | struct ib_recv_wr *bad_wr; |
120 | int i, ret; | 120 | int i, ret; |
121 | 121 | ||
122 | priv->cm.rx_wr.wr_id = id | IPOIB_OP_CM | IPOIB_OP_RECV; | 122 | wr->wr_id = id | IPOIB_OP_CM | IPOIB_OP_RECV; |
123 | 123 | ||
124 | for (i = 0; i < IPOIB_CM_RX_SG; ++i) | 124 | for (i = 0; i < IPOIB_CM_RX_SG; ++i) |
125 | priv->cm.rx_sge[i].addr = rx->rx_ring[id].mapping[i]; | 125 | sge[i].addr = rx->rx_ring[id].mapping[i]; |
126 | 126 | ||
127 | ret = ib_post_recv(rx->qp, &priv->cm.rx_wr, &bad_wr); | 127 | ret = ib_post_recv(rx->qp, wr, &bad_wr); |
128 | if (unlikely(ret)) { | 128 | if (unlikely(ret)) { |
129 | ipoib_warn(priv, "post recv failed for buf %d (%d)\n", id, ret); | 129 | ipoib_warn(priv, "post recv failed for buf %d (%d)\n", id, ret); |
130 | ipoib_cm_dma_unmap_rx(priv, IPOIB_CM_RX_SG - 1, | 130 | ipoib_cm_dma_unmap_rx(priv, IPOIB_CM_RX_SG - 1, |
@@ -322,10 +322,33 @@ static int ipoib_cm_modify_rx_qp(struct net_device *dev, | |||
322 | return 0; | 322 | return 0; |
323 | } | 323 | } |
324 | 324 | ||
325 | static void ipoib_cm_init_rx_wr(struct net_device *dev, | ||
326 | struct ib_recv_wr *wr, | ||
327 | struct ib_sge *sge) | ||
328 | { | ||
329 | struct ipoib_dev_priv *priv = netdev_priv(dev); | ||
330 | int i; | ||
331 | |||
332 | for (i = 0; i < priv->cm.num_frags; ++i) | ||
333 | sge[i].lkey = priv->mr->lkey; | ||
334 | |||
335 | sge[0].length = IPOIB_CM_HEAD_SIZE; | ||
336 | for (i = 1; i < priv->cm.num_frags; ++i) | ||
337 | sge[i].length = PAGE_SIZE; | ||
338 | |||
339 | wr->next = NULL; | ||
340 | wr->sg_list = priv->cm.rx_sge; | ||
341 | wr->num_sge = priv->cm.num_frags; | ||
342 | } | ||
343 | |||
325 | static int ipoib_cm_nonsrq_init_rx(struct net_device *dev, struct ib_cm_id *cm_id, | 344 | static int ipoib_cm_nonsrq_init_rx(struct net_device *dev, struct ib_cm_id *cm_id, |
326 | struct ipoib_cm_rx *rx) | 345 | struct ipoib_cm_rx *rx) |
327 | { | 346 | { |
328 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 347 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
348 | struct { | ||
349 | struct ib_recv_wr wr; | ||
350 | struct ib_sge sge[IPOIB_CM_RX_SG]; | ||
351 | } *t; | ||
329 | int ret; | 352 | int ret; |
330 | int i; | 353 | int i; |
331 | 354 | ||
@@ -333,6 +356,14 @@ static int ipoib_cm_nonsrq_init_rx(struct net_device *dev, struct ib_cm_id *cm_i | |||
333 | if (!rx->rx_ring) | 356 | if (!rx->rx_ring) |
334 | return -ENOMEM; | 357 | return -ENOMEM; |
335 | 358 | ||
359 | t = kmalloc(sizeof *t, GFP_KERNEL); | ||
360 | if (!t) { | ||
361 | ret = -ENOMEM; | ||
362 | goto err_free; | ||
363 | } | ||
364 | |||
365 | ipoib_cm_init_rx_wr(dev, &t->wr, t->sge); | ||
366 | |||
336 | spin_lock_irq(&priv->lock); | 367 | spin_lock_irq(&priv->lock); |
337 | 368 | ||
338 | if (priv->cm.nonsrq_conn_qp >= ipoib_max_conn_qp) { | 369 | if (priv->cm.nonsrq_conn_qp >= ipoib_max_conn_qp) { |
@@ -351,8 +382,8 @@ static int ipoib_cm_nonsrq_init_rx(struct net_device *dev, struct ib_cm_id *cm_i | |||
351 | ipoib_warn(priv, "failed to allocate receive buffer %d\n", i); | 382 | ipoib_warn(priv, "failed to allocate receive buffer %d\n", i); |
352 | ret = -ENOMEM; | 383 | ret = -ENOMEM; |
353 | goto err_count; | 384 | goto err_count; |
354 | } | 385 | } |
355 | ret = ipoib_cm_post_receive_nonsrq(dev, rx, i); | 386 | ret = ipoib_cm_post_receive_nonsrq(dev, rx, &t->wr, t->sge, i); |
356 | if (ret) { | 387 | if (ret) { |
357 | ipoib_warn(priv, "ipoib_cm_post_receive_nonsrq " | 388 | ipoib_warn(priv, "ipoib_cm_post_receive_nonsrq " |
358 | "failed for buf %d\n", i); | 389 | "failed for buf %d\n", i); |
@@ -363,6 +394,8 @@ static int ipoib_cm_nonsrq_init_rx(struct net_device *dev, struct ib_cm_id *cm_i | |||
363 | 394 | ||
364 | rx->recv_count = ipoib_recvq_size; | 395 | rx->recv_count = ipoib_recvq_size; |
365 | 396 | ||
397 | kfree(t); | ||
398 | |||
366 | return 0; | 399 | return 0; |
367 | 400 | ||
368 | err_count: | 401 | err_count: |
@@ -371,6 +404,7 @@ err_count: | |||
371 | spin_unlock_irq(&priv->lock); | 404 | spin_unlock_irq(&priv->lock); |
372 | 405 | ||
373 | err_free: | 406 | err_free: |
407 | kfree(t); | ||
374 | ipoib_cm_free_rx_ring(dev, rx->rx_ring); | 408 | ipoib_cm_free_rx_ring(dev, rx->rx_ring); |
375 | 409 | ||
376 | return ret; | 410 | return ret; |
@@ -525,6 +559,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) | |||
525 | u64 mapping[IPOIB_CM_RX_SG]; | 559 | u64 mapping[IPOIB_CM_RX_SG]; |
526 | int frags; | 560 | int frags; |
527 | int has_srq; | 561 | int has_srq; |
562 | struct sk_buff *small_skb; | ||
528 | 563 | ||
529 | ipoib_dbg_data(priv, "cm recv completion: id %d, status: %d\n", | 564 | ipoib_dbg_data(priv, "cm recv completion: id %d, status: %d\n", |
530 | wr_id, wc->status); | 565 | wr_id, wc->status); |
@@ -579,6 +614,23 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) | |||
579 | } | 614 | } |
580 | } | 615 | } |
581 | 616 | ||
617 | if (wc->byte_len < IPOIB_CM_COPYBREAK) { | ||
618 | int dlen = wc->byte_len; | ||
619 | |||
620 | small_skb = dev_alloc_skb(dlen + 12); | ||
621 | if (small_skb) { | ||
622 | skb_reserve(small_skb, 12); | ||
623 | ib_dma_sync_single_for_cpu(priv->ca, rx_ring[wr_id].mapping[0], | ||
624 | dlen, DMA_FROM_DEVICE); | ||
625 | skb_copy_from_linear_data(skb, small_skb->data, dlen); | ||
626 | ib_dma_sync_single_for_device(priv->ca, rx_ring[wr_id].mapping[0], | ||
627 | dlen, DMA_FROM_DEVICE); | ||
628 | skb_put(small_skb, dlen); | ||
629 | skb = small_skb; | ||
630 | goto copied; | ||
631 | } | ||
632 | } | ||
633 | |||
582 | frags = PAGE_ALIGN(wc->byte_len - min(wc->byte_len, | 634 | frags = PAGE_ALIGN(wc->byte_len - min(wc->byte_len, |
583 | (unsigned)IPOIB_CM_HEAD_SIZE)) / PAGE_SIZE; | 635 | (unsigned)IPOIB_CM_HEAD_SIZE)) / PAGE_SIZE; |
584 | 636 | ||
@@ -601,6 +653,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) | |||
601 | 653 | ||
602 | skb_put_frags(skb, IPOIB_CM_HEAD_SIZE, wc->byte_len, newskb); | 654 | skb_put_frags(skb, IPOIB_CM_HEAD_SIZE, wc->byte_len, newskb); |
603 | 655 | ||
656 | copied: | ||
604 | skb->protocol = ((struct ipoib_header *) skb->data)->proto; | 657 | skb->protocol = ((struct ipoib_header *) skb->data)->proto; |
605 | skb_reset_mac_header(skb); | 658 | skb_reset_mac_header(skb); |
606 | skb_pull(skb, IPOIB_ENCAP_LEN); | 659 | skb_pull(skb, IPOIB_ENCAP_LEN); |
@@ -620,7 +673,10 @@ repost: | |||
620 | ipoib_warn(priv, "ipoib_cm_post_receive_srq failed " | 673 | ipoib_warn(priv, "ipoib_cm_post_receive_srq failed " |
621 | "for buf %d\n", wr_id); | 674 | "for buf %d\n", wr_id); |
622 | } else { | 675 | } else { |
623 | if (unlikely(ipoib_cm_post_receive_nonsrq(dev, p, wr_id))) { | 676 | if (unlikely(ipoib_cm_post_receive_nonsrq(dev, p, |
677 | &priv->cm.rx_wr, | ||
678 | priv->cm.rx_sge, | ||
679 | wr_id))) { | ||
624 | --p->recv_count; | 680 | --p->recv_count; |
625 | ipoib_warn(priv, "ipoib_cm_post_receive_nonsrq failed " | 681 | ipoib_warn(priv, "ipoib_cm_post_receive_nonsrq failed " |
626 | "for buf %d\n", wr_id); | 682 | "for buf %d\n", wr_id); |
@@ -647,7 +703,7 @@ static inline int post_send(struct ipoib_dev_priv *priv, | |||
647 | void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_tx *tx) | 703 | void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_tx *tx) |
648 | { | 704 | { |
649 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 705 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
650 | struct ipoib_tx_buf *tx_req; | 706 | struct ipoib_cm_tx_buf *tx_req; |
651 | u64 addr; | 707 | u64 addr; |
652 | 708 | ||
653 | if (unlikely(skb->len > tx->mtu)) { | 709 | if (unlikely(skb->len > tx->mtu)) { |
@@ -678,7 +734,7 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_ | |||
678 | return; | 734 | return; |
679 | } | 735 | } |
680 | 736 | ||
681 | tx_req->mapping[0] = addr; | 737 | tx_req->mapping = addr; |
682 | 738 | ||
683 | if (unlikely(post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1), | 739 | if (unlikely(post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1), |
684 | addr, skb->len))) { | 740 | addr, skb->len))) { |
@@ -703,7 +759,7 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) | |||
703 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 759 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
704 | struct ipoib_cm_tx *tx = wc->qp->qp_context; | 760 | struct ipoib_cm_tx *tx = wc->qp->qp_context; |
705 | unsigned int wr_id = wc->wr_id & ~IPOIB_OP_CM; | 761 | unsigned int wr_id = wc->wr_id & ~IPOIB_OP_CM; |
706 | struct ipoib_tx_buf *tx_req; | 762 | struct ipoib_cm_tx_buf *tx_req; |
707 | unsigned long flags; | 763 | unsigned long flags; |
708 | 764 | ||
709 | ipoib_dbg_data(priv, "cm send completion: id %d, status: %d\n", | 765 | ipoib_dbg_data(priv, "cm send completion: id %d, status: %d\n", |
@@ -717,7 +773,7 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) | |||
717 | 773 | ||
718 | tx_req = &tx->tx_ring[wr_id]; | 774 | tx_req = &tx->tx_ring[wr_id]; |
719 | 775 | ||
720 | ib_dma_unmap_single(priv->ca, tx_req->mapping[0], tx_req->skb->len, DMA_TO_DEVICE); | 776 | ib_dma_unmap_single(priv->ca, tx_req->mapping, tx_req->skb->len, DMA_TO_DEVICE); |
721 | 777 | ||
722 | /* FIXME: is this right? Shouldn't we only increment on success? */ | 778 | /* FIXME: is this right? Shouldn't we only increment on success? */ |
723 | ++dev->stats.tx_packets; | 779 | ++dev->stats.tx_packets; |
@@ -1087,7 +1143,7 @@ err_tx: | |||
1087 | static void ipoib_cm_tx_destroy(struct ipoib_cm_tx *p) | 1143 | static void ipoib_cm_tx_destroy(struct ipoib_cm_tx *p) |
1088 | { | 1144 | { |
1089 | struct ipoib_dev_priv *priv = netdev_priv(p->dev); | 1145 | struct ipoib_dev_priv *priv = netdev_priv(p->dev); |
1090 | struct ipoib_tx_buf *tx_req; | 1146 | struct ipoib_cm_tx_buf *tx_req; |
1091 | unsigned long flags; | 1147 | unsigned long flags; |
1092 | unsigned long begin; | 1148 | unsigned long begin; |
1093 | 1149 | ||
@@ -1115,7 +1171,7 @@ timeout: | |||
1115 | 1171 | ||
1116 | while ((int) p->tx_tail - (int) p->tx_head < 0) { | 1172 | while ((int) p->tx_tail - (int) p->tx_head < 0) { |
1117 | tx_req = &p->tx_ring[p->tx_tail & (ipoib_sendq_size - 1)]; | 1173 | tx_req = &p->tx_ring[p->tx_tail & (ipoib_sendq_size - 1)]; |
1118 | ib_dma_unmap_single(priv->ca, tx_req->mapping[0], tx_req->skb->len, | 1174 | ib_dma_unmap_single(priv->ca, tx_req->mapping, tx_req->skb->len, |
1119 | DMA_TO_DEVICE); | 1175 | DMA_TO_DEVICE); |
1120 | dev_kfree_skb_any(tx_req->skb); | 1176 | dev_kfree_skb_any(tx_req->skb); |
1121 | ++p->tx_tail; | 1177 | ++p->tx_tail; |
@@ -1384,7 +1440,9 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr, | |||
1384 | ipoib_warn(priv, "enabling connected mode " | 1440 | ipoib_warn(priv, "enabling connected mode " |
1385 | "will cause multicast packet drops\n"); | 1441 | "will cause multicast packet drops\n"); |
1386 | 1442 | ||
1443 | rtnl_lock(); | ||
1387 | dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO); | 1444 | dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO); |
1445 | rtnl_unlock(); | ||
1388 | priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; | 1446 | priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; |
1389 | 1447 | ||
1390 | ipoib_flush_paths(dev); | 1448 | ipoib_flush_paths(dev); |
@@ -1393,14 +1451,16 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr, | |||
1393 | 1451 | ||
1394 | if (!strcmp(buf, "datagram\n")) { | 1452 | if (!strcmp(buf, "datagram\n")) { |
1395 | clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); | 1453 | clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); |
1396 | dev->mtu = min(priv->mcast_mtu, dev->mtu); | ||
1397 | ipoib_flush_paths(dev); | ||
1398 | 1454 | ||
1455 | rtnl_lock(); | ||
1399 | if (test_bit(IPOIB_FLAG_CSUM, &priv->flags)) { | 1456 | if (test_bit(IPOIB_FLAG_CSUM, &priv->flags)) { |
1400 | dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; | 1457 | dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; |
1401 | if (priv->hca_caps & IB_DEVICE_UD_TSO) | 1458 | if (priv->hca_caps & IB_DEVICE_UD_TSO) |
1402 | dev->features |= NETIF_F_TSO; | 1459 | dev->features |= NETIF_F_TSO; |
1403 | } | 1460 | } |
1461 | dev_set_mtu(dev, min(priv->mcast_mtu, dev->mtu)); | ||
1462 | rtnl_unlock(); | ||
1463 | ipoib_flush_paths(dev); | ||
1404 | 1464 | ||
1405 | return count; | 1465 | return count; |
1406 | } | 1466 | } |
@@ -1485,15 +1545,7 @@ int ipoib_cm_dev_init(struct net_device *dev) | |||
1485 | priv->cm.num_frags = IPOIB_CM_RX_SG; | 1545 | priv->cm.num_frags = IPOIB_CM_RX_SG; |
1486 | } | 1546 | } |
1487 | 1547 | ||
1488 | for (i = 0; i < priv->cm.num_frags; ++i) | 1548 | ipoib_cm_init_rx_wr(dev, &priv->cm.rx_wr, priv->cm.rx_sge); |
1489 | priv->cm.rx_sge[i].lkey = priv->mr->lkey; | ||
1490 | |||
1491 | priv->cm.rx_sge[0].length = IPOIB_CM_HEAD_SIZE; | ||
1492 | for (i = 1; i < priv->cm.num_frags; ++i) | ||
1493 | priv->cm.rx_sge[i].length = PAGE_SIZE; | ||
1494 | priv->cm.rx_wr.next = NULL; | ||
1495 | priv->cm.rx_wr.sg_list = priv->cm.rx_sge; | ||
1496 | priv->cm.rx_wr.num_sge = priv->cm.num_frags; | ||
1497 | 1549 | ||
1498 | if (ipoib_cm_has_srq(dev)) { | 1550 | if (ipoib_cm_has_srq(dev)) { |
1499 | for (i = 0; i < ipoib_recvq_size; ++i) { | 1551 | for (i = 0; i < ipoib_recvq_size; ++i) { |