Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 229253
b: refs/heads/master
c: f5a4953
h: refs/heads/master
i:
  229251: 540516d
v: v3
  • Loading branch information
Roland Dreier committed Jan 11, 2011
1 parent 29d6719 commit 8c5f002
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 8 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8ae31e5b1fc73751d800d551fb30340caa53c7dd
refs/heads/master: f5a49539a64ae5e3833fddec54a3c2524c7fe333
1 change: 1 addition & 0 deletions trunk/drivers/infiniband/ulp/ipoib/Kconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
config INFINIBAND_IPOIB
tristate "IP-over-InfiniBand"
depends on NETDEVICES && INET && (IPV6 || IPV6=n)
select INET_LRO
---help---
Support for the IP-over-InfiniBand protocol (IPoIB). This
transports IP packets over InfiniBand so you can use your IB
Expand Down
12 changes: 11 additions & 1 deletion trunk/drivers/infiniband/ulp/ipoib/ipoib.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
#include <rdma/ib_verbs.h>
#include <rdma/ib_pack.h>
#include <rdma/ib_sa.h>
#include <linux/sched.h>
#include <linux/inet_lro.h>

/* constants */

Expand Down Expand Up @@ -100,6 +100,9 @@ enum {
IPOIB_MCAST_FLAG_BUSY = 2, /* joining or already joined */
IPOIB_MCAST_FLAG_ATTACHED = 3,

IPOIB_MAX_LRO_DESCRIPTORS = 8,
IPOIB_LRO_MAX_AGGR = 64,

MAX_SEND_CQE = 16,
IPOIB_CM_COPYBREAK = 256,
};
Expand Down Expand Up @@ -259,6 +262,11 @@ struct ipoib_ethtool_st {
u16 max_coalesced_frames;
};

struct ipoib_lro {
struct net_lro_mgr lro_mgr;
struct net_lro_desc lro_desc[IPOIB_MAX_LRO_DESCRIPTORS];
};

/*
* Device private locking: network stack tx_lock protects members used
* in TX fast path, lock protects everything else. lock nests inside
Expand Down Expand Up @@ -344,6 +352,8 @@ struct ipoib_dev_priv {
int hca_caps;
struct ipoib_ethtool_st ethtool;
struct timer_list poll_timer;

struct ipoib_lro lro;
};

struct ipoib_ah {
Expand Down
1 change: 0 additions & 1 deletion trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1480,7 +1480,6 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr,

if (test_bit(IPOIB_FLAG_CSUM, &priv->flags)) {
dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
priv->dev->features |= NETIF_F_GRO;
if (priv->hca_caps & IB_DEVICE_UD_TSO)
dev->features |= NETIF_F_TSO;
}
Expand Down
51 changes: 51 additions & 0 deletions trunk/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,63 @@ static int ipoib_set_coalesce(struct net_device *dev,
return 0;
}

static const char ipoib_stats_keys[][ETH_GSTRING_LEN] = {
"LRO aggregated", "LRO flushed",
"LRO avg aggr", "LRO no desc"
};

static void ipoib_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
{
switch (stringset) {
case ETH_SS_STATS:
memcpy(data, *ipoib_stats_keys, sizeof(ipoib_stats_keys));
break;
}
}

static int ipoib_get_sset_count(struct net_device *dev, int sset)
{
switch (sset) {
case ETH_SS_STATS:
return ARRAY_SIZE(ipoib_stats_keys);
default:
return -EOPNOTSUPP;
}
}

static void ipoib_get_ethtool_stats(struct net_device *dev,
struct ethtool_stats *stats, uint64_t *data)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
int index = 0;

/* Get LRO statistics */
data[index++] = priv->lro.lro_mgr.stats.aggregated;
data[index++] = priv->lro.lro_mgr.stats.flushed;
if (priv->lro.lro_mgr.stats.flushed)
data[index++] = priv->lro.lro_mgr.stats.aggregated /
priv->lro.lro_mgr.stats.flushed;
else
data[index++] = 0;
data[index++] = priv->lro.lro_mgr.stats.no_desc;
}

static int ipoib_set_flags(struct net_device *dev, u32 flags)
{
return ethtool_op_set_flags(dev, flags, ETH_FLAG_LRO);
}

static const struct ethtool_ops ipoib_ethtool_ops = {
.get_drvinfo = ipoib_get_drvinfo,
.get_rx_csum = ipoib_get_rx_csum,
.set_tso = ipoib_set_tso,
.get_coalesce = ipoib_get_coalesce,
.set_coalesce = ipoib_set_coalesce,
.get_flags = ethtool_op_get_flags,
.set_flags = ipoib_set_flags,
.get_strings = ipoib_get_strings,
.get_sset_count = ipoib_get_sset_count,
.get_ethtool_stats = ipoib_get_ethtool_stats,
};

void ipoib_set_ethtool_ops(struct net_device *dev)
Expand Down
8 changes: 7 additions & 1 deletion trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,10 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
if (test_bit(IPOIB_FLAG_CSUM, &priv->flags) && likely(wc->csum_ok))
skb->ip_summed = CHECKSUM_UNNECESSARY;

