diff options
Diffstat (limited to 'drivers/infiniband/ulp')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/Makefile | 3 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib.h | 10 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_cm.c | 15 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_ethtool.c | 99 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_ib.c | 126 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_main.c | 33 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_verbs.c | 3 | ||||
-rw-r--r-- | drivers/infiniband/ulp/iser/iser_initiator.c | 4 | ||||
-rw-r--r-- | drivers/infiniband/ulp/iser/iser_verbs.c | 5 | ||||
-rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.c | 7 |
10 files changed, 256 insertions, 49 deletions
diff --git a/drivers/infiniband/ulp/ipoib/Makefile b/drivers/infiniband/ulp/ipoib/Makefile index 98ee38e8c2c4..3090100f0de7 100644 --- a/drivers/infiniband/ulp/ipoib/Makefile +++ b/drivers/infiniband/ulp/ipoib/Makefile | |||
@@ -4,7 +4,8 @@ ib_ipoib-y := ipoib_main.o \ | |||
4 | ipoib_ib.o \ | 4 | ipoib_ib.o \ |
5 | ipoib_multicast.o \ | 5 | ipoib_multicast.o \ |
6 | ipoib_verbs.o \ | 6 | ipoib_verbs.o \ |
7 | ipoib_vlan.o | 7 | ipoib_vlan.o \ |
8 | ipoib_ethtool.o | ||
8 | ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_CM) += ipoib_cm.o | 9 | ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_CM) += ipoib_cm.o |
9 | ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_DEBUG) += ipoib_fs.o | 10 | ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_DEBUG) += ipoib_fs.o |
10 | 11 | ||
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 054fab8e27a0..73b2b176ad0e 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h | |||
@@ -87,6 +87,7 @@ enum { | |||
87 | IPOIB_MCAST_STARTED = 8, | 87 | IPOIB_MCAST_STARTED = 8, |
88 | IPOIB_FLAG_ADMIN_CM = 9, | 88 | IPOIB_FLAG_ADMIN_CM = 9, |
89 | IPOIB_FLAG_UMCAST = 10, | 89 | IPOIB_FLAG_UMCAST = 10, |
90 | IPOIB_FLAG_CSUM = 11, | ||
90 | 91 | ||
91 | IPOIB_MAX_BACKOFF_SECONDS = 16, | 92 | IPOIB_MAX_BACKOFF_SECONDS = 16, |
92 | 93 | ||
@@ -241,6 +242,11 @@ struct ipoib_cm_dev_priv { | |||
241 | int num_frags; | 242 | int num_frags; |
242 | }; | 243 | }; |
243 | 244 | ||
245 | struct ipoib_ethtool_st { | ||
246 | u16 coalesce_usecs; | ||
247 | u16 max_coalesced_frames; | ||
248 | }; | ||
249 | |||
244 | /* | 250 | /* |
245 | * Device private locking: tx_lock protects members used in TX fast | 251 | * Device private locking: tx_lock protects members used in TX fast |
246 | * path (and we use LLTX so upper layers don't do extra locking). | 252 | * path (and we use LLTX so upper layers don't do extra locking). |
@@ -318,6 +324,8 @@ struct ipoib_dev_priv { | |||
318 | struct dentry *mcg_dentry; | 324 | struct dentry *mcg_dentry; |
319 | struct dentry *path_dentry; | 325 | struct dentry *path_dentry; |
320 | #endif | 326 | #endif |
327 | int hca_caps; | ||
328 | struct ipoib_ethtool_st ethtool; | ||
321 | }; | 329 | }; |
322 | 330 | ||
323 | struct ipoib_ah { | 331 | struct ipoib_ah { |
@@ -458,6 +466,8 @@ void ipoib_pkey_poll(struct work_struct *work); | |||
458 | int ipoib_pkey_dev_delay_open(struct net_device *dev); | 466 | int ipoib_pkey_dev_delay_open(struct net_device *dev); |
459 | void ipoib_drain_cq(struct net_device *dev); | 467 | void ipoib_drain_cq(struct net_device *dev); |
460 | 468 | ||
469 | void ipoib_set_ethtool_ops(struct net_device *dev); | ||
470 | |||
461 | #ifdef CONFIG_INFINIBAND_IPOIB_CM | 471 | #ifdef CONFIG_INFINIBAND_IPOIB_CM |
462 | 472 | ||
463 | #define IPOIB_FLAGS_RC 0x80 | 473 | #define IPOIB_FLAGS_RC 0x80 |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 2490b2d79dbb..9db7b0bd9134 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c | |||
@@ -1007,9 +1007,9 @@ static int ipoib_cm_modify_tx_init(struct net_device *dev, | |||
1007 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 1007 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
1008 | struct ib_qp_attr qp_attr; | 1008 | struct ib_qp_attr qp_attr; |
1009 | int qp_attr_mask, ret; | 1009 | int qp_attr_mask, ret; |
1010 | ret = ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &qp_attr.pkey_index); | 1010 | ret = ib_find_pkey(priv->ca, priv->port, priv->pkey, &qp_attr.pkey_index); |
1011 | if (ret) { | 1011 | if (ret) { |
1012 | ipoib_warn(priv, "pkey 0x%x not in cache: %d\n", priv->pkey, ret); | 1012 | ipoib_warn(priv, "pkey 0x%x not found: %d\n", priv->pkey, ret); |
1013 | return ret; | 1013 | return ret; |
1014 | } | 1014 | } |
1015 | 1015 | ||
@@ -1383,6 +1383,10 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr, | |||
1383 | set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); | 1383 | set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); |
1384 | ipoib_warn(priv, "enabling connected mode " | 1384 | ipoib_warn(priv, "enabling connected mode " |
1385 | "will cause multicast packet drops\n"); | 1385 | "will cause multicast packet drops\n"); |
1386 | |||
1387 | dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO); | ||
1388 | priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; | ||
1389 | |||
1386 | ipoib_flush_paths(dev); | 1390 | ipoib_flush_paths(dev); |
1387 | return count; | 1391 | return count; |
1388 | } | 1392 | } |
@@ -1391,6 +1395,13 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr, | |||
1391 | clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); | 1395 | clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); |
1392 | dev->mtu = min(priv->mcast_mtu, dev->mtu); | 1396 | dev->mtu = min(priv->mcast_mtu, dev->mtu); |
1393 | ipoib_flush_paths(dev); | 1397 | ipoib_flush_paths(dev); |
1398 | |||
1399 | if (test_bit(IPOIB_FLAG_CSUM, &priv->flags)) { | ||
1400 | dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; | ||
1401 | if (priv->hca_caps & IB_DEVICE_UD_TSO) | ||
1402 | dev->features |= NETIF_F_TSO; | ||
1403 | } | ||
1404 | |||
1394 | return count; | 1405 | return count; |
1395 | } | 1406 | } |
1396 | 1407 | ||
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c new file mode 100644 index 000000000000..9a47428366c9 --- /dev/null +++ b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2007 Mellanox Technologies. All rights reserved. | ||
3 | * | ||
4 | * This software is available to you under a choice of one of two | ||
5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
6 | * General Public License (GPL) Version 2, available from the file | ||
7 | * COPYING in the main directory of this source tree, or the | ||
8 | * OpenIB.org BSD license below: | ||
9 | * | ||
10 | * Redistribution and use in source and binary forms, with or | ||
11 | * without modification, are permitted provided that the following | ||
12 | * conditions are met: | ||
13 | * | ||
14 | * - Redistributions of source code must retain the above | ||
15 | * copyright notice, this list of conditions and the following | ||
16 | * disclaimer. | ||
17 | * | ||
18 | * - Redistributions in binary form must reproduce the above | ||
19 | * copyright notice, this list of conditions and the following | ||
20 | * disclaimer in the documentation and/or other materials | ||
21 | * provided with the distribution. | ||
22 | * | ||
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
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 | ||
30 | * SOFTWARE. | ||
31 | */ | ||
32 | |||
33 | #include <linux/kernel.h> | ||
34 | #include <linux/ethtool.h> | ||
35 | #include <linux/netdevice.h> | ||
36 | |||
37 | #include "ipoib.h" | ||
38 | |||
39 | static void ipoib_get_drvinfo(struct net_device *netdev, | ||
40 | struct ethtool_drvinfo *drvinfo) | ||
41 | { | ||
42 | strncpy(drvinfo->driver, "ipoib", sizeof(drvinfo->driver) - 1); | ||
43 | } | ||
44 | |||
45 | static int ipoib_get_coalesce(struct net_device *dev, | ||
46 | struct ethtool_coalesce *coal) | ||
47 | { | ||
48 | struct ipoib_dev_priv *priv = netdev_priv(dev); | ||
49 | |||
50 | coal->rx_coalesce_usecs = priv->ethtool.coalesce_usecs; | ||
51 | coal->tx_coalesce_usecs = priv->ethtool.coalesce_usecs; | ||
52 | coal->rx_max_coalesced_frames = priv->ethtool.max_coalesced_frames; | ||
53 | coal->tx_max_coalesced_frames = priv->ethtool.max_coalesced_frames; | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static int ipoib_set_coalesce(struct net_device *dev, | ||
59 | struct ethtool_coalesce *coal) | ||
60 | { | ||
61 | struct ipoib_dev_priv *priv = netdev_priv(dev); | ||
62 | int ret; | ||
63 | |||
64 | /* | ||
65 | * Since IPoIB uses a single CQ for both rx and tx, we assume | ||
66 | * that rx params dictate the configuration. These values are | ||
67 | * saved in the private data and returned when ipoib_get_coalesce() | ||
68 | * is called. | ||
69 | */ | ||
70 | if (coal->rx_coalesce_usecs > 0xffff || | ||
71 | coal->rx_max_coalesced_frames > 0xffff) | ||
72 | return -EINVAL; | ||
73 | |||
74 | ret = ib_modify_cq(priv->cq, coal->rx_max_coalesced_frames, | ||
75 | coal->rx_coalesce_usecs); | ||
76 | if (ret && ret != -ENOSYS) { | ||
77 | ipoib_warn(priv, "failed modifying CQ (%d)\n", ret); | ||
78 | return ret; | ||
79 | } | ||
80 | |||
81 | coal->tx_coalesce_usecs = coal->rx_coalesce_usecs; | ||
82 | coal->tx_max_coalesced_frames = coal->rx_max_coalesced_frames; | ||
83 | priv->ethtool.coalesce_usecs = coal->rx_coalesce_usecs; | ||
84 | priv->ethtool.max_coalesced_frames = coal->rx_max_coalesced_frames; | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static const struct ethtool_ops ipoib_ethtool_ops = { | ||
90 | .get_drvinfo = ipoib_get_drvinfo, | ||
91 | .get_tso = ethtool_op_get_tso, | ||
92 | .get_coalesce = ipoib_get_coalesce, | ||
93 | .set_coalesce = ipoib_set_coalesce, | ||
94 | }; | ||
95 | |||
96 | void ipoib_set_ethtool_ops(struct net_device *dev) | ||
97 | { | ||
98 | SET_ETHTOOL_OPS(dev, &ipoib_ethtool_ops); | ||
99 | } | ||
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 08c4396cf418..0205eb7c1bd3 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c | |||
@@ -39,6 +39,8 @@ | |||
39 | #include <linux/dma-mapping.h> | 39 | #include <linux/dma-mapping.h> |
40 | 40 | ||
41 | #include <rdma/ib_cache.h> | 41 | #include <rdma/ib_cache.h> |
42 | #include <linux/ip.h> | ||
43 | #include <linux/tcp.h> | ||
42 | 44 | ||
43 | #include "ipoib.h" | 45 | #include "ipoib.h" |
44 | 46 | ||
@@ -231,6 +233,10 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) | |||
231 | skb->dev = dev; | 233 | skb->dev = dev; |
232 | /* XXX get correct PACKET_ type here */ | 234 | /* XXX get correct PACKET_ type here */ |
233 | skb->pkt_type = PACKET_HOST; | 235 | skb->pkt_type = PACKET_HOST; |
236 | |||
237 | if (test_bit(IPOIB_FLAG_CSUM, &priv->flags) && likely(wc->csum_ok)) | ||
238 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
239 | |||
234 | netif_receive_skb(skb); | 240 | netif_receive_skb(skb); |
235 | 241 | ||
236 | repost: | 242 | repost: |
@@ -245,29 +251,37 @@ static int ipoib_dma_map_tx(struct ib_device *ca, | |||
245 | struct sk_buff *skb = tx_req->skb; | 251 | struct sk_buff *skb = tx_req->skb; |
246 | u64 *mapping = tx_req->mapping; | 252 | u64 *mapping = tx_req->mapping; |
247 | int i; | 253 | int i; |
254 | int off; | ||
248 | 255 | ||
249 | mapping[0] = ib_dma_map_single(ca, skb->data, skb_headlen(skb), | 256 | if (skb_headlen(skb)) { |
250 | DMA_TO_DEVICE); | 257 | mapping[0] = ib_dma_map_single(ca, skb->data, skb_headlen(skb), |
251 | if (unlikely(ib_dma_mapping_error(ca, mapping[0]))) | 258 | DMA_TO_DEVICE); |
252 | return -EIO; | 259 | if (unlikely(ib_dma_mapping_error(ca, mapping[0]))) |
260 | return -EIO; | ||
261 | |||
262 | off = 1; | ||
263 | } else | ||
264 | off = 0; | ||
253 | 265 | ||
254 | for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) { | 266 | for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) { |
255 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; | 267 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; |
256 | mapping[i + 1] = ib_dma_map_page(ca, frag->page, | 268 | mapping[i + off] = ib_dma_map_page(ca, frag->page, |
257 | frag->page_offset, frag->size, | 269 | frag->page_offset, frag->size, |
258 | DMA_TO_DEVICE); | 270 | DMA_TO_DEVICE); |
259 | if (unlikely(ib_dma_mapping_error(ca, mapping[i + 1]))) | 271 | if (unlikely(ib_dma_mapping_error(ca, mapping[i + off]))) |
260 | goto partial_error; | 272 | goto partial_error; |
261 | } | 273 | } |
262 | return 0; | 274 | return 0; |
263 | 275 | ||
264 | partial_error: | 276 | partial_error: |
265 | ib_dma_unmap_single(ca, mapping[0], skb_headlen(skb), DMA_TO_DEVICE); | ||
266 | |||
267 | for (; i > 0; --i) { | 277 | for (; i > 0; --i) { |
268 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1]; | 278 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1]; |
269 | ib_dma_unmap_page(ca, mapping[i], frag->size, DMA_TO_DEVICE); | 279 | ib_dma_unmap_page(ca, mapping[i - !off], frag->size, DMA_TO_DEVICE); |
270 | } | 280 | } |
281 | |||
282 | if (off) | ||
283 | ib_dma_unmap_single(ca, mapping[0], skb_headlen(skb), DMA_TO_DEVICE); | ||
284 | |||
271 | return -EIO; | 285 | return -EIO; |
272 | } | 286 | } |
273 | 287 | ||
@@ -277,12 +291,17 @@ static void ipoib_dma_unmap_tx(struct ib_device *ca, | |||
277 | struct sk_buff *skb = tx_req->skb; | 291 | struct sk_buff *skb = tx_req->skb; |
278 | u64 *mapping = tx_req->mapping; | 292 | u64 *mapping = tx_req->mapping; |
279 | int i; | 293 | int i; |
294 | int off; | ||
280 | 295 | ||
281 | ib_dma_unmap_single(ca, mapping[0], skb_headlen(skb), DMA_TO_DEVICE); | 296 | if (skb_headlen(skb)) { |
297 | ib_dma_unmap_single(ca, mapping[0], skb_headlen(skb), DMA_TO_DEVICE); | ||
298 | off = 1; | ||
299 | } else | ||
300 | off = 0; | ||
282 | 301 | ||
283 | for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) { | 302 | for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) { |
284 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; | 303 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; |
285 | ib_dma_unmap_page(ca, mapping[i + 1], frag->size, | 304 | ib_dma_unmap_page(ca, mapping[i + off], frag->size, |
286 | DMA_TO_DEVICE); | 305 | DMA_TO_DEVICE); |
287 | } | 306 | } |
288 | } | 307 | } |
@@ -388,24 +407,40 @@ void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr) | |||
388 | static inline int post_send(struct ipoib_dev_priv *priv, | 407 | static inline int post_send(struct ipoib_dev_priv *priv, |
389 | unsigned int wr_id, | 408 | unsigned int wr_id, |
390 | struct ib_ah *address, u32 qpn, | 409 | struct ib_ah *address, u32 qpn, |
391 | u64 *mapping, int headlen, | 410 | struct ipoib_tx_buf *tx_req, |
392 | skb_frag_t *frags, | 411 | void *head, int hlen) |
393 | int nr_frags) | ||
394 | { | 412 | { |
395 | struct ib_send_wr *bad_wr; | 413 | struct ib_send_wr *bad_wr; |
396 | int i; | 414 | int i, off; |
415 | struct sk_buff *skb = tx_req->skb; | ||
416 | skb_frag_t *frags = skb_shinfo(skb)->frags; | ||
417 | int nr_frags = skb_shinfo(skb)->nr_frags; | ||
418 | u64 *mapping = tx_req->mapping; | ||
419 | |||
420 | if (skb_headlen(skb)) { | ||
421 | priv->tx_sge[0].addr = mapping[0]; | ||
422 | priv->tx_sge[0].length = skb_headlen(skb); | ||
423 | off = 1; | ||
424 | } else | ||
425 | off = 0; | ||
397 | 426 | ||
398 | priv->tx_sge[0].addr = mapping[0]; | ||
399 | priv->tx_sge[0].length = headlen; | ||
400 | for (i = 0; i < nr_frags; ++i) { | 427 | for (i = 0; i < nr_frags; ++i) { |
401 | priv->tx_sge[i + 1].addr = mapping[i + 1]; | 428 | priv->tx_sge[i + off].addr = mapping[i + off]; |
402 | priv->tx_sge[i + 1].length = frags[i].size; | 429 | priv->tx_sge[i + off].length = frags[i].size; |
403 | } | 430 | } |
404 | priv->tx_wr.num_sge = nr_frags + 1; | 431 | priv->tx_wr.num_sge = nr_frags + off; |
405 | priv->tx_wr.wr_id = wr_id; | 432 | priv->tx_wr.wr_id = wr_id; |
406 | priv->tx_wr.wr.ud.remote_qpn = qpn; | 433 | priv->tx_wr.wr.ud.remote_qpn = qpn; |
407 | priv->tx_wr.wr.ud.ah = address; | 434 | priv->tx_wr.wr.ud.ah = address; |
408 | 435 | ||
436 | if (head) { | ||
437 | priv->tx_wr.wr.ud.mss = skb_shinfo(skb)->gso_size; | ||
438 | priv->tx_wr.wr.ud.header = head; | ||
439 | priv->tx_wr.wr.ud.hlen = hlen; | ||
440 | priv->tx_wr.opcode = IB_WR_LSO; | ||
441 | } else | ||
442 | priv->tx_wr.opcode = IB_WR_SEND; | ||
443 | |||
409 | return ib_post_send(priv->qp, &priv->tx_wr, &bad_wr); | 444 | return ib_post_send(priv->qp, &priv->tx_wr, &bad_wr); |
410 | } | 445 | } |
411 | 446 | ||
@@ -414,14 +449,30 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, | |||
414 | { | 449 | { |
415 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 450 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
416 | struct ipoib_tx_buf *tx_req; | 451 | struct ipoib_tx_buf *tx_req; |
417 | 452 | int hlen; | |
418 | if (unlikely(skb->len > priv->mcast_mtu + IPOIB_ENCAP_LEN)) { | 453 | void *phead; |
419 | ipoib_warn(priv, "packet len %d (> %d) too long to send, dropping\n", | 454 | |
420 | skb->len, priv->mcast_mtu + IPOIB_ENCAP_LEN); | 455 | if (skb_is_gso(skb)) { |
421 | ++dev->stats.tx_dropped; | 456 | hlen = skb_transport_offset(skb) + tcp_hdrlen(skb); |
422 | ++dev->stats.tx_errors; | 457 | phead = skb->data; |
423 | ipoib_cm_skb_too_long(dev, skb, priv->mcast_mtu); | 458 | if (unlikely(!skb_pull(skb, hlen))) { |
424 | return; | 459 | ipoib_warn(priv, "linear data too small\n"); |
460 | ++dev->stats.tx_dropped; | ||
461 | ++dev->stats.tx_errors; | ||
462 | dev_kfree_skb_any(skb); | ||
463 | return; | ||
464 | } | ||
465 | } else { | ||
466 | if (unlikely(skb->len > priv->mcast_mtu + IPOIB_ENCAP_LEN)) { | ||
467 | ipoib_warn(priv, "packet len %d (> %d) too long to send, dropping\n", | ||
468 | skb->len, priv->mcast_mtu + IPOIB_ENCAP_LEN); | ||
469 | ++dev->stats.tx_dropped; | ||
470 | ++dev->stats.tx_errors; | ||
471 | ipoib_cm_skb_too_long(dev, skb, priv->mcast_mtu); | ||
472 | return; | ||
473 | } | ||
474 | phead = NULL; | ||
475 | hlen = 0; | ||
425 | } | 476 | } |
426 | 477 | ||
427 | ipoib_dbg_data(priv, "sending packet, length=%d address=%p qpn=0x%06x\n", | 478 | ipoib_dbg_data(priv, "sending packet, length=%d address=%p qpn=0x%06x\n", |
@@ -442,10 +493,13 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, | |||
442 | return; | 493 | return; |
443 | } | 494 | } |
444 | 495 | ||
496 | if (skb->ip_summed == CHECKSUM_PARTIAL) | ||
497 | priv->tx_wr.send_flags |= IB_SEND_IP_CSUM; | ||
498 | else | ||
499 | priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; | ||
500 | |||
445 | if (unlikely(post_send(priv, priv->tx_head & (ipoib_sendq_size - 1), | 501 | if (unlikely(post_send(priv, priv->tx_head & (ipoib_sendq_size - 1), |
446 | address->ah, qpn, | 502 | address->ah, qpn, tx_req, phead, hlen))) { |
447 | tx_req->mapping, skb_headlen(skb), | ||
448 | skb_shinfo(skb)->frags, skb_shinfo(skb)->nr_frags))) { | ||
449 | ipoib_warn(priv, "post_send failed\n"); | 503 | ipoib_warn(priv, "post_send failed\n"); |
450 | ++dev->stats.tx_errors; | 504 | ++dev->stats.tx_errors; |
451 | ipoib_dma_unmap_tx(priv->ca, tx_req); | 505 | ipoib_dma_unmap_tx(priv->ca, tx_req); |
@@ -540,7 +594,7 @@ static void ipoib_pkey_dev_check_presence(struct net_device *dev) | |||
540 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 594 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
541 | u16 pkey_index = 0; | 595 | u16 pkey_index = 0; |
542 | 596 | ||
543 | if (ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &pkey_index)) | 597 | if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &pkey_index)) |
544 | clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); | 598 | clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); |
545 | else | 599 | else |
546 | set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); | 600 | set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); |
@@ -781,13 +835,13 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, int pkey_event) | |||
781 | clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); | 835 | clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); |
782 | ipoib_ib_dev_down(dev, 0); | 836 | ipoib_ib_dev_down(dev, 0); |
783 | ipoib_ib_dev_stop(dev, 0); | 837 | ipoib_ib_dev_stop(dev, 0); |
784 | ipoib_pkey_dev_delay_open(dev); | 838 | if (ipoib_pkey_dev_delay_open(dev)) |
785 | return; | 839 | return; |
786 | } | 840 | } |
787 | set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); | ||
788 | 841 | ||
789 | /* restart QP only if P_Key index is changed */ | 842 | /* restart QP only if P_Key index is changed */ |
790 | if (new_index == priv->pkey_index) { | 843 | if (test_and_set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags) && |
844 | new_index == priv->pkey_index) { | ||
791 | ipoib_dbg(priv, "Not flushing - P_Key index not changed.\n"); | 845 | ipoib_dbg(priv, "Not flushing - P_Key index not changed.\n"); |
792 | return; | 846 | return; |
793 | } | 847 | } |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 57282048865c..bd07f02cf02b 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
@@ -359,8 +359,7 @@ void ipoib_flush_paths(struct net_device *dev) | |||
359 | spin_lock_irq(&priv->tx_lock); | 359 | spin_lock_irq(&priv->tx_lock); |
360 | spin_lock(&priv->lock); | 360 | spin_lock(&priv->lock); |
361 | 361 | ||
362 | list_splice(&priv->path_list, &remove_list); | 362 | list_splice_init(&priv->path_list, &remove_list); |
363 | INIT_LIST_HEAD(&priv->path_list); | ||
364 | 363 | ||
365 | list_for_each_entry(path, &remove_list, list) | 364 | list_for_each_entry(path, &remove_list, list) |
366 | rb_erase(&path->rb_node, &priv->path_tree); | 365 | rb_erase(&path->rb_node, &priv->path_tree); |
@@ -952,6 +951,8 @@ static void ipoib_setup(struct net_device *dev) | |||
952 | dev->set_multicast_list = ipoib_set_mcast_list; | 951 | dev->set_multicast_list = ipoib_set_mcast_list; |
953 | dev->neigh_setup = ipoib_neigh_setup_dev; | 952 | dev->neigh_setup = ipoib_neigh_setup_dev; |
954 | 953 | ||
954 | ipoib_set_ethtool_ops(dev); | ||
955 | |||
955 | netif_napi_add(dev, &priv->napi, ipoib_poll, 100); | 956 | netif_napi_add(dev, &priv->napi, ipoib_poll, 100); |
956 | 957 | ||
957 | dev->watchdog_timeo = HZ; | 958 | dev->watchdog_timeo = HZ; |
@@ -1105,6 +1106,7 @@ static struct net_device *ipoib_add_port(const char *format, | |||
1105 | struct ib_device *hca, u8 port) | 1106 | struct ib_device *hca, u8 port) |
1106 | { | 1107 | { |
1107 | struct ipoib_dev_priv *priv; | 1108 | struct ipoib_dev_priv *priv; |
1109 | struct ib_device_attr *device_attr; | ||
1108 | int result = -ENOMEM; | 1110 | int result = -ENOMEM; |
1109 | 1111 | ||
1110 | priv = ipoib_intf_alloc(format); | 1112 | priv = ipoib_intf_alloc(format); |
@@ -1120,6 +1122,29 @@ static struct net_device *ipoib_add_port(const char *format, | |||
1120 | goto device_init_failed; | 1122 | goto device_init_failed; |
1121 | } | 1123 | } |
1122 | 1124 | ||
1125 | device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL); | ||
1126 | if (!device_attr) { | ||
1127 | printk(KERN_WARNING "%s: allocation of %zu bytes failed\n", | ||
1128 | hca->name, sizeof *device_attr); | ||
1129 | goto device_init_failed; | ||
1130 | } | ||
1131 | |||
1132 | result = ib_query_device(hca, device_attr); | ||
1133 | if (result) { | ||
1134 | printk(KERN_WARNING "%s: ib_query_device failed (ret = %d)\n", | ||
1135 | hca->name, result); | ||
1136 | kfree(device_attr); | ||
1137 | goto device_init_failed; | ||
1138 | } | ||
1139 | priv->hca_caps = device_attr->device_cap_flags; | ||
1140 | |||
1141 | kfree(device_attr); | ||
1142 | |||
1143 | if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) { | ||
1144 | set_bit(IPOIB_FLAG_CSUM, &priv->flags); | ||
1145 | priv->dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; | ||
1146 | } | ||
1147 | |||
1123 | /* | 1148 | /* |
1124 | * Set the full membership bit, so that we join the right | 1149 | * Set the full membership bit, so that we join the right |
1125 | * broadcast group, etc. | 1150 | * broadcast group, etc. |
@@ -1137,7 +1162,6 @@ static struct net_device *ipoib_add_port(const char *format, | |||
1137 | } else | 1162 | } else |
1138 | memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid)); | 1163 | memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid)); |
1139 | 1164 | ||
1140 | |||
1141 | result = ipoib_dev_init(priv->dev, hca, port); | 1165 | result = ipoib_dev_init(priv->dev, hca, port); |
1142 | if (result < 0) { | 1166 | if (result < 0) { |
1143 | printk(KERN_WARNING "%s: failed to initialize port %d (ret = %d)\n", | 1167 | printk(KERN_WARNING "%s: failed to initialize port %d (ret = %d)\n", |
@@ -1155,6 +1179,9 @@ static struct net_device *ipoib_add_port(const char *format, | |||
1155 | goto event_failed; | 1179 | goto event_failed; |
1156 | } | 1180 | } |
1157 | 1181 | ||
1182 | if (priv->dev->features & NETIF_F_SG && priv->hca_caps & IB_DEVICE_UD_TSO) | ||
1183 | priv->dev->features |= NETIF_F_TSO; | ||
1184 | |||
1158 | result = register_netdev(priv->dev); | 1185 | result = register_netdev(priv->dev); |
1159 | if (result) { | 1186 | if (result) { |
1160 | printk(KERN_WARNING "%s: couldn't register ipoib port %d; error %d\n", | 1187 | printk(KERN_WARNING "%s: couldn't register ipoib port %d; error %d\n", |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c index a3aeb911f024..8a20e3742c43 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c | |||
@@ -192,6 +192,9 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca) | |||
192 | init_attr.send_cq = priv->cq; | 192 | init_attr.send_cq = priv->cq; |
193 | init_attr.recv_cq = priv->cq; | 193 | init_attr.recv_cq = priv->cq; |
194 | 194 | ||
195 | if (priv->hca_caps & IB_DEVICE_UD_TSO) | ||
196 | init_attr.create_flags = IB_QP_CREATE_IPOIB_UD_LSO; | ||
197 | |||
195 | if (dev->features & NETIF_F_SG) | 198 | if (dev->features & NETIF_F_SG) |
196 | init_attr.cap.max_send_sge = MAX_SKB_FRAGS + 1; | 199 | init_attr.cap.max_send_sge = MAX_SKB_FRAGS + 1; |
197 | 200 | ||
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c index 83247f1fdf72..08dc81c46f41 100644 --- a/drivers/infiniband/ulp/iser/iser_initiator.c +++ b/drivers/infiniband/ulp/iser/iser_initiator.c | |||
@@ -405,7 +405,7 @@ int iser_send_data_out(struct iscsi_conn *conn, | |||
405 | struct iser_dto *send_dto = NULL; | 405 | struct iser_dto *send_dto = NULL; |
406 | unsigned long buf_offset; | 406 | unsigned long buf_offset; |
407 | unsigned long data_seg_len; | 407 | unsigned long data_seg_len; |
408 | unsigned int itt; | 408 | uint32_t itt; |
409 | int err = 0; | 409 | int err = 0; |
410 | 410 | ||
411 | if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) { | 411 | if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) { |
@@ -416,7 +416,7 @@ int iser_send_data_out(struct iscsi_conn *conn, | |||
416 | if (iser_check_xmit(conn, ctask)) | 416 | if (iser_check_xmit(conn, ctask)) |
417 | return -ENOBUFS; | 417 | return -ENOBUFS; |
418 | 418 | ||
419 | itt = ntohl(hdr->itt); | 419 | itt = (__force uint32_t)hdr->itt; |
420 | data_seg_len = ntoh24(hdr->dlength); | 420 | data_seg_len = ntoh24(hdr->dlength); |
421 | buf_offset = ntohl(hdr->offset); | 421 | buf_offset = ntohl(hdr->offset); |
422 | 422 | ||
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index 993f0a8ff28f..d19cfe605ebb 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c | |||
@@ -473,11 +473,8 @@ static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *eve | |||
473 | iser_connect_error(cma_id); | 473 | iser_connect_error(cma_id); |
474 | break; | 474 | break; |
475 | case RDMA_CM_EVENT_DISCONNECTED: | 475 | case RDMA_CM_EVENT_DISCONNECTED: |
476 | iser_disconnected_handler(cma_id); | ||
477 | break; | ||
478 | case RDMA_CM_EVENT_DEVICE_REMOVAL: | 476 | case RDMA_CM_EVENT_DEVICE_REMOVAL: |
479 | iser_err("Device removal is currently unsupported\n"); | 477 | iser_disconnected_handler(cma_id); |
480 | BUG(); | ||
481 | break; | 478 | break; |
482 | default: | 479 | default: |
483 | iser_err("Unexpected RDMA CM event (%d)\n", event->event); | 480 | iser_err("Unexpected RDMA CM event (%d)\n", event->event); |
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index fd4a49fc4773..125765aa9d59 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
@@ -68,7 +68,7 @@ static int srp_max_iu_len; | |||
68 | 68 | ||
69 | module_param(srp_sg_tablesize, int, 0444); | 69 | module_param(srp_sg_tablesize, int, 0444); |
70 | MODULE_PARM_DESC(srp_sg_tablesize, | 70 | MODULE_PARM_DESC(srp_sg_tablesize, |
71 | "Max number of gather/scatter entries per I/O (default is 12)"); | 71 | "Max number of gather/scatter entries per I/O (default is 12, max 255)"); |
72 | 72 | ||
73 | static int topspin_workarounds = 1; | 73 | static int topspin_workarounds = 1; |
74 | 74 | ||
@@ -2138,6 +2138,11 @@ static int __init srp_init_module(void) | |||
2138 | { | 2138 | { |
2139 | int ret; | 2139 | int ret; |
2140 | 2140 | ||
2141 | if (srp_sg_tablesize > 255) { | ||
2142 | printk(KERN_WARNING PFX "Clamping srp_sg_tablesize to 255\n"); | ||
2143 | srp_sg_tablesize = 255; | ||
2144 | } | ||
2145 | |||
2141 | ib_srp_transport_template = | 2146 | ib_srp_transport_template = |
2142 | srp_attach_transport(&ib_srp_transport_functions); | 2147 | srp_attach_transport(&ib_srp_transport_functions); |
2143 | if (!ib_srp_transport_template) | 2148 | if (!ib_srp_transport_template) |