aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h21
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c116
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c8
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
101struct ipoib_mcast; 101struct ipoib_mcast;
102 102
103struct ipoib_buf { 103struct ipoib_rx_buf {
104 struct sk_buff *skb;
105 dma_addr_t mapping;
106};
107
108struct 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
98static inline int ipoib_ib_receive(struct ipoib_dev_priv *priv, 98static 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, &param, &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, &param, &bad_wr); 125 return ret;
115} 126}
116 127
117static int ipoib_ib_post_receive(struct net_device *dev, int id) 128static 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
151static int ipoib_ib_post_receives(struct net_device *dev) 159static 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