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 | 34 | ||||
-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 | 42 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 2 | ||||
-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 | 52 | ||||
-rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.c | 188 | ||||
-rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.h | 4 |
12 files changed, 397 insertions, 170 deletions
diff --git a/drivers/infiniband/ulp/ipoib/Makefile b/drivers/infiniband/ulp/ipoib/Makefile index 98ee38e8c2c..3090100f0de 100644 --- a/drivers/infiniband/ulp/ipoib/Makefile +++ b/drivers/infiniband/ulp/ipoib/Makefile @@ -4,7 +4,8 @@ ib_ipoib-y := ipoib_main.o \ ipoib_ib.o \ ipoib_multicast.o \ ipoib_verbs.o \ - ipoib_vlan.o + ipoib_vlan.o \ + ipoib_ethtool.o ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_CM) += ipoib_cm.o ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_DEBUG) += ipoib_fs.o diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 054fab8e27a..73b2b176ad0 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -87,6 +87,7 @@ enum { IPOIB_MCAST_STARTED = 8, IPOIB_FLAG_ADMIN_CM = 9, IPOIB_FLAG_UMCAST = 10, + IPOIB_FLAG_CSUM = 11, IPOIB_MAX_BACKOFF_SECONDS = 16, @@ -241,6 +242,11 @@ struct ipoib_cm_dev_priv { int num_frags; }; +struct ipoib_ethtool_st { + u16 coalesce_usecs; + u16 max_coalesced_frames; +}; + /* * Device private locking: tx_lock protects members used in TX fast * path (and we use LLTX so upper layers don't do extra locking). @@ -318,6 +324,8 @@ struct ipoib_dev_priv { struct dentry *mcg_dentry; struct dentry *path_dentry; #endif + int hca_caps; + struct ipoib_ethtool_st ethtool; }; struct ipoib_ah { @@ -458,6 +466,8 @@ void ipoib_pkey_poll(struct work_struct *work); int ipoib_pkey_dev_delay_open(struct net_device *dev); void ipoib_drain_cq(struct net_device *dev); +void ipoib_set_ethtool_ops(struct net_device *dev); + #ifdef CONFIG_INFINIBAND_IPOIB_CM #define IPOIB_FLAGS_RC 0x80 diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 7dd2ec473d2..9db7b0bd913 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -38,6 +38,7 @@ #include <net/icmp.h> #include <linux/icmpv6.h> #include <linux/delay.h> +#include <linux/vmalloc.h> #include "ipoib.h" @@ -637,6 +638,7 @@ static inline int post_send(struct ipoib_dev_priv *priv, priv->tx_sge[0].addr = addr; priv->tx_sge[0].length = len; + priv->tx_wr.num_sge = 1; priv->tx_wr.wr_id = wr_id | IPOIB_OP_CM; return ib_post_send(tx->qp, &priv->tx_wr, &bad_wr); @@ -824,7 +826,6 @@ void ipoib_cm_dev_stop(struct net_device *dev) struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_cm_rx *p; unsigned long begin; - LIST_HEAD(list); int ret; if (!IPOIB_CM_SUPPORTED(dev->dev_addr) || !priv->cm.id) @@ -857,9 +858,12 @@ void ipoib_cm_dev_stop(struct net_device *dev) /* * assume the HW is wedged and just free up everything. */ - list_splice_init(&priv->cm.rx_flush_list, &list); - list_splice_init(&priv->cm.rx_error_list, &list); - list_splice_init(&priv->cm.rx_drain_list, &list); + list_splice_init(&priv->cm.rx_flush_list, + &priv->cm.rx_reap_list); + list_splice_init(&priv->cm.rx_error_list, + &priv->cm.rx_reap_list); + list_splice_init(&priv->cm.rx_drain_list, + &priv->cm.rx_reap_list); break; } spin_unlock_irq(&priv->lock); @@ -1003,9 +1007,9 @@ static int ipoib_cm_modify_tx_init(struct net_device *dev, struct ipoib_dev_priv *priv = netdev_priv(dev); struct ib_qp_attr qp_attr; int qp_attr_mask, ret; - ret = ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &qp_attr.pkey_index); + ret = ib_find_pkey(priv->ca, priv->port, priv->pkey, &qp_attr.pkey_index); if (ret) { - ipoib_warn(priv, "pkey 0x%x not in cache: %d\n", priv->pkey, ret); + ipoib_warn(priv, "pkey 0x%x not found: %d\n", priv->pkey, ret); return ret; } @@ -1028,13 +1032,13 @@ static int ipoib_cm_tx_init(struct ipoib_cm_tx *p, u32 qpn, struct ipoib_dev_priv *priv = netdev_priv(p->dev); int ret; - p->tx_ring = kzalloc(ipoib_sendq_size * sizeof *p->tx_ring, - GFP_KERNEL); + p->tx_ring = vmalloc(ipoib_sendq_size * sizeof *p->tx_ring); if (!p->tx_ring) { ipoib_warn(priv, "failed to allocate tx ring\n"); ret = -ENOMEM; goto err_tx; } + memset(p->tx_ring, 0, ipoib_sendq_size * sizeof *p->tx_ring); p->qp = ipoib_cm_create_tx_qp(p->dev, p); if (IS_ERR(p->qp)) { @@ -1075,6 +1079,7 @@ err_id: ib_destroy_qp(p->qp); err_qp: p->qp = NULL; + vfree(p->tx_ring); err_tx: return ret; } @@ -1125,7 +1130,7 @@ timeout: if (p->qp) ib_destroy_qp(p->qp); - kfree(p->tx_ring); + vfree(p->tx_ring); kfree(p); } @@ -1378,6 +1383,10 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr, set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); ipoib_warn(priv, "enabling connected mode " "will cause multicast packet drops\n"); + + dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO); + priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; + ipoib_flush_paths(dev); return count; } @@ -1386,6 +1395,13 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr, clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); dev->mtu = min(priv->mcast_mtu, dev->mtu); ipoib_flush_paths(dev); + + if (test_bit(IPOIB_FLAG_CSUM, &priv->flags)) { + dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; + if (priv->hca_caps & IB_DEVICE_UD_TSO) + dev->features |= NETIF_F_TSO; + } + return count; } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c new file mode 100644 index 00000000000..9a47428366c --- /dev/null +++ b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2007 Mellanox Technologies. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include <linux/kernel.h> +#include <linux/ethtool.h> +#include <linux/netdevice.h> + +#include "ipoib.h" + +static void ipoib_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *drvinfo) +{ + strncpy(drvinfo->driver, "ipoib", sizeof(drvinfo->driver) - 1); +} + +static int ipoib_get_coalesce(struct net_device *dev, + struct ethtool_coalesce *coal) +{ + struct ipoib_dev_priv *priv = netdev_priv(dev); + + coal->rx_coalesce_usecs = priv->ethtool.coalesce_usecs; + coal->tx_coalesce_usecs = priv->ethtool.coalesce_usecs; + coal->rx_max_coalesced_frames = priv->ethtool.max_coalesced_frames; + coal->tx_max_coalesced_frames = priv->ethtool.max_coalesced_frames; + + return 0; +} + +static int ipoib_set_coalesce(struct net_device *dev, + struct ethtool_coalesce *coal) +{ + struct ipoib_dev_priv *priv = netdev_priv(dev); + int ret; + + /* + * Since IPoIB uses a single CQ for both rx and tx, we assume + * that rx params dictate the configuration. These values are + * saved in the private data and returned when ipoib_get_coalesce() + * is called. + */ + if (coal->rx_coalesce_usecs > 0xffff || + coal->rx_max_coalesced_frames > 0xffff) + return -EINVAL; + + ret = ib_modify_cq(priv->cq, coal->rx_max_coalesced_frames, + coal->rx_coalesce_usecs); + if (ret && ret != -ENOSYS) { + ipoib_warn(priv, "failed modifying CQ (%d)\n", ret); + return ret; + } + + coal->tx_coalesce_usecs = coal->rx_coalesce_usecs; + coal->tx_max_coalesced_frames = coal->rx_max_coalesced_frames; + priv->ethtool.coalesce_usecs = coal->rx_coalesce_usecs; + priv->ethtool.max_coalesced_frames = coal->rx_max_coalesced_frames; + + return 0; +} + +static const struct ethtool_ops ipoib_ethtool_ops = { + .get_drvinfo = ipoib_get_drvinfo, + .get_tso = ethtool_op_get_tso, + .get_coalesce = ipoib_get_coalesce, + .set_coalesce = ipoib_set_coalesce, +}; + +void ipoib_set_ethtool_ops(struct net_device *dev) +{ + SET_ETHTOOL_OPS(dev, &ipoib_ethtool_ops); +} diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 08c4396cf41..0205eb7c1bd 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -39,6 +39,8 @@ #include <linux/dma-mapping.h> #include <rdma/ib_cache.h> +#include <linux/ip.h> +#include <linux/tcp.h> #include "ipoib.h" @@ -231,6 +233,10 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) skb->dev = dev; /* XXX get correct PACKET_ type here */ skb->pkt_type = PACKET_HOST; + + if (test_bit(IPOIB_FLAG_CSUM, &priv->flags) && likely(wc->csum_ok)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + netif_receive_skb(skb); repost: @@ -245,29 +251,37 @@ static int ipoib_dma_map_tx(struct ib_device *ca, struct sk_buff *skb = tx_req->skb; u64 *mapping = tx_req->mapping; int i; + int off; - mapping[0] = ib_dma_map_single(ca, skb->data, skb_headlen(skb), - DMA_TO_DEVICE); - if (unlikely(ib_dma_mapping_error(ca, mapping[0]))) - return -EIO; + if (skb_headlen(skb)) { + mapping[0] = ib_dma_map_single(ca, skb->data, skb_headlen(skb), + DMA_TO_DEVICE); + if (unlikely(ib_dma_mapping_error(ca, mapping[0]))) + return -EIO; + + off = 1; + } else + off = 0; for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - mapping[i + 1] = ib_dma_map_page(ca, frag->page, + mapping[i + off] = ib_dma_map_page(ca, frag->page, frag->page_offset, frag->size, DMA_TO_DEVICE); - if (unlikely(ib_dma_mapping_error(ca, mapping[i + 1]))) + if (unlikely(ib_dma_mapping_error(ca, mapping[i + off]))) goto partial_error; } return 0; partial_error: - ib_dma_unmap_single(ca, mapping[0], skb_headlen(skb), DMA_TO_DEVICE); - for (; i > 0; --i) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1]; - ib_dma_unmap_page(ca, mapping[i], frag->size, DMA_TO_DEVICE); + ib_dma_unmap_page(ca, mapping[i - !off], frag->size, DMA_TO_DEVICE); } + + if (off) + ib_dma_unmap_single(ca, mapping[0], skb_headlen(skb), DMA_TO_DEVICE); + return -EIO; } @@ -277,12 +291,17 @@ static void ipoib_dma_unmap_tx(struct ib_device *ca, struct sk_buff *skb = tx_req->skb; u64 *mapping = tx_req->mapping; int i; + int off; - ib_dma_unmap_single(ca, mapping[0], skb_headlen(skb), DMA_TO_DEVICE); + if (skb_headlen(skb)) { + ib_dma_unmap_single(ca, mapping[0], skb_headlen(skb), DMA_TO_DEVICE); + off = 1; + } else + off = 0; for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - ib_dma_unmap_page(ca, mapping[i + 1], frag->size, + ib_dma_unmap_page(ca, mapping[i + off], frag->size, DMA_TO_DEVICE); } } @@ -388,24 +407,40 @@ void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr) static inline int post_send(struct ipoib_dev_priv *priv, unsigned int wr_id, struct ib_ah *address, u32 qpn, - u64 *mapping, int headlen, - skb_frag_t *frags, - int nr_frags) + struct ipoib_tx_buf *tx_req, + void *head, int hlen) { struct ib_send_wr *bad_wr; - int i; + int i, off; + struct sk_buff *skb = tx_req->skb; + skb_frag_t *frags = skb_shinfo(skb)->frags; + int nr_frags = skb_shinfo(skb)->nr_frags; + u64 *mapping = tx_req->mapping; + + if (skb_headlen(skb)) { + priv->tx_sge[0].addr = mapping[0]; + priv->tx_sge[0].length = skb_headlen(skb); + off = 1; + } else + off = 0; - priv->tx_sge[0].addr = mapping[0]; - priv->tx_sge[0].length = headlen; for (i = 0; i < nr_frags; ++i) { - priv->tx_sge[i + 1].addr = mapping[i + 1]; - priv->tx_sge[i + 1].length = frags[i].size; + priv->tx_sge[i + off].addr = mapping[i + off]; + priv->tx_sge[i + off].length = frags[i].size; } - priv->tx_wr.num_sge = nr_frags + 1; + priv->tx_wr.num_sge = nr_frags + off; priv->tx_wr.wr_id = wr_id; priv->tx_wr.wr.ud.remote_qpn = qpn; priv->tx_wr.wr.ud.ah = address; + if (head) { + priv->tx_wr.wr.ud.mss = skb_shinfo(skb)->gso_size; + priv->tx_wr.wr.ud.header = head; + priv->tx_wr.wr.ud.hlen = hlen; + priv->tx_wr.opcode = IB_WR_LSO; + } else + priv->tx_wr.opcode = IB_WR_SEND; + return ib_post_send(priv->qp, &priv->tx_wr, &bad_wr); } @@ -414,14 +449,30 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, { struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_tx_buf *tx_req; - - if (unlikely(skb->len > priv->mcast_mtu + IPOIB_ENCAP_LEN)) { - ipoib_warn(priv, "packet len %d (> %d) too long to send, dropping\n", - skb->len, priv->mcast_mtu + IPOIB_ENCAP_LEN); - ++dev->stats.tx_dropped; - ++dev->stats.tx_errors; - ipoib_cm_skb_too_long(dev, skb, priv->mcast_mtu); - return; + int hlen; + void *phead; + + if (skb_is_gso(skb)) { + hlen = skb_transport_offset(skb) + tcp_hdrlen(skb); + phead = skb->data; + if (unlikely(!skb_pull(skb, hlen))) { + ipoib_warn(priv, "linear data too small\n"); + ++dev->stats.tx_dropped; + ++dev->stats.tx_errors; + dev_kfree_skb_any(skb); + return; + } + } else { + if (unlikely(skb->len > priv->mcast_mtu + IPOIB_ENCAP_LEN)) { + ipoib_warn(priv, "packet len %d (> %d) too long to send, dropping\n", + skb->len, priv->mcast_mtu + IPOIB_ENCAP_LEN); + ++dev->stats.tx_dropped; + ++dev->stats.tx_errors; + ipoib_cm_skb_too_long(dev, skb, priv->mcast_mtu); + return; + } + phead = NULL; + hlen = 0; } 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, return; } + if (skb->ip_summed == CHECKSUM_PARTIAL) + priv->tx_wr.send_flags |= IB_SEND_IP_CSUM; + else + priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; + if (unlikely(post_send(priv, priv->tx_head & (ipoib_sendq_size - 1), - address->ah, qpn, - tx_req->mapping, skb_headlen(skb), - skb_shinfo(skb)->frags, skb_shinfo(skb)->nr_frags))) { + address->ah, qpn, tx_req, phead, hlen))) { ipoib_warn(priv, "post_send failed\n"); ++dev->stats.tx_errors; ipoib_dma_unmap_tx(priv->ca, tx_req); @@ -540,7 +594,7 @@ static void ipoib_pkey_dev_check_presence(struct net_device *dev) struct ipoib_dev_priv *priv = netdev_priv(dev); u16 pkey_index = 0; - if (ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &pkey_index)) + if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &pkey_index)) clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); else 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) clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); ipoib_ib_dev_down(dev, 0); ipoib_ib_dev_stop(dev, 0); - ipoib_pkey_dev_delay_open(dev); - return; + if (ipoib_pkey_dev_delay_open(dev)) + return; } - set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); /* restart QP only if P_Key index is changed */ - if (new_index == priv->pkey_index) { + if (test_and_set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags) && + new_index == priv->pkey_index) { ipoib_dbg(priv, "Not flushing - P_Key index not changed.\n"); return; } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index f96477a8ca5..bd07f02cf02 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -41,6 +41,7 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/kernel.h> +#include <linux/vmalloc.h> #include <linux/if_arp.h> /* For ARPHRD_xxx */ @@ -358,8 +359,7 @@ void ipoib_flush_paths(struct net_device *dev) spin_lock_irq(&priv->tx_lock); spin_lock(&priv->lock); - list_splice(&priv->path_list, &remove_list); - INIT_LIST_HEAD(&priv->path_list); + list_splice_init(&priv->path_list, &remove_list); list_for_each_entry(path, &remove_list, list) rb_erase(&path->rb_node, &priv->path_tree); @@ -887,13 +887,13 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port) goto out; } - priv->tx_ring = kzalloc(ipoib_sendq_size * sizeof *priv->tx_ring, - GFP_KERNEL); + priv->tx_ring = vmalloc(ipoib_sendq_size * sizeof *priv->tx_ring); if (!priv->tx_ring) { printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n", ca->name, ipoib_sendq_size); goto out_rx_ring_cleanup; } + memset(priv->tx_ring, 0, ipoib_sendq_size * sizeof *priv->tx_ring); /* priv->tx_head, tx_tail & tx_outstanding are already 0 */ @@ -903,7 +903,7 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port) return 0; out_tx_ring_cleanup: - kfree(priv->tx_ring); + vfree(priv->tx_ring); out_rx_ring_cleanup: kfree(priv->rx_ring); @@ -928,7 +928,7 @@ void ipoib_dev_cleanup(struct net_device *dev) ipoib_ib_dev_cleanup(dev); kfree(priv->rx_ring); - kfree(priv->tx_ring); + vfree(priv->tx_ring); priv->rx_ring = NULL; priv->tx_ring = NULL; @@ -951,6 +951,8 @@ static void ipoib_setup(struct net_device *dev) dev->set_multicast_list = ipoib_set_mcast_list; dev->neigh_setup = ipoib_neigh_setup_dev; + ipoib_set_ethtool_ops(dev); + netif_napi_add(dev, &priv->napi, ipoib_poll, 100); dev->watchdog_timeo = HZ; @@ -1104,6 +1106,7 @@ static struct net_device *ipoib_add_port(const char *format, struct ib_device *hca, u8 port) { struct ipoib_dev_priv *priv; + struct ib_device_attr *device_attr; int result = -ENOMEM; priv = ipoib_intf_alloc(format); @@ -1119,6 +1122,29 @@ static struct net_device *ipoib_add_port(const char *format, goto device_init_failed; } + device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL); + if (!device_attr) { + printk(KERN_WARNING "%s: allocation of %zu bytes failed\n", + hca->name, sizeof *device_attr); + goto device_init_failed; + } + + result = ib_query_device(hca, device_attr); + if (result) { + printk(KERN_WARNING "%s: ib_query_device failed (ret = %d)\n", + hca->name, result); + kfree(device_attr); + goto device_init_failed; + } + priv->hca_caps = device_attr->device_cap_flags; + + kfree(device_attr); + + if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) { + set_bit(IPOIB_FLAG_CSUM, &priv->flags); + priv->dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; + } + /* * Set the full membership bit, so that we join the right * broadcast group, etc. @@ -1136,7 +1162,6 @@ static struct net_device *ipoib_add_port(const char *format, } else memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid)); - result = ipoib_dev_init(priv->dev, hca, port); if (result < 0) { printk(KERN_WARNING "%s: failed to initialize port %d (ret = %d)\n", @@ -1154,6 +1179,9 @@ static struct net_device *ipoib_add_port(const char *format, goto event_failed; } + if (priv->dev->features & NETIF_F_SG && priv->hca_caps & IB_DEVICE_UD_TSO) + priv->dev->features |= NETIF_F_TSO; + result = register_netdev(priv->dev); if (result) { printk(KERN_WARNING "%s: couldn't register ipoib port %d; error %d\n", diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 2628339e3a9..31a53c5bcb1 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -650,7 +650,7 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb) */ spin_lock(&priv->lock); - if (!test_bit(IPOIB_MCAST_STARTED, &priv->flags) || + if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags) || !priv->broadcast || !test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) { ++dev->stats.tx_dropped; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c index a3aeb911f02..8a20e3742c4 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) init_attr.send_cq = priv->cq; init_attr.recv_cq = priv->cq; + if (priv->hca_caps & IB_DEVICE_UD_TSO) + init_attr.create_flags = IB_QP_CREATE_IPOIB_UD_LSO; + if (dev->features & NETIF_F_SG) init_attr.cap.max_send_sge = MAX_SKB_FRAGS + 1; diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c index 83247f1fdf7..08dc81c46f4 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, struct iser_dto *send_dto = NULL; unsigned long buf_offset; unsigned long data_seg_len; - unsigned int itt; + uint32_t itt; int err = 0; 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, if (iser_check_xmit(conn, ctask)) return -ENOBUFS; - itt = ntohl(hdr->itt); + itt = (__force uint32_t)hdr->itt; data_seg_len = ntoh24(hdr->dlength); buf_offset = ntohl(hdr->offset); diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index 714b8db02b2..d19cfe605eb 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c @@ -237,36 +237,32 @@ static int iser_free_ib_conn_res(struct iser_conn *ib_conn) static struct iser_device *iser_device_find_by_ib_device(struct rdma_cm_id *cma_id) { - struct list_head *p_list; - struct iser_device *device = NULL; + struct iser_device *device; mutex_lock(&ig.device_list_mutex); - p_list = ig.device_list.next; - while (p_list != &ig.device_list) { - device = list_entry(p_list, struct iser_device, ig_list); + list_for_each_entry(device, &ig.device_list, ig_list) /* find if there's a match using the node GUID */ if (device->ib_device->node_guid == cma_id->device->node_guid) - break; - } + goto inc_refcnt; - if (device == NULL) { - device = kzalloc(sizeof *device, GFP_KERNEL); - if (device == NULL) - goto out; - /* assign this device to the device */ - device->ib_device = cma_id->device; - /* init the device and link it into ig device list */ - if (iser_create_device_ib_res(device)) { - kfree(device); - device = NULL; - goto out; - } - list_add(&device->ig_list, &ig.device_list); + device = kzalloc(sizeof *device, GFP_KERNEL); + if (device == NULL) + goto out; + + /* assign this device to the device */ + device->ib_device = cma_id->device; + /* init the device and link it into ig device list */ + if (iser_create_device_ib_res(device)) { + kfree(device); + device = NULL; + goto out; } -out: - BUG_ON(device == NULL); + list_add(&device->ig_list, &ig.device_list); + +inc_refcnt: device->refcount++; +out: mutex_unlock(&ig.device_list_mutex); return device; } @@ -372,6 +368,12 @@ static void iser_addr_handler(struct rdma_cm_id *cma_id) int ret; device = iser_device_find_by_ib_device(cma_id); + if (!device) { + iser_err("device lookup/creation failed\n"); + iser_connect_error(cma_id); + return; + } + ib_conn = (struct iser_conn *)cma_id->context; ib_conn->device = device; @@ -380,7 +382,6 @@ static void iser_addr_handler(struct rdma_cm_id *cma_id) iser_err("resolve route failed: %d\n", ret); iser_connect_error(cma_id); } - return; } static void iser_route_handler(struct rdma_cm_id *cma_id) @@ -472,11 +473,8 @@ static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *eve iser_connect_error(cma_id); break; case RDMA_CM_EVENT_DISCONNECTED: - iser_disconnected_handler(cma_id); - break; case RDMA_CM_EVENT_DEVICE_REMOVAL: - iser_err("Device removal is currently unsupported\n"); - BUG(); + iser_disconnected_handler(cma_id); break; default: 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 fd4a49fc477..435145709dd 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; module_param(srp_sg_tablesize, int, 0444); MODULE_PARM_DESC(srp_sg_tablesize, - "Max number of gather/scatter entries per I/O (default is 12)"); + "Max number of gather/scatter entries per I/O (default is 12, max 255)"); static int topspin_workarounds = 1; @@ -139,8 +139,9 @@ static struct srp_iu *srp_alloc_iu(struct srp_host *host, size_t size, if (!iu->buf) goto out_free_iu; - iu->dma = ib_dma_map_single(host->dev->dev, iu->buf, size, direction); - if (ib_dma_mapping_error(host->dev->dev, iu->dma)) + iu->dma = ib_dma_map_single(host->srp_dev->dev, iu->buf, size, + direction); + if (ib_dma_mapping_error(host->srp_dev->dev, iu->dma)) goto out_free_buf; iu->size = size; @@ -161,7 +162,8 @@ static void srp_free_iu(struct srp_host *host, struct srp_iu *iu) if (!iu) return; - ib_dma_unmap_single(host->dev->dev, iu->dma, iu->size, iu->direction); + ib_dma_unmap_single(host->srp_dev->dev, iu->dma, iu->size, + iu->direction); kfree(iu->buf); kfree(iu); } @@ -181,7 +183,7 @@ static int srp_init_qp(struct srp_target_port *target, if (!attr) return -ENOMEM; - ret = ib_find_cached_pkey(target->srp_host->dev->dev, + ret = ib_find_cached_pkey(target->srp_host->srp_dev->dev, target->srp_host->port, be16_to_cpu(target->path.pkey), &attr->pkey_index); @@ -208,7 +210,7 @@ static int srp_new_cm_id(struct srp_target_port *target) { struct ib_cm_id *new_cm_id; - new_cm_id = ib_create_cm_id(target->srp_host->dev->dev, + new_cm_id = ib_create_cm_id(target->srp_host->srp_dev->dev, srp_cm_handler, target); if (IS_ERR(new_cm_id)) return PTR_ERR(new_cm_id); @@ -229,8 +231,8 @@ static int srp_create_target_ib(struct srp_target_port *target) if (!init_attr) return -ENOMEM; - target->cq = ib_create_cq(target->srp_host->dev->dev, srp_completion, - NULL, target, SRP_CQ_SIZE, 0); + target->cq = ib_create_cq(target->srp_host->srp_dev->dev, + srp_completion, NULL, target, SRP_CQ_SIZE, 0); if (IS_ERR(target->cq)) { ret = PTR_ERR(target->cq); goto out; @@ -248,7 +250,7 @@ static int srp_create_target_ib(struct srp_target_port *target) init_attr->send_cq = target->cq; init_attr->recv_cq = target->cq; - target->qp = ib_create_qp(target->srp_host->dev->pd, init_attr); + target->qp = ib_create_qp(target->srp_host->srp_dev->pd, init_attr); if (IS_ERR(target->qp)) { ret = PTR_ERR(target->qp); ib_destroy_cq(target->cq); @@ -302,7 +304,7 @@ static int srp_lookup_path(struct srp_target_port *target) init_completion(&target->done); target->path_query_id = ib_sa_path_rec_get(&srp_sa_client, - target->srp_host->dev->dev, + target->srp_host->srp_dev->dev, target->srp_host->port, &target->path, IB_SA_PATH_REC_SERVICE_ID | @@ -403,7 +405,7 @@ static int srp_send_req(struct srp_target_port *target) (unsigned long long) be64_to_cpu(target->ioc_guid)); memset(req->priv.initiator_port_id, 0, 8); memcpy(req->priv.initiator_port_id + 8, - &target->srp_host->dev->dev->node_guid, 8); + &target->srp_host->srp_dev->dev->node_guid, 8); } status = ib_send_cm_req(target->cm_id, &req->param); @@ -520,7 +522,7 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd, req->fmr = NULL; } - ib_dma_unmap_sg(target->srp_host->dev->dev, scsi_sglist(scmnd), + ib_dma_unmap_sg(target->srp_host->srp_dev->dev, scsi_sglist(scmnd), scsi_sg_count(scmnd), scmnd->sc_data_direction); } @@ -628,7 +630,7 @@ static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat, int page_cnt; int i, j; int ret; - struct srp_device *dev = target->srp_host->dev; + struct srp_device *dev = target->srp_host->srp_dev; struct ib_device *ibdev = dev->dev; struct scatterlist *sg; @@ -723,7 +725,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, nents = scsi_sg_count(scmnd); scat = scsi_sglist(scmnd); - dev = target->srp_host->dev; + dev = target->srp_host->srp_dev; ibdev = dev->dev; count = ib_dma_map_sg(ibdev, scat, nents, scmnd->sc_data_direction); @@ -779,7 +781,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, buf->table_desc.va = cpu_to_be64(req->cmd->dma + sizeof *cmd + sizeof *buf); buf->table_desc.key = - cpu_to_be32(target->srp_host->dev->mr->rkey); + cpu_to_be32(target->srp_host->srp_dev->mr->rkey); buf->table_desc.len = cpu_to_be32(count * sizeof (struct srp_direct_buf)); @@ -855,7 +857,7 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc) iu = target->rx_ring[wc->wr_id & ~SRP_OP_RECV]; - dev = target->srp_host->dev->dev; + dev = target->srp_host->srp_dev->dev; ib_dma_sync_single_for_cpu(dev, iu->dma, target->max_ti_iu_len, DMA_FROM_DEVICE); @@ -937,7 +939,7 @@ static int __srp_post_recv(struct srp_target_port *target) list.addr = iu->dma; list.length = iu->size; - list.lkey = target->srp_host->dev->mr->lkey; + list.lkey = target->srp_host->srp_dev->mr->lkey; wr.next = NULL; wr.sg_list = &list; @@ -996,7 +998,7 @@ static int __srp_post_send(struct srp_target_port *target, list.addr = iu->dma; list.length = len; - list.lkey = target->srp_host->dev->mr->lkey; + list.lkey = target->srp_host->srp_dev->mr->lkey; wr.next = NULL; wr.wr_id = target->tx_head & SRP_SQ_SIZE; @@ -1039,7 +1041,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd, if (!iu) goto err; - dev = target->srp_host->dev->dev; + dev = target->srp_host->srp_dev->dev; ib_dma_sync_single_for_cpu(dev, iu->dma, srp_max_iu_len, DMA_TO_DEVICE); @@ -1456,9 +1458,10 @@ static int srp_reset_host(struct scsi_cmnd *scmnd) return ret; } -static ssize_t show_id_ext(struct class_device *cdev, char *buf) +static ssize_t show_id_ext(struct device *dev, struct device_attribute *attr, + char *buf) { - struct srp_target_port *target = host_to_target(class_to_shost(cdev)); + struct srp_target_port *target = host_to_target(class_to_shost(dev)); if (target->state == SRP_TARGET_DEAD || target->state == SRP_TARGET_REMOVED) @@ -1468,9 +1471,10 @@ static ssize_t show_id_ext(struct class_device *cdev, char *buf) (unsigned long long) be64_to_cpu(target->id_ext)); } -static ssize_t show_ioc_guid(struct class_device *cdev, char *buf) +static ssize_t show_ioc_guid(struct device *dev, struct device_attribute *attr, + char *buf) { - struct srp_target_port *target = host_to_target(class_to_shost(cdev)); + struct srp_target_port *target = host_to_target(class_to_shost(dev)); if (target->state == SRP_TARGET_DEAD || target->state == SRP_TARGET_REMOVED) @@ -1480,9 +1484,10 @@ static ssize_t show_ioc_guid(struct class_device *cdev, char *buf) (unsigned long long) be64_to_cpu(target->ioc_guid)); } -static ssize_t show_service_id(struct class_device *cdev, char *buf) +static ssize_t show_service_id(struct device *dev, + struct device_attribute *attr, char *buf) { - struct srp_target_port *target = host_to_target(class_to_shost(cdev)); + struct srp_target_port *target = host_to_target(class_to_shost(dev)); if (target->state == SRP_TARGET_DEAD || target->state == SRP_TARGET_REMOVED) @@ -1492,9 +1497,10 @@ static ssize_t show_service_id(struct class_device *cdev, char *buf) (unsigned long long) be64_to_cpu(target->service_id)); } -static ssize_t show_pkey(struct class_device *cdev, char *buf) +static ssize_t show_pkey(struct device *dev, struct device_attribute *attr, + char *buf) { - struct srp_target_port *target = host_to_target(class_to_shost(cdev)); + struct srp_target_port *target = host_to_target(class_to_shost(dev)); if (target->state == SRP_TARGET_DEAD || target->state == SRP_TARGET_REMOVED) @@ -1503,9 +1509,10 @@ static ssize_t show_pkey(struct class_device *cdev, char *buf) return sprintf(buf, "0x%04x\n", be16_to_cpu(target->path.pkey)); } -static ssize_t show_dgid(struct class_device *cdev, char *buf) +static ssize_t show_dgid(struct device *dev, struct device_attribute *attr, + char *buf) { - struct srp_target_port *target = host_to_target(class_to_shost(cdev)); + struct srp_target_port *target = host_to_target(class_to_shost(dev)); if (target->state == SRP_TARGET_DEAD || target->state == SRP_TARGET_REMOVED) @@ -1522,9 +1529,10 @@ static ssize_t show_dgid(struct class_device *cdev, char *buf) be16_to_cpu(((__be16 *) target->path.dgid.raw)[7])); } -static ssize_t show_orig_dgid(struct class_device *cdev, char *buf) +static ssize_t show_orig_dgid(struct device *dev, + struct device_attribute *attr, char *buf) { - struct srp_target_port *target = host_to_target(class_to_shost(cdev)); + struct srp_target_port *target = host_to_target(class_to_shost(dev)); if (target->state == SRP_TARGET_DEAD || target->state == SRP_TARGET_REMOVED) @@ -1541,9 +1549,10 @@ static ssize_t show_orig_dgid(struct class_device *cdev, char *buf) be16_to_cpu(target->orig_dgid[7])); } -static ssize_t show_zero_req_lim(struct class_device *cdev, char *buf) +static ssize_t show_zero_req_lim(struct device *dev, + struct device_attribute *attr, char *buf) { - struct srp_target_port *target = host_to_target(class_to_shost(cdev)); + struct srp_target_port *target = host_to_target(class_to_shost(dev)); if (target->state == SRP_TARGET_DEAD || target->state == SRP_TARGET_REMOVED) @@ -1552,40 +1561,42 @@ static ssize_t show_zero_req_lim(struct class_device *cdev, char *buf) return sprintf(buf, "%d\n", target->zero_req_lim); } -static ssize_t show_local_ib_port(struct class_device *cdev, char *buf) +static ssize_t show_local_ib_port(struct device *dev, + struct device_attribute *attr, char *buf) { - struct srp_target_port *target = host_to_target(class_to_shost(cdev)); + struct srp_target_port *target = host_to_target(class_to_shost(dev)); return sprintf(buf, "%d\n", target->srp_host->port); } -static ssize_t show_local_ib_device(struct class_device *cdev, char *buf) +static ssize_t show_local_ib_device(struct device *dev, + struct device_attribute *attr, char *buf) { - struct srp_target_port *target = host_to_target(class_to_shost(cdev)); + struct srp_target_port *target = host_to_target(class_to_shost(dev)); - return sprintf(buf, "%s\n", target->srp_host->dev->dev->name); + return sprintf(buf, "%s\n", target->srp_host->srp_dev->dev->name); } -static CLASS_DEVICE_ATTR(id_ext, S_IRUGO, show_id_ext, NULL); -static CLASS_DEVICE_ATTR(ioc_guid, S_IRUGO, show_ioc_guid, NULL); -static CLASS_DEVICE_ATTR(service_id, S_IRUGO, show_service_id, NULL); -static CLASS_DEVICE_ATTR(pkey, S_IRUGO, show_pkey, NULL); -static CLASS_DEVICE_ATTR(dgid, S_IRUGO, show_dgid, NULL); -static CLASS_DEVICE_ATTR(orig_dgid, S_IRUGO, show_orig_dgid, NULL); -static CLASS_DEVICE_ATTR(zero_req_lim, S_IRUGO, show_zero_req_lim, NULL); -static CLASS_DEVICE_ATTR(local_ib_port, S_IRUGO, show_local_ib_port, NULL); -static CLASS_DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL); - -static struct class_device_attribute *srp_host_attrs[] = { - &class_device_attr_id_ext, - &class_device_attr_ioc_guid, - &class_device_attr_service_id, - &class_device_attr_pkey, - &class_device_attr_dgid, - &class_device_attr_orig_dgid, - &class_device_attr_zero_req_lim, - &class_device_attr_local_ib_port, - &class_device_attr_local_ib_device, +static DEVICE_ATTR(id_ext, S_IRUGO, show_id_ext, NULL); +static DEVICE_ATTR(ioc_guid, S_IRUGO, show_ioc_guid, NULL); +static DEVICE_ATTR(service_id, S_IRUGO, show_service_id, NULL); +static DEVICE_ATTR(pkey, S_IRUGO, show_pkey, NULL); +static DEVICE_ATTR(dgid, S_IRUGO, show_dgid, NULL); +static DEVICE_ATTR(orig_dgid, S_IRUGO, show_orig_dgid, NULL); +static DEVICE_ATTR(zero_req_lim, S_IRUGO, show_zero_req_lim, NULL); +static DEVICE_ATTR(local_ib_port, S_IRUGO, show_local_ib_port, NULL); +static DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL); + +static struct device_attribute *srp_host_attrs[] = { + &dev_attr_id_ext, + &dev_attr_ioc_guid, + &dev_attr_service_id, + &dev_attr_pkey, + &dev_attr_dgid, + &dev_attr_orig_dgid, + &dev_attr_zero_req_lim, + &dev_attr_local_ib_port, + &dev_attr_local_ib_device, NULL }; @@ -1613,7 +1624,7 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target) sprintf(target->target_name, "SRP.T10:%016llX", (unsigned long long) be64_to_cpu(target->id_ext)); - if (scsi_add_host(target->scsi_host, host->dev->dev->dma_device)) + if (scsi_add_host(target->scsi_host, host->srp_dev->dev->dma_device)) return -ENODEV; memcpy(ids.port_id, &target->id_ext, 8); @@ -1637,17 +1648,17 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target) return 0; } -static void srp_release_class_dev(struct class_device *class_dev) +static void srp_release_dev(struct device *dev) { struct srp_host *host = - container_of(class_dev, struct srp_host, class_dev); + container_of(dev, struct srp_host, dev); complete(&host->released); } static struct class srp_class = { .name = "infiniband_srp", - .release = srp_release_class_dev + .dev_release = srp_release_dev }; /* @@ -1835,11 +1846,12 @@ out: return ret; } -static ssize_t srp_create_target(struct class_device *class_dev, +static ssize_t srp_create_target(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { struct srp_host *host = - container_of(class_dev, struct srp_host, class_dev); + container_of(dev, struct srp_host, dev); struct Scsi_Host *target_host; struct srp_target_port *target; int ret; @@ -1871,7 +1883,8 @@ static ssize_t srp_create_target(struct class_device *class_dev, if (ret) goto err; - ib_get_cached_gid(host->dev->dev, host->port, 0, &target->path.sgid); + ib_get_cached_gid(host->srp_dev->dev, host->port, 0, + &target->path.sgid); shost_printk(KERN_DEBUG, target->scsi_host, PFX "new target: id_ext %016llx ioc_guid %016llx pkey %04x " @@ -1926,27 +1939,27 @@ err: return ret; } -static CLASS_DEVICE_ATTR(add_target, S_IWUSR, NULL, srp_create_target); +static DEVICE_ATTR(add_target, S_IWUSR, NULL, srp_create_target); -static ssize_t show_ibdev(struct class_device *class_dev, char *buf) +static ssize_t show_ibdev(struct device *dev, struct device_attribute *attr, + char *buf) { - struct srp_host *host = - container_of(class_dev, struct srp_host, class_dev); + struct srp_host *host = container_of(dev, struct srp_host, dev); - return sprintf(buf, "%s\n", host->dev->dev->name); + return sprintf(buf, "%s\n", host->srp_dev->dev->name); } -static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); +static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); -static ssize_t show_port(struct class_device *class_dev, char *buf) +static ssize_t show_port(struct device *dev, struct device_attribute *attr, + char *buf) { - struct srp_host *host = - container_of(class_dev, struct srp_host, class_dev); + struct srp_host *host = container_of(dev, struct srp_host, dev); return sprintf(buf, "%d\n", host->port); } -static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL); +static DEVICE_ATTR(port, S_IRUGO, show_port, NULL); static struct srp_host *srp_add_port(struct srp_device *device, u8 port) { @@ -1959,27 +1972,27 @@ static struct srp_host *srp_add_port(struct srp_device *device, u8 port) INIT_LIST_HEAD(&host->target_list); spin_lock_init(&host->target_lock); init_completion(&host->released); - host->dev = device; + host->srp_dev = device; host->port = port; - host->class_dev.class = &srp_class; - host->class_dev.dev = device->dev->dma_device; - snprintf(host->class_dev.class_id, BUS_ID_SIZE, "srp-%s-%d", + host->dev.class = &srp_class; + host->dev.parent = device->dev->dma_device; + snprintf(host->dev.bus_id, BUS_ID_SIZE, "srp-%s-%d", device->dev->name, port); - if (class_device_register(&host->class_dev)) + if (device_register(&host->dev)) goto free_host; - if (class_device_create_file(&host->class_dev, &class_device_attr_add_target)) + if (device_create_file(&host->dev, &dev_attr_add_target)) goto err_class; - if (class_device_create_file(&host->class_dev, &class_device_attr_ibdev)) + if (device_create_file(&host->dev, &dev_attr_ibdev)) goto err_class; - if (class_device_create_file(&host->class_dev, &class_device_attr_port)) + if (device_create_file(&host->dev, &dev_attr_port)) goto err_class; return host; err_class: - class_device_unregister(&host->class_dev); + device_unregister(&host->dev); free_host: kfree(host); @@ -2084,7 +2097,7 @@ static void srp_remove_one(struct ib_device *device) srp_dev = ib_get_client_data(device, &srp_client); list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) { - class_device_unregister(&host->class_dev); + device_unregister(&host->dev); /* * Wait for the sysfs entry to go away, so that no new * target ports can be created. @@ -2138,6 +2151,11 @@ static int __init srp_init_module(void) { int ret; + if (srp_sg_tablesize > 255) { + printk(KERN_WARNING PFX "Clamping srp_sg_tablesize to 255\n"); + srp_sg_tablesize = 255; + } + ib_srp_transport_template = srp_attach_transport(&ib_srp_transport_functions); if (!ib_srp_transport_template) diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h index cb6eb816024..63d2ae72406 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.h +++ b/drivers/infiniband/ulp/srp/ib_srp.h @@ -97,9 +97,9 @@ struct srp_device { }; struct srp_host { - struct srp_device *dev; + struct srp_device *srp_dev; u8 port; - struct class_device class_dev; + struct device dev; struct list_head target_list; spinlock_t target_lock; struct completion released; |