napi_gro_receive(&priv->napi, skb);
if (dev->features & NETIF_F_LRO)
lro_receive_skb(&priv->lro.lro_mgr, skb, NULL);
else
netif_receive_skb(skb);

repost:
if (unlikely(ipoib_ib_post_receive(dev, wr_id)))
Expand Down Expand Up @@ -447,6 +450,9 @@ int ipoib_poll(struct napi_struct *napi, int budget)
}

if (done < budget) {
if (dev->features & NETIF_F_LRO)
lro_flush_all(&priv->lro.lro_mgr);

napi_complete(napi);
if (unlikely(ib_req_notify_cq(priv->recv_cq,
IB_CQ_NEXT_COMP |
Expand Down
62 changes: 61 additions & 1 deletion trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ MODULE_PARM_DESC(send_queue_size, "Number of descriptors in send queue");
module_param_named(recv_queue_size, ipoib_recvq_size, int, 0444);
MODULE_PARM_DESC(recv_queue_size, "Number of descriptors in receive queue");

static int lro;
module_param(lro, bool, 0444);
MODULE_PARM_DESC(lro, "Enable LRO (Large Receive Offload)");

static int lro_max_aggr = IPOIB_LRO_MAX_AGGR;
module_param(lro_max_aggr, int, 0644);
MODULE_PARM_DESC(lro_max_aggr, "LRO: Max packets to be aggregated "
"(default = 64)");

#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
int ipoib_debug_level;

Expand Down Expand Up @@ -967,6 +976,54 @@ static const struct header_ops ipoib_header_ops = {
.create = ipoib_hard_header,
};

static int get_skb_hdr(struct sk_buff *skb, void **iphdr,
void **tcph, u64 *hdr_flags, void *priv)
{
unsigned int ip_len;
struct iphdr *iph;

if (unlikely(skb->protocol != htons(ETH_P_IP)))
return -1;

/*
* In the future we may add an else clause that verifies the
* checksum and allows devices which do not calculate checksum
* to use LRO.
*/
if (unlikely(skb->ip_summed != CHECKSUM_UNNECESSARY))
return -1;

/* Check for non-TCP packet */
skb_reset_network_header(skb);
iph = ip_hdr(skb);
if (iph->protocol != IPPROTO_TCP)
return -1;

ip_len = ip_hdrlen(skb);
skb_set_transport_header(skb, ip_len);
*tcph = tcp_hdr(skb);

/* check if IP header and TCP header are complete */
if (ntohs(iph->tot_len) < ip_len + tcp_hdrlen(skb))
return -1;

*hdr_flags = LRO_IPV4 | LRO_TCP;
*iphdr = iph;

return 0;
}

static void ipoib_lro_setup(struct ipoib_dev_priv *priv)
{
priv->lro.lro_mgr.max_aggr = lro_max_aggr;
priv->lro.lro_mgr.max_desc = IPOIB_MAX_LRO_DESCRIPTORS;
priv->lro.lro_mgr.lro_arr = priv->lro.lro_desc;
priv->lro.lro_mgr.get_skb_header = get_skb_hdr;
priv->lro.lro_mgr.features = LRO_F_NAPI;
priv->lro.lro_mgr.dev = priv->dev;
priv->lro.lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
}

static const struct net_device_ops ipoib_netdev_ops = {
.ndo_open = ipoib_open,
.ndo_stop = ipoib_stop,
Expand Down Expand Up @@ -1010,6 +1067,8 @@ static void ipoib_setup(struct net_device *dev)

priv->dev = dev;

ipoib_lro_setup(priv);

spin_lock_init(&priv->lock);

mutex_init(&priv->vlan_mutex);
Expand Down Expand Up @@ -1159,7 +1218,8 @@ int ipoib_set_dev_features(struct ipoib_dev_priv *priv, struct ib_device *hca)
priv->dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
}

priv->dev->features |= NETIF_F_GRO;
if (lro)
priv->dev->features |= NETIF_F_LRO;

if (priv->dev->features & NETIF_F_SG && priv->hca_caps & IB_DEVICE_UD_TSO)
priv->dev->features |= NETIF_F_TSO;
Expand Down
4 changes: 1 addition & 3 deletions trunk/drivers/net/mlx4/fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,10 +289,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
MLX4_GET(field, outbox, QUERY_DEV_CAP_LOG_BF_REG_SZ_OFFSET);
dev_cap->bf_reg_size = 1 << (field & 0x1f);
MLX4_GET(field, outbox, QUERY_DEV_CAP_LOG_MAX_BF_REGS_PER_PAGE_OFFSET);
if ((1 << (field & 0x3f)) > (PAGE_SIZE / dev_cap->bf_reg_size)) {
mlx4_warn(dev, "firmware bug: log2 # of blue flame regs is invalid (%d), forcing 3\n", field & 0x1f);
if ((1 << (field & 0x3f)) > (PAGE_SIZE / dev_cap->bf_reg_size))
field = 3;
}
dev_cap->bf_regs_per_page = 1 << (field & 0x3f);
mlx4_dbg(dev, "BlueFlame available (reg size %d, regs/page %d)\n",
dev_cap->bf_reg_size, dev_cap->bf_regs_per_page);
Expand Down

0 comments on commit 8c5f002

Please sign in to comment.