aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/ulp/ipoib/ipoib_ib.c
diff options
context:
space:
mode:
authorErez Shitrit <erezsh@mellanox.com>2015-04-02 06:39:00 -0400
committerDoug Ledford <dledford@redhat.com>2015-04-15 16:06:18 -0400
commita44878d100630a34a44f54960115b81e449858db (patch)
tree31acd864cb26c0161664c9e2cf922f057723e35b /drivers/infiniband/ulp/ipoib/ipoib_ib.c
parent1c0453d64a341909bbf89cb68c9edaa6cff93850 (diff)
IB/ipoib: Use one linear skb in RX flow
The current code in the RX flow uses two sg entries for each incoming packet, the first one was for the IB headers and the second for the rest of the data, that causes two dma map/unmap and two allocations, and few more actions that were done at the data path. Use only one linear skb on each incoming packet, for the data (IB headers and payload), that reduces the packet processing in the data-path (only one skb, no frags, the first frag was not used anyway, less memory allocations) and the dma handling (only one dma map/unmap over each incoming packet instead of two map/unmap per each incoming packet). After commit 73d3fe6d1c6d ("gro: fix aggregation for skb using frag_list") from Eric Dumazet, we will get full aggregation for large packets. When running bandwidth tests before and after the (over the card's numa node), using "netperf -H 1.1.1.3 -T -t TCP_STREAM", the results before are ~12Gbs before and after ~16Gbs on my setup (Mellanox's ConnectX3). Signed-off-by: Erez Shitrit <erezsh@mellanox.com> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
Diffstat (limited to 'drivers/infiniband/ulp/ipoib/ipoib_ib.c')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c67
1 files changed, 9 insertions, 58 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index e144d07d53cc..29b376dadd2b 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -94,39 +94,9 @@ void ipoib_free_ah(struct kref *kref)
94static void ipoib_ud_dma_unmap_rx(struct ipoib_dev_priv *priv, 94static void ipoib_ud_dma_unmap_rx(struct ipoib_dev_priv *priv,
95 u64 mapping[IPOIB_UD_RX_SG]) 95 u64 mapping[IPOIB_UD_RX_SG])
96{ 96{
97 if (ipoib_ud_need_sg(priv->max_ib_mtu)) { 97 ib_dma_unmap_single(priv->ca, mapping[0],
98 ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_UD_HEAD_SIZE, 98 IPOIB_UD_BUF_SIZE(priv->max_ib_mtu),
99 DMA_FROM_DEVICE); 99 DMA_FROM_DEVICE);
100 ib_dma_unmap_page(priv->ca, mapping[1], PAGE_SIZE,
101 DMA_FROM_DEVICE);
102 } else
103 ib_dma_unmap_single(priv->ca, mapping[0],
104 IPOIB_UD_BUF_SIZE(priv->max_ib_mtu),
105 DMA_FROM_DEVICE);
106}
107
108static void ipoib_ud_skb_put_frags(struct ipoib_dev_priv *priv,
109 struct sk_buff *skb,
110 unsigned int length)
111{
112 if (ipoib_ud_need_sg(priv->max_ib_mtu)) {
113 skb_frag_t *frag = &skb_shinfo(skb)->frags[0];
114 unsigned int size;
115 /*
116 * There is only two buffers needed for max_payload = 4K,
117 * first buf size is IPOIB_UD_HEAD_SIZE
118 */
119 skb->tail += IPOIB_UD_HEAD_SIZE;
120 skb->len += length;
121
122 size = length - IPOIB_UD_HEAD_SIZE;
123
124 skb_frag_size_set(frag, size);
125 skb->data_len += size;
126 skb->truesize += PAGE_SIZE;
127 } else
128 skb_put(skb, length);
129
130} 100}
131 101
132static int ipoib_ib_post_receive(struct net_device *dev, int id) 102static int ipoib_ib_post_receive(struct net_device *dev, int id)
@@ -156,18 +126,11 @@ static struct sk_buff *ipoib_alloc_rx_skb(struct net_device *dev, int id)
156 struct ipoib_dev_priv *priv = netdev_priv(dev); 126 struct ipoib_dev_priv *priv = netdev_priv(dev);
157 struct sk_buff *skb; 127 struct sk_buff *skb;
158 int buf_size; 128 int buf_size;
159 int tailroom;
160 u64 *mapping; 129 u64 *mapping;
161 130
162 if (ipoib_ud_need_sg(priv->max_ib_mtu)) { 131 buf_size = IPOIB_UD_BUF_SIZE(priv->max_ib_mtu);
163 buf_size = IPOIB_UD_HEAD_SIZE;
164 tailroom = 128; /* reserve some tailroom for IP/TCP headers */
165 } else {
166 buf_size = IPOIB_UD_BUF_SIZE(priv->max_ib_mtu);
167 tailroom = 0;
168 }
169 132
170 skb = dev_alloc_skb(buf_size + tailroom + 4); 133 skb = dev_alloc_skb(buf_size + IPOIB_ENCAP_LEN);
171 if (unlikely(!skb)) 134 if (unlikely(!skb))
172 return NULL; 135 return NULL;
173 136
@@ -184,23 +147,8 @@ static struct sk_buff *ipoib_alloc_rx_skb(struct net_device *dev, int id)
184 if (unlikely(ib_dma_mapping_error(priv->ca, mapping[0]))) 147 if (unlikely(ib_dma_mapping_error(priv->ca, mapping[0])))
185 goto error; 148 goto error;
186 149
187 if (ipoib_ud_need_sg(priv->max_ib_mtu)) {
188 struct page *page = alloc_page(GFP_ATOMIC);
189 if (!page)
190 goto partial_error;
191 skb_fill_page_desc(skb, 0, page, 0, PAGE_SIZE);
192 mapping[1] =
193 ib_dma_map_page(priv->ca, page,
194 0, PAGE_SIZE, DMA_FROM_DEVICE);
195 if (unlikely(ib_dma_mapping_error(priv->ca, mapping[1])))
196 goto partial_error;
197 }
198
199 priv->rx_ring[id].skb = skb; 150 priv->rx_ring[id].skb = skb;
200 return skb; 151 return skb;
201
202partial_error:
203 ib_dma_unmap_single(priv->ca, mapping[0], buf_size, DMA_FROM_DEVICE);
204error: 152error:
205 dev_kfree_skb_any(skb); 153 dev_kfree_skb_any(skb);
206 return NULL; 154 return NULL;
@@ -278,7 +226,8 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
278 wc->byte_len, wc->slid); 226 wc->byte_len, wc->slid);
279 227
280 ipoib_ud_dma_unmap_rx(priv, mapping); 228 ipoib_ud_dma_unmap_rx(priv, mapping);
281 ipoib_ud_skb_put_frags(priv, skb, wc->byte_len); 229
230 skb_put(skb, wc->byte_len);
282 231
283 /* First byte of dgid signals multicast when 0xff */ 232 /* First byte of dgid signals multicast when 0xff */
284 dgid = &((struct ib_grh *)skb->data)->dgid; 233 dgid = &((struct ib_grh *)skb->data)->dgid;
@@ -296,6 +245,8 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
296 skb_reset_mac_header(skb); 245 skb_reset_mac_header(skb);
297 skb_pull(skb, IPOIB_ENCAP_LEN); 246 skb_pull(skb, IPOIB_ENCAP_LEN);
298 247
248 skb->truesize = SKB_TRUESIZE(skb->len);
249
299 ++dev->stats.rx_packets; 250 ++dev->stats.rx_packets;
300 dev->stats.rx_bytes += skb->len; 251 dev->stats.rx_bytes += skb->len;
301 252