diff options
Diffstat (limited to 'drivers/infiniband')
-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 | ||