aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/myricom/myri10ge
diff options
context:
space:
mode:
authorAndrew Gallatin <gallatin@myri.com>2012-11-30 03:31:58 -0500
committerDavid S. Miller <davem@davemloft.net>2012-11-30 13:44:04 -0500
commit4ca3221fe4b6c4c6c77352672942e8afa57d55e5 (patch)
tree4ceb69490b19d256e8b760535f854701066f8e7a /drivers/net/ethernet/myricom/myri10ge
parentba57b6f20429028127618230b74d55e8eb9cfce3 (diff)
myri10ge: Convert from LRO to GRO
Convert myri10ge from LRO to GRO, and simplify the driver by removing various LRO-related code which is no longer needed including ndo_fix_features op, custom skb building from frags, and LRO header parsing. Signed-off-by: Andrew Gallatin <gallatin@myri.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/myricom/myri10ge')
-rw-r--r--drivers/net/ethernet/myricom/myri10ge/myri10ge.c236
1 files changed, 34 insertions, 202 deletions
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 83516e3369c9..84207c04530f 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -50,7 +50,6 @@
50#include <linux/etherdevice.h> 50#include <linux/etherdevice.h>
51#include <linux/if_ether.h> 51#include <linux/if_ether.h>
52#include <linux/if_vlan.h> 52#include <linux/if_vlan.h>
53#include <linux/inet_lro.h>
54#include <linux/dca.h> 53#include <linux/dca.h>
55#include <linux/ip.h> 54#include <linux/ip.h>
56#include <linux/inet.h> 55#include <linux/inet.h>
@@ -96,8 +95,6 @@ MODULE_LICENSE("Dual BSD/GPL");
96 95
97#define MYRI10GE_EEPROM_STRINGS_SIZE 256 96#define MYRI10GE_EEPROM_STRINGS_SIZE 256
98#define MYRI10GE_MAX_SEND_DESC_TSO ((65536 / 2048) * 2) 97#define MYRI10GE_MAX_SEND_DESC_TSO ((65536 / 2048) * 2)
99#define MYRI10GE_MAX_LRO_DESCRIPTORS 8
100#define MYRI10GE_LRO_MAX_PKTS 64
101 98
102#define MYRI10GE_NO_CONFIRM_DATA htonl(0xffffffff) 99#define MYRI10GE_NO_CONFIRM_DATA htonl(0xffffffff)
103#define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff 100#define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff
@@ -165,8 +162,6 @@ struct myri10ge_rx_done {
165 dma_addr_t bus; 162 dma_addr_t bus;
166 int cnt; 163 int cnt;
167 int idx; 164 int idx;
168 struct net_lro_mgr lro_mgr;
169 struct net_lro_desc lro_desc[MYRI10GE_MAX_LRO_DESCRIPTORS];
170}; 165};
171 166
172struct myri10ge_slice_netstats { 167struct myri10ge_slice_netstats {
@@ -338,11 +333,6 @@ static int myri10ge_debug = -1; /* defaults above */
338module_param(myri10ge_debug, int, 0); 333module_param(myri10ge_debug, int, 0);
339MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)"); 334MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)");
340 335
341static int myri10ge_lro_max_pkts = MYRI10GE_LRO_MAX_PKTS;
342module_param(myri10ge_lro_max_pkts, int, S_IRUGO);
343MODULE_PARM_DESC(myri10ge_lro_max_pkts,
344 "Number of LRO packets to be aggregated");
345
346static int myri10ge_fill_thresh = 256; 336static int myri10ge_fill_thresh = 256;
347module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR); 337module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR);
348MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed"); 338MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed");
@@ -1197,36 +1187,6 @@ static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, __wsum hw_csum)
1197 } 1187 }
1198} 1188}
1199 1189
1200static inline void
1201myri10ge_rx_skb_build(struct sk_buff *skb, u8 * va,
1202 struct skb_frag_struct *rx_frags, int len, int hlen)
1203{
1204 struct skb_frag_struct *skb_frags;
1205
1206 skb->len = skb->data_len = len;
1207 /* attach the page(s) */
1208
1209 skb_frags = skb_shinfo(skb)->frags;
1210 while (len > 0) {
1211 memcpy(skb_frags, rx_frags, sizeof(*skb_frags));
1212 len -= skb_frag_size(rx_frags);
1213 skb_frags++;
1214 rx_frags++;
1215 skb_shinfo(skb)->nr_frags++;
1216 }
1217
1218 /* pskb_may_pull is not available in irq context, but
1219 * skb_pull() (for ether_pad and eth_type_trans()) requires
1220 * the beginning of the packet in skb_headlen(), move it
1221 * manually */
1222 skb_copy_to_linear_data(skb, va, hlen);
1223 skb_shinfo(skb)->frags[0].page_offset += hlen;
1224 skb_frag_size_sub(&skb_shinfo(skb)->frags[0], hlen);
1225 skb->data_len -= hlen;
1226 skb->tail += hlen;
1227 skb_pull(skb, MXGEFW_PAD);
1228}
1229
1230static void 1190static void
1231myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, 1191myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
1232 int bytes, int watchdog) 1192 int bytes, int watchdog)
@@ -1304,18 +1264,14 @@ myri10ge_unmap_rx_page(struct pci_dev *pdev,
1304 } 1264 }
1305} 1265}
1306 1266
1307#define MYRI10GE_HLEN 64 /* The number of bytes to copy from a
1308 * page into an skb */
1309
1310static inline int 1267static inline int
1311myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum, 1268myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum)
1312 bool lro_enabled)
1313{ 1269{
1314 struct myri10ge_priv *mgp = ss->mgp; 1270 struct myri10ge_priv *mgp = ss->mgp;
1315 struct sk_buff *skb; 1271 struct sk_buff *skb;
1316 struct skb_frag_struct rx_frags[MYRI10GE_MAX_FRAGS_PER_FRAME]; 1272 struct skb_frag_struct *rx_frags;
1317 struct myri10ge_rx_buf *rx; 1273 struct myri10ge_rx_buf *rx;
1318 int i, idx, hlen, remainder, bytes; 1274 int i, idx, remainder, bytes;
1319 struct pci_dev *pdev = mgp->pdev; 1275 struct pci_dev *pdev = mgp->pdev;
1320 struct net_device *dev = mgp->dev; 1276 struct net_device *dev = mgp->dev;
1321 u8 *va; 1277 u8 *va;
@@ -1332,67 +1288,47 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum,
1332 idx = rx->cnt & rx->mask; 1288 idx = rx->cnt & rx->mask;
1333 va = page_address(rx->info[idx].page) + rx->info[idx].page_offset; 1289 va = page_address(rx->info[idx].page) + rx->info[idx].page_offset;
1334 prefetch(va); 1290 prefetch(va);
1291
1292 skb = napi_get_frags(&ss->napi);
1293 if (unlikely(skb == NULL)) {
1294 ss->stats.rx_dropped++;
1295 for (i = 0, remainder = len; remainder > 0; i++) {
1296 myri10ge_unmap_rx_page(pdev, &rx->info[idx], bytes);
1297 put_page(rx->info[idx].page);
1298 rx->cnt++;
1299 idx = rx->cnt & rx->mask;
1300 remainder -= MYRI10GE_ALLOC_SIZE;
1301 }
1302 return 0;
1303 }
1304 rx_frags = skb_shinfo(skb)->frags;
1335 /* Fill skb_frag_struct(s) with data from our receive */ 1305 /* Fill skb_frag_struct(s) with data from our receive */
1336 for (i = 0, remainder = len; remainder > 0; i++) { 1306 for (i = 0, remainder = len; remainder > 0; i++) {
1337 myri10ge_unmap_rx_page(pdev, &rx->info[idx], bytes); 1307 myri10ge_unmap_rx_page(pdev, &rx->info[idx], bytes);
1338 __skb_frag_set_page(&rx_frags[i], rx->info[idx].page); 1308 skb_fill_page_desc(skb, i, rx->info[idx].page,
1339 rx_frags[i].page_offset = rx->info[idx].page_offset; 1309 rx->info[idx].page_offset,
1340 if (remainder < MYRI10GE_ALLOC_SIZE) 1310 remainder < MYRI10GE_ALLOC_SIZE ?
1341 skb_frag_size_set(&rx_frags[i], remainder); 1311 remainder : MYRI10GE_ALLOC_SIZE);
1342 else
1343 skb_frag_size_set(&rx_frags[i], MYRI10GE_ALLOC_SIZE);
1344 rx->cnt++; 1312 rx->cnt++;
1345 idx = rx->cnt & rx->mask; 1313 idx = rx->cnt & rx->mask;
1346 remainder -= MYRI10GE_ALLOC_SIZE; 1314 remainder -= MYRI10GE_ALLOC_SIZE;
1347 } 1315 }
1348 1316
1349 if (lro_enabled) { 1317 /* remove padding */
1350 rx_frags[0].page_offset += MXGEFW_PAD; 1318 rx_frags[0].page_offset += MXGEFW_PAD;
1351 skb_frag_size_sub(&rx_frags[0], MXGEFW_PAD); 1319 rx_frags[0].size -= MXGEFW_PAD;
1352 len -= MXGEFW_PAD; 1320 len -= MXGEFW_PAD;
1353 lro_receive_frags(&ss->rx_done.lro_mgr, rx_frags,
1354 /* opaque, will come back in get_frag_header */
1355 len, len,
1356 (void *)(__force unsigned long)csum, csum);
1357 1321
1358 return 1; 1322 skb->len = len;
1359 } 1323 skb->data_len = len;
1360 1324 skb->truesize += len;
1361 hlen = MYRI10GE_HLEN > len ? len : MYRI10GE_HLEN; 1325 if (dev->features & NETIF_F_RXCSUM) {
1362 1326 skb->ip_summed = CHECKSUM_COMPLETE;
1363 /* allocate an skb to attach the page(s) to. This is done 1327 skb->csum = csum;
1364 * after trying LRO, so as to avoid skb allocation overheads */
1365
1366 skb = netdev_alloc_skb(dev, MYRI10GE_HLEN + 16);
1367 if (unlikely(skb == NULL)) {
1368 ss->stats.rx_dropped++;
1369 do {
1370 i--;
1371 __skb_frag_unref(&rx_frags[i]);
1372 } while (i != 0);
1373 return 0;
1374 }
1375
1376 /* Attach the pages to the skb, and trim off any padding */
1377 myri10ge_rx_skb_build(skb, va, rx_frags, len, hlen);
1378 if (skb_frag_size(&skb_shinfo(skb)->frags[0]) <= 0) {
1379 skb_frag_unref(skb, 0);
1380 skb_shinfo(skb)->nr_frags = 0;
1381 } else {
1382 skb->truesize += bytes * skb_shinfo(skb)->nr_frags;
1383 } 1328 }
1384 skb->protocol = eth_type_trans(skb, dev);
1385 skb_record_rx_queue(skb, ss - &mgp->ss[0]); 1329 skb_record_rx_queue(skb, ss - &mgp->ss[0]);
1386 1330
1387 if (dev->features & NETIF_F_RXCSUM) { 1331 napi_gro_frags(&ss->napi);
1388 if ((skb->protocol == htons(ETH_P_IP)) ||
1389 (skb->protocol == htons(ETH_P_IPV6))) {
1390 skb->csum = csum;
1391 skb->ip_summed = CHECKSUM_COMPLETE;
1392 } else
1393 myri10ge_vlan_ip_csum(skb, csum);
1394 }
1395 netif_receive_skb(skb);
1396 return 1; 1332 return 1;
1397} 1333}
1398 1334
@@ -1480,18 +1416,11 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget)
1480 u16 length; 1416 u16 length;
1481 __wsum checksum; 1417 __wsum checksum;
1482 1418
1483 /*
1484 * Prevent compiler from generating more than one ->features memory
1485 * access to avoid theoretical race condition with functions that
1486 * change NETIF_F_LRO flag at runtime.
1487 */
1488 bool lro_enabled = !!(ACCESS_ONCE(mgp->dev->features) & NETIF_F_LRO);
1489
1490 while (rx_done->entry[idx].length != 0 && work_done < budget) { 1419 while (rx_done->entry[idx].length != 0 && work_done < budget) {
1491 length = ntohs(rx_done->entry[idx].length); 1420 length = ntohs(rx_done->entry[idx].length);
1492 rx_done->entry[idx].length = 0; 1421 rx_done->entry[idx].length = 0;
1493 checksum = csum_unfold(rx_done->entry[idx].checksum); 1422 checksum = csum_unfold(rx_done->entry[idx].checksum);
1494 rx_ok = myri10ge_rx_done(ss, length, checksum, lro_enabled); 1423 rx_ok = myri10ge_rx_done(ss, length, checksum);
1495 rx_packets += rx_ok; 1424 rx_packets += rx_ok;
1496 rx_bytes += rx_ok * (unsigned long)length; 1425 rx_bytes += rx_ok * (unsigned long)length;
1497 cnt++; 1426 cnt++;
@@ -1503,9 +1432,6 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget)
1503 ss->stats.rx_packets += rx_packets; 1432 ss->stats.rx_packets += rx_packets;
1504 ss->stats.rx_bytes += rx_bytes; 1433 ss->stats.rx_bytes += rx_bytes;
1505 1434
1506 if (lro_enabled)
1507 lro_flush_all(&rx_done->lro_mgr);
1508
1509 /* restock receive rings if needed */ 1435 /* restock receive rings if needed */
1510 if (ss->rx_small.fill_cnt - ss->rx_small.cnt < myri10ge_fill_thresh) 1436 if (ss->rx_small.fill_cnt - ss->rx_small.cnt < myri10ge_fill_thresh)
1511 myri10ge_alloc_rx_pages(mgp, &ss->rx_small, 1437 myri10ge_alloc_rx_pages(mgp, &ss->rx_small,
@@ -1779,7 +1705,6 @@ static const char myri10ge_gstrings_slice_stats[][ETH_GSTRING_LEN] = {
1779 "tx_pkt_start", "tx_pkt_done", "tx_req", "tx_done", 1705 "tx_pkt_start", "tx_pkt_done", "tx_req", "tx_done",
1780 "rx_small_cnt", "rx_big_cnt", 1706 "rx_small_cnt", "rx_big_cnt",
1781 "wake_queue", "stop_queue", "tx_linearized", 1707 "wake_queue", "stop_queue", "tx_linearized",
1782 "LRO aggregated", "LRO flushed", "LRO avg aggr", "LRO no_desc",
1783}; 1708};
1784 1709
1785#define MYRI10GE_NET_STATS_LEN 21 1710#define MYRI10GE_NET_STATS_LEN 21
@@ -1880,14 +1805,6 @@ myri10ge_get_ethtool_stats(struct net_device *netdev,
1880 data[i++] = (unsigned int)ss->tx.wake_queue; 1805 data[i++] = (unsigned int)ss->tx.wake_queue;
1881 data[i++] = (unsigned int)ss->tx.stop_queue; 1806 data[i++] = (unsigned int)ss->tx.stop_queue;
1882 data[i++] = (unsigned int)ss->tx.linearized; 1807 data[i++] = (unsigned int)ss->tx.linearized;
1883 data[i++] = ss->rx_done.lro_mgr.stats.aggregated;
1884 data[i++] = ss->rx_done.lro_mgr.stats.flushed;
1885 if (ss->rx_done.lro_mgr.stats.flushed)
1886 data[i++] = ss->rx_done.lro_mgr.stats.aggregated /
1887 ss->rx_done.lro_mgr.stats.flushed;
1888 else
1889 data[i++] = 0;
1890 data[i++] = ss->rx_done.lro_mgr.stats.no_desc;
1891 } 1808 }
1892} 1809}
1893 1810
@@ -2271,67 +2188,6 @@ static void myri10ge_free_irq(struct myri10ge_priv *mgp)
2271 pci_disable_msix(pdev); 2188 pci_disable_msix(pdev);
2272} 2189}
2273 2190
2274static int
2275myri10ge_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr,
2276 void **ip_hdr, void **tcpudp_hdr,
2277 u64 * hdr_flags, void *priv)
2278{
2279 struct ethhdr *eh;
2280 struct vlan_ethhdr *veh;
2281 struct iphdr *iph;
2282 u8 *va = skb_frag_address(frag);
2283 unsigned long ll_hlen;
2284 /* passed opaque through lro_receive_frags() */
2285 __wsum csum = (__force __wsum) (unsigned long)priv;
2286
2287 /* find the mac header, aborting if not IPv4 */
2288
2289 eh = (struct ethhdr *)va;
2290 *mac_hdr = eh;
2291 ll_hlen = ETH_HLEN;
2292 if (eh->h_proto != htons(ETH_P_IP)) {
2293 if (eh->h_proto == htons(ETH_P_8021Q)) {
2294 veh = (struct vlan_ethhdr *)va;
2295 if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP))
2296 return -1;
2297
2298 ll_hlen += VLAN_HLEN;
2299
2300 /*
2301 * HW checksum starts ETH_HLEN bytes into
2302 * frame, so we must subtract off the VLAN
2303 * header's checksum before csum can be used
2304 */
2305 csum = csum_sub(csum, csum_partial(va + ETH_HLEN,
2306 VLAN_HLEN, 0));
2307 } else {
2308 return -1;
2309 }
2310 }
2311 *hdr_flags = LRO_IPV4;
2312
2313 iph = (struct iphdr *)(va + ll_hlen);
2314 *ip_hdr = iph;
2315 if (iph->protocol != IPPROTO_TCP)
2316 return -1;
2317 if (ip_is_fragment(iph))
2318 return -1;
2319 *hdr_flags |= LRO_TCP;
2320 *tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2);
2321
2322 /* verify the IP checksum */
2323 if (unlikely(ip_fast_csum((u8 *) iph, iph->ihl)))
2324 return -1;
2325
2326 /* verify the checksum */
2327 if (unlikely(csum_tcpudp_magic(iph->saddr, iph->daddr,
2328 ntohs(iph->tot_len) - (iph->ihl << 2),
2329 IPPROTO_TCP, csum)))
2330 return -1;
2331
2332 return 0;
2333}
2334
2335static int myri10ge_get_txrx(struct myri10ge_priv *mgp, int slice) 2191static int myri10ge_get_txrx(struct myri10ge_priv *mgp, int slice)
2336{ 2192{
2337 struct myri10ge_cmd cmd; 2193 struct myri10ge_cmd cmd;
@@ -2402,7 +2258,6 @@ static int myri10ge_open(struct net_device *dev)
2402 struct myri10ge_cmd cmd; 2258 struct myri10ge_cmd cmd;
2403 int i, status, big_pow2, slice; 2259 int i, status, big_pow2, slice;
2404 u8 *itable; 2260 u8 *itable;
2405 struct net_lro_mgr *lro_mgr;
2406 2261
2407 if (mgp->running != MYRI10GE_ETH_STOPPED) 2262 if (mgp->running != MYRI10GE_ETH_STOPPED)
2408 return -EBUSY; 2263 return -EBUSY;
@@ -2513,19 +2368,6 @@ static int myri10ge_open(struct net_device *dev)
2513 goto abort_with_rings; 2368 goto abort_with_rings;
2514 } 2369 }
2515 2370
2516 lro_mgr = &ss->rx_done.lro_mgr;
2517 lro_mgr->dev = dev;
2518 lro_mgr->features = LRO_F_NAPI;
2519 lro_mgr->ip_summed = CHECKSUM_COMPLETE;
2520 lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY;
2521 lro_mgr->max_desc = MYRI10GE_MAX_LRO_DESCRIPTORS;
2522 lro_mgr->lro_arr = ss->rx_done.lro_desc;
2523 lro_mgr->get_frag_header = myri10ge_get_frag_header;
2524 lro_mgr->max_aggr = myri10ge_lro_max_pkts;
2525 lro_mgr->frag_align_pad = 2;
2526 if (lro_mgr->max_aggr > MAX_SKB_FRAGS)
2527 lro_mgr->max_aggr = MAX_SKB_FRAGS;
2528
2529 /* must happen prior to any irq */ 2371 /* must happen prior to any irq */
2530 napi_enable(&(ss)->napi); 2372 napi_enable(&(ss)->napi);
2531 } 2373 }
@@ -3143,15 +2985,6 @@ static int myri10ge_set_mac_address(struct net_device *dev, void *addr)
3143 return 0; 2985 return 0;
3144} 2986}
3145 2987
3146static netdev_features_t myri10ge_fix_features(struct net_device *dev,
3147 netdev_features_t features)
3148{
3149 if (!(features & NETIF_F_RXCSUM))
3150 features &= ~NETIF_F_LRO;
3151
3152 return features;
3153}
3154
3155static int myri10ge_change_mtu(struct net_device *dev, int new_mtu) 2988static int myri10ge_change_mtu(struct net_device *dev, int new_mtu)
3156{ 2989{
3157 struct myri10ge_priv *mgp = netdev_priv(dev); 2990 struct myri10ge_priv *mgp = netdev_priv(dev);
@@ -3878,7 +3711,6 @@ static const struct net_device_ops myri10ge_netdev_ops = {
3878 .ndo_get_stats64 = myri10ge_get_stats, 3711 .ndo_get_stats64 = myri10ge_get_stats,
3879 .ndo_validate_addr = eth_validate_addr, 3712 .ndo_validate_addr = eth_validate_addr,
3880 .ndo_change_mtu = myri10ge_change_mtu, 3713 .ndo_change_mtu = myri10ge_change_mtu,
3881 .ndo_fix_features = myri10ge_fix_features,
3882 .ndo_set_rx_mode = myri10ge_set_multicast_list, 3714 .ndo_set_rx_mode = myri10ge_set_multicast_list,
3883 .ndo_set_mac_address = myri10ge_set_mac_address, 3715 .ndo_set_mac_address = myri10ge_set_mac_address,
3884}; 3716};
@@ -4018,7 +3850,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
4018 3850
4019 netdev->netdev_ops = &myri10ge_netdev_ops; 3851 netdev->netdev_ops = &myri10ge_netdev_ops;
4020 netdev->mtu = myri10ge_initial_mtu; 3852 netdev->mtu = myri10ge_initial_mtu;
4021 netdev->hw_features = mgp->features | NETIF_F_LRO | NETIF_F_RXCSUM; 3853 netdev->hw_features = mgp->features | NETIF_F_RXCSUM;
4022 netdev->features = netdev->hw_features; 3854 netdev->features = netdev->hw_features;
4023 3855
4024 if (dac_enabled) 3856 if (dac_enabled)