diff options
| -rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib.h | 21 | ||||
| -rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_ib.c | 116 | ||||
| -rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_main.c | 8 |
3 files changed, 85 insertions, 60 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 6b14bd1c60a0..c994a916a58a 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h | |||
| @@ -100,7 +100,12 @@ struct ipoib_pseudoheader { | |||
| 100 | 100 | ||
| 101 | struct ipoib_mcast; | 101 | struct ipoib_mcast; |
| 102 | 102 | ||
| 103 | struct ipoib_buf { | 103 | struct ipoib_rx_buf { |
| 104 | struct sk_buff *skb; | ||
| 105 | dma_addr_t mapping; | ||
| 106 | }; | ||
| 107 | |||
| 108 | struct ipoib_tx_buf { | ||
| 104 | struct sk_buff *skb; | 109 | struct sk_buff *skb; |
| 105 | DECLARE_PCI_UNMAP_ADDR(mapping) | 110 | DECLARE_PCI_UNMAP_ADDR(mapping) |
| 106 | }; | 111 | }; |
| @@ -150,14 +155,14 @@ struct ipoib_dev_priv { | |||
| 150 | unsigned int admin_mtu; | 155 | unsigned int admin_mtu; |
| 151 | unsigned int mcast_mtu; | 156 | unsigned int mcast_mtu; |
| 152 | 157 | ||
| 153 | struct ipoib_buf *rx_ring; | 158 | struct ipoib_rx_buf *rx_ring; |
| 154 | 159 | ||
| 155 | spinlock_t tx_lock; | 160 | spinlock_t tx_lock; |
| 156 | struct ipoib_buf *tx_ring; | 161 | struct ipoib_tx_buf *tx_ring; |
| 157 | unsigned tx_head; | 162 | unsigned tx_head; |
| 158 | unsigned tx_tail; | 163 | unsigned tx_tail; |
| 159 | struct ib_sge tx_sge; | 164 | struct ib_sge tx_sge; |
| 160 | struct ib_send_wr tx_wr; | 165 | struct ib_send_wr tx_wr; |
| 161 | 166 | ||
| 162 | struct ib_wc ibwc[IPOIB_NUM_WC]; | 167 | struct ib_wc ibwc[IPOIB_NUM_WC]; |
| 163 | 168 | ||
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 02d0e0006578..192fef884e21 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c | |||
| @@ -95,57 +95,65 @@ void ipoib_free_ah(struct kref *kref) | |||
| 95 | } | 95 | } |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | static inline int ipoib_ib_receive(struct ipoib_dev_priv *priv, | 98 | static int ipoib_ib_post_receive(struct net_device *dev, int id) |
| 99 | unsigned int wr_id, | ||
| 100 | dma_addr_t addr) | ||
| 101 | { | 99 | { |
| 102 | struct ib_sge list = { | 100 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| 103 | .addr = addr, | 101 | struct ib_sge list; |
| 104 | .length = IPOIB_BUF_SIZE, | 102 | struct ib_recv_wr param; |
| 105 | .lkey = priv->mr->lkey, | ||
| 106 | }; | ||
| 107 | struct ib_recv_wr param = { | ||
| 108 | .wr_id = wr_id | IPOIB_OP_RECV, | ||
| 109 | .sg_list = &list, | ||
| 110 | .num_sge = 1, | ||
| 111 | }; | ||
| 112 | struct ib_recv_wr *bad_wr; | 103 | struct ib_recv_wr *bad_wr; |
| 104 | int ret; | ||
| 105 | |||
| 106 | list.addr = priv->rx_ring[id].mapping; | ||
| 107 | list.length = IPOIB_BUF_SIZE; | ||
| 108 | list.lkey = priv->mr->lkey; | ||
| 109 | |||
| 110 | param.next = NULL; | ||
| 111 | param.wr_id = id | IPOIB_OP_RECV; | ||
| 112 | param.sg_list = &list; | ||
| 113 | param.num_sge = 1; | ||
| 114 | |||
| 115 | ret = ib_post_recv(priv->qp, ¶m, &bad_wr); | ||
| 116 | if (unlikely(ret)) { | ||
| 117 | ipoib_warn(priv, "receive failed for buf %d (%d)\n", id, ret); | ||
| 118 | dma_unmap_single(priv->ca->dma_device, | ||
| 119 | priv->rx_ring[id].mapping, | ||
| 120 | IPOIB_BUF_SIZE, DMA_FROM_DEVICE); | ||
| 121 | dev_kfree_skb_any(priv->rx_ring[id].skb); | ||
| 122 | priv->rx_ring[id].skb = NULL; | ||
| 123 | } | ||
| 113 | 124 | ||
| 114 | return ib_post_recv(priv->qp, ¶m, &bad_wr); | 125 | return ret; |
| 115 | } | 126 | } |
| 116 | 127 | ||
| 117 | static int ipoib_ib_post_receive(struct net_device *dev, int id) | 128 | static int ipoib_alloc_rx_skb(struct net_device *dev, int id) |
| 118 | { | 129 | { |
| 119 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 130 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| 120 | struct sk_buff *skb; | 131 | struct sk_buff *skb; |
| 121 | dma_addr_t addr; | 132 | dma_addr_t addr; |
| 122 | int ret; | ||
| 123 | 133 | ||
| 124 | skb = dev_alloc_skb(IPOIB_BUF_SIZE + 4); | 134 | skb = dev_alloc_skb(IPOIB_BUF_SIZE + 4); |
| 125 | if (!skb) { | 135 | if (!skb) |
| 126 | ipoib_warn(priv, "failed to allocate receive buffer\n"); | ||
| 127 | |||
| 128 | priv->rx_ring[id].skb = NULL; | ||
| 129 | return -ENOMEM; | 136 | return -ENOMEM; |
| 130 | } | 137 | |
| 131 | skb_reserve(skb, 4); /* 16 byte align IP header */ | 138 | /* |
| 132 | priv->rx_ring[id].skb = skb; | 139 | * IB will leave a 40 byte gap for a GRH and IPoIB adds a 4 byte |
| 140 | * header. So we need 4 more bytes to get to 48 and align the | ||
| 141 | * IP header to a multiple of 16. | ||
| 142 | */ | ||
| 143 | skb_reserve(skb, 4); | ||
| 144 | |||
| 133 | addr = dma_map_single(priv->ca->dma_device, | 145 | addr = dma_map_single(priv->ca->dma_device, |
| 134 | skb->data, IPOIB_BUF_SIZE, | 146 | skb->data, IPOIB_BUF_SIZE, |
| 135 | DMA_FROM_DEVICE); | 147 | DMA_FROM_DEVICE); |
| 136 | pci_unmap_addr_set(&priv->rx_ring[id], mapping, addr); | 148 | if (unlikely(dma_mapping_error(addr))) { |
| 137 | |||
| 138 | ret = ipoib_ib_receive(priv, id, addr); | ||
| 139 | if (ret) { | ||
| 140 | ipoib_warn(priv, "ipoib_ib_receive failed for buf %d (%d)\n", | ||
| 141 | id, ret); | ||
| 142 | dma_unmap_single(priv->ca->dma_device, addr, | ||
| 143 | IPOIB_BUF_SIZE, DMA_FROM_DEVICE); | ||
| 144 | dev_kfree_skb_any(skb); | 149 | dev_kfree_skb_any(skb); |
| 145 | priv->rx_ring[id].skb = NULL; | 150 | return -EIO; |
| 146 | } | 151 | } |
| 147 | 152 | ||
| 148 | return ret; | 153 | priv->rx_ring[id].skb = skb; |
| 154 | priv->rx_ring[id].mapping = addr; | ||
| 155 | |||
| 156 | return 0; | ||
| 149 | } | 157 | } |
| 150 | 158 | ||
| 151 | static int ipoib_ib_post_receives(struct net_device *dev) | 159 | static int ipoib_ib_post_receives(struct net_device *dev) |
| @@ -154,6 +162,10 @@ static int ipoib_ib_post_receives(struct net_device *dev) | |||
| 154 | int i; | 162 | int i; |
| 155 | 163 | ||
| 156 | for (i = 0; i < IPOIB_RX_RING_SIZE; ++i) { | 164 | for (i = 0; i < IPOIB_RX_RING_SIZE; ++i) { |
| 165 | if (ipoib_alloc_rx_skb(dev, i)) { | ||
| 166 | ipoib_warn(priv, "failed to allocate receive buffer %d\n", i); | ||
| 167 | return -ENOMEM; | ||
| 168 | } | ||
| 157 | if (ipoib_ib_post_receive(dev, i)) { | 169 | if (ipoib_ib_post_receive(dev, i)) { |
| 158 | ipoib_warn(priv, "ipoib_ib_post_receive failed for buf %d\n", i); | 170 | ipoib_warn(priv, "ipoib_ib_post_receive failed for buf %d\n", i); |
| 159 | return -EIO; | 171 | return -EIO; |
| @@ -176,28 +188,36 @@ static void ipoib_ib_handle_wc(struct net_device *dev, | |||
| 176 | wr_id &= ~IPOIB_OP_RECV; | 188 | wr_id &= ~IPOIB_OP_RECV; |
| 177 | 189 | ||
| 178 | if (wr_id < IPOIB_RX_RING_SIZE) { | 190 | if (wr_id < IPOIB_RX_RING_SIZE) { |
| 179 | struct sk_buff *skb = priv->rx_ring[wr_id].skb; | 191 | struct sk_buff *skb = priv->rx_ring[wr_id].skb; |
| 180 | 192 | dma_addr_t addr = priv->rx_ring[wr_id].mapping; | |
| 181 | priv->rx_ring[wr_id].skb = NULL; | ||
| 182 | 193 | ||
| 183 | dma_unmap_single(priv->ca->dma_device, | 194 | if (unlikely(wc->status != IB_WC_SUCCESS)) { |
| 184 | pci_unmap_addr(&priv->rx_ring[wr_id], | ||
| 185 | mapping), | ||
| 186 | IPOIB_BUF_SIZE, | ||
| 187 | DMA_FROM_DEVICE); | ||
| 188 | |||
| 189 | if (wc->status != IB_WC_SUCCESS) { | ||
| 190 | if (wc->status != IB_WC_WR_FLUSH_ERR) | 195 | if (wc->status != IB_WC_WR_FLUSH_ERR) |
| 191 | ipoib_warn(priv, "failed recv event " | 196 | ipoib_warn(priv, "failed recv event " |
| 192 | "(status=%d, wrid=%d vend_err %x)\n", | 197 | "(status=%d, wrid=%d vend_err %x)\n", |
| 193 | wc->status, wr_id, wc->vendor_err); | 198 | wc->status, wr_id, wc->vendor_err); |
| 199 | dma_unmap_single(priv->ca->dma_device, addr, | ||
| 200 | IPOIB_BUF_SIZE, DMA_FROM_DEVICE); | ||
| 194 | dev_kfree_skb_any(skb); | 201 | dev_kfree_skb_any(skb); |
| 202 | priv->rx_ring[wr_id].skb = NULL; | ||
| 195 | return; | 203 | return; |
| 196 | } | 204 | } |
| 197 | 205 | ||
| 206 | /* | ||
| 207 | * If we can't allocate a new RX buffer, dump | ||
| 208 | * this packet and reuse the old buffer. | ||
| 209 | */ | ||
| 210 | if (unlikely(ipoib_alloc_rx_skb(dev, wr_id))) { | ||
| 211 | ++priv->stats.rx_dropped; | ||
| 212 | goto repost; | ||
| 213 | } | ||
| 214 | |||
| 198 | ipoib_dbg_data(priv, "received %d bytes, SLID 0x%04x\n", | 215 | ipoib_dbg_data(priv, "received %d bytes, SLID 0x%04x\n", |
| 199 | wc->byte_len, wc->slid); | 216 | wc->byte_len, wc->slid); |
| 200 | 217 | ||
| 218 | dma_unmap_single(priv->ca->dma_device, addr, | ||
| 219 | IPOIB_BUF_SIZE, DMA_FROM_DEVICE); | ||
| 220 | |||
| 201 | skb_put(skb, wc->byte_len); | 221 | skb_put(skb, wc->byte_len); |
| 202 | skb_pull(skb, IB_GRH_BYTES); | 222 | skb_pull(skb, IB_GRH_BYTES); |
| 203 | 223 | ||
| @@ -220,8 +240,8 @@ static void ipoib_ib_handle_wc(struct net_device *dev, | |||
| 220 | dev_kfree_skb_any(skb); | 240 | dev_kfree_skb_any(skb); |
| 221 | } | 241 | } |
| 222 | 242 | ||
| 223 | /* repost receive */ | 243 | repost: |
| 224 | if (ipoib_ib_post_receive(dev, wr_id)) | 244 | if (unlikely(ipoib_ib_post_receive(dev, wr_id))) |
| 225 | ipoib_warn(priv, "ipoib_ib_post_receive failed " | 245 | ipoib_warn(priv, "ipoib_ib_post_receive failed " |
| 226 | "for buf %d\n", wr_id); | 246 | "for buf %d\n", wr_id); |
| 227 | } else | 247 | } else |
| @@ -229,7 +249,7 @@ static void ipoib_ib_handle_wc(struct net_device *dev, | |||
| 229 | wr_id); | 249 | wr_id); |
| 230 | 250 | ||
| 231 | } else { | 251 | } else { |
| 232 | struct ipoib_buf *tx_req; | 252 | struct ipoib_tx_buf *tx_req; |
| 233 | unsigned long flags; | 253 | unsigned long flags; |
| 234 | 254 | ||
| 235 | if (wr_id >= IPOIB_TX_RING_SIZE) { | 255 | if (wr_id >= IPOIB_TX_RING_SIZE) { |
| @@ -302,7 +322,7 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, | |||
| 302 | struct ipoib_ah *address, u32 qpn) | 322 | struct ipoib_ah *address, u32 qpn) |
| 303 | { | 323 | { |
| 304 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 324 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| 305 | struct ipoib_buf *tx_req; | 325 | struct ipoib_tx_buf *tx_req; |
| 306 | dma_addr_t addr; | 326 | dma_addr_t addr; |
| 307 | 327 | ||
| 308 | if (skb->len > dev->mtu + INFINIBAND_ALEN) { | 328 | if (skb->len > dev->mtu + INFINIBAND_ALEN) { |
| @@ -468,7 +488,7 @@ int ipoib_ib_dev_stop(struct net_device *dev) | |||
| 468 | struct ib_qp_attr qp_attr; | 488 | struct ib_qp_attr qp_attr; |
| 469 | int attr_mask; | 489 | int attr_mask; |
| 470 | unsigned long begin; | 490 | unsigned long begin; |
| 471 | struct ipoib_buf *tx_req; | 491 | struct ipoib_tx_buf *tx_req; |
| 472 | int i; | 492 | int i; |
| 473 | 493 | ||
| 474 | /* Kill the existing QP and allocate a new one */ | 494 | /* Kill the existing QP and allocate a new one */ |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index ee303859b044..cd4f42328dbe 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
| @@ -732,7 +732,7 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port) | |||
| 732 | 732 | ||
| 733 | /* Allocate RX/TX "rings" to hold queued skbs */ | 733 | /* Allocate RX/TX "rings" to hold queued skbs */ |
| 734 | 734 | ||
| 735 | priv->rx_ring = kmalloc(IPOIB_RX_RING_SIZE * sizeof (struct ipoib_buf), | 735 | priv->rx_ring = kmalloc(IPOIB_RX_RING_SIZE * sizeof (struct ipoib_rx_buf), |
| 736 | GFP_KERNEL); | 736 | GFP_KERNEL); |
| 737 | if (!priv->rx_ring) { | 737 | if (!priv->rx_ring) { |
| 738 | printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n", | 738 | printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n", |
| @@ -740,9 +740,9 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port) | |||
| 740 | goto out; | 740 | goto out; |
| 741 | } | 741 | } |
| 742 | memset(priv->rx_ring, 0, | 742 | memset(priv->rx_ring, 0, |
| 743 | IPOIB_RX_RING_SIZE * sizeof (struct ipoib_buf)); | 743 | IPOIB_RX_RING_SIZE * sizeof (struct ipoib_rx_buf)); |
| 744 | 744 | ||
| 745 | priv->tx_ring = kmalloc(IPOIB_TX_RING_SIZE * sizeof (struct ipoib_buf), | 745 | priv->tx_ring = kmalloc(IPOIB_TX_RING_SIZE * sizeof (struct ipoib_tx_buf), |
| 746 | GFP_KERNEL); | 746 | GFP_KERNEL); |
| 747 | if (!priv->tx_ring) { | 747 | if (!priv->tx_ring) { |
| 748 | printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n", | 748 | printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n", |
| @@ -750,7 +750,7 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port) | |||
| 750 | goto out_rx_ring_cleanup; | 750 | goto out_rx_ring_cleanup; |
| 751 | } | 751 | } |
| 752 | memset(priv->tx_ring, 0, | 752 | memset(priv->tx_ring, 0, |
| 753 | IPOIB_TX_RING_SIZE * sizeof (struct ipoib_buf)); | 753 | IPOIB_TX_RING_SIZE * sizeof (struct ipoib_tx_buf)); |
| 754 | 754 | ||
| 755 | /* priv->tx_head & tx_tail are already 0 */ | 755 | /* priv->tx_head & tx_tail are already 0 */ |
| 756 | 756 | ||
