aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/freescale/fec_main.c
diff options
context:
space:
mode:
authorNimrod Andy <B38611@freescale.com>2014-09-29 21:28:05 -0400
committerDavid S. Miller <davem@davemloft.net>2014-10-01 21:28:21 -0400
commit1b7bde6d659d30f171259cc2dfba8e5dab34e735 (patch)
tree93990ae75315127b3c75a5e4441923889268e78f /drivers/net/ethernet/freescale/fec_main.c
parentce1a4ea3f125863bfbcb1afb76590ee2b7b93fbf (diff)
net: fec: implement rx_copybreak to improve rx performance
- Copy short frames and keep the buffers mapped, re-allocate skb instead of memory copy for long frames. - Add support for setting/getting rx_copybreak using generic ethtool tunable Changes V3: * As Eric Dumazet's suggestion that removing the copybreak module parameter and only keep the ethtool API support for rx_copybreak. Changes V2: * Implements rx_copybreak * Rx_copybreak provides module parameter to change this value * Add tunable_ops support for rx_copybreak Signed-off-by: Fugang Duan <B38611@freescale.com> Signed-off-by: Frank Li <Frank.Li@freescale.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/freescale/fec_main.c')
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c208
1 files changed, 143 insertions, 65 deletions
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 2c7343473e1c..1f07db891ee8 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -236,6 +236,8 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
236#define FEC_PAUSE_FLAG_AUTONEG 0x1 236#define FEC_PAUSE_FLAG_AUTONEG 0x1
237#define FEC_PAUSE_FLAG_ENABLE 0x2 237#define FEC_PAUSE_FLAG_ENABLE 0x2
238 238
239#define COPYBREAK_DEFAULT 256
240
239#define TSO_HEADER_SIZE 128 241#define TSO_HEADER_SIZE 128
240/* Max number of allowed TCP segments for software TSO */ 242/* Max number of allowed TCP segments for software TSO */
241#define FEC_MAX_TSO_SEGS 100 243#define FEC_MAX_TSO_SEGS 100
@@ -1322,6 +1324,50 @@ fec_enet_tx(struct net_device *ndev)
1322 return; 1324 return;
1323} 1325}
1324 1326
1327static int
1328fec_enet_new_rxbdp(struct net_device *ndev, struct bufdesc *bdp, struct sk_buff *skb)
1329{
1330 struct fec_enet_private *fep = netdev_priv(ndev);
1331 int off;
1332
1333 off = ((unsigned long)skb->data) & fep->rx_align;
1334 if (off)
1335 skb_reserve(skb, fep->rx_align + 1 - off);
1336
1337 bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data,
1338 FEC_ENET_RX_FRSIZE - fep->rx_align,
1339 DMA_FROM_DEVICE);
1340 if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
1341 if (net_ratelimit())
1342 netdev_err(ndev, "Rx DMA memory map failed\n");
1343 return -ENOMEM;
1344 }
1345
1346 return 0;
1347}
1348
1349static bool fec_enet_copybreak(struct net_device *ndev, struct sk_buff **skb,
1350 struct bufdesc *bdp, u32 length)
1351{
1352 struct fec_enet_private *fep = netdev_priv(ndev);
1353 struct sk_buff *new_skb;
1354
1355 if (length > fep->rx_copybreak)
1356 return false;
1357
1358 new_skb = netdev_alloc_skb(ndev, length);
1359 if (!new_skb)
1360 return false;
1361
1362 dma_sync_single_for_cpu(&fep->pdev->dev, bdp->cbd_bufaddr,
1363 FEC_ENET_RX_FRSIZE - fep->rx_align,
1364 DMA_FROM_DEVICE);
1365 memcpy(new_skb->data, (*skb)->data, length);
1366 *skb = new_skb;
1367
1368 return true;
1369}
1370
1325/* During a receive, the cur_rx points to the current incoming buffer. 1371/* During a receive, the cur_rx points to the current incoming buffer.
1326 * When we update through the ring, if the next incoming buffer has 1372 * When we update through the ring, if the next incoming buffer has
1327 * not been given to the system, we just set the empty indicator, 1373 * not been given to the system, we just set the empty indicator,
@@ -1336,7 +1382,8 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
1336 struct fec_enet_priv_rx_q *rxq; 1382 struct fec_enet_priv_rx_q *rxq;
1337 struct bufdesc *bdp; 1383 struct bufdesc *bdp;
1338 unsigned short status; 1384 unsigned short status;
1339 struct sk_buff *skb; 1385 struct sk_buff *skb_new = NULL;
1386 struct sk_buff *skb;
1340 ushort pkt_len; 1387 ushort pkt_len;
1341 __u8 *data; 1388 __u8 *data;
1342 int pkt_received = 0; 1389 int pkt_received = 0;
@@ -1344,6 +1391,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
1344 bool vlan_packet_rcvd = false; 1391 bool vlan_packet_rcvd = false;
1345 u16 vlan_tag; 1392 u16 vlan_tag;
1346 int index = 0; 1393 int index = 0;
1394 bool is_copybreak;
1347 1395
1348#ifdef CONFIG_M532x 1396#ifdef CONFIG_M532x
1349 flush_cache_all(); 1397 flush_cache_all();
@@ -1401,11 +1449,27 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
1401 ndev->stats.rx_bytes += pkt_len; 1449 ndev->stats.rx_bytes += pkt_len;
1402 1450
1403 index = fec_enet_get_bd_index(rxq->rx_bd_base, bdp, fep); 1451 index = fec_enet_get_bd_index(rxq->rx_bd_base, bdp, fep);
1404 data = rxq->rx_skbuff[index]->data; 1452 skb = rxq->rx_skbuff[index];
1405 dma_sync_single_for_cpu(&fep->pdev->dev, bdp->cbd_bufaddr,
1406 FEC_ENET_RX_FRSIZE - fep->rx_align,
1407 DMA_FROM_DEVICE);
1408 1453
1454 /* The packet length includes FCS, but we don't want to
1455 * include that when passing upstream as it messes up
1456 * bridging applications.
1457 */
1458 is_copybreak = fec_enet_copybreak(ndev, &skb, bdp, pkt_len - 4);
1459 if (!is_copybreak) {
1460 skb_new = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE);
1461 if (unlikely(!skb_new)) {
1462 ndev->stats.rx_dropped++;
1463 goto rx_processing_done;
1464 }
1465 dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
1466 FEC_ENET_RX_FRSIZE - fep->rx_align,
1467 DMA_FROM_DEVICE);
1468 }
1469
1470 prefetch(skb->data - NET_IP_ALIGN);
1471 skb_put(skb, pkt_len - 4);
1472 data = skb->data;
1409 if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) 1473 if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
1410 swap_buffer(data, pkt_len); 1474 swap_buffer(data, pkt_len);
1411 1475
@@ -1422,62 +1486,48 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
1422 struct vlan_hdr *vlan_header = 1486 struct vlan_hdr *vlan_header =
1423 (struct vlan_hdr *) (data + ETH_HLEN); 1487 (struct vlan_hdr *) (data + ETH_HLEN);
1424 vlan_tag = ntohs(vlan_header->h_vlan_TCI); 1488 vlan_tag = ntohs(vlan_header->h_vlan_TCI);
1425 pkt_len -= VLAN_HLEN;
1426 1489
1427 vlan_packet_rcvd = true; 1490 vlan_packet_rcvd = true;
1491
1492 skb_copy_to_linear_data_offset(skb, VLAN_HLEN,
1493 data, (2 * ETH_ALEN));
1494 skb_pull(skb, VLAN_HLEN);
1428 } 1495 }
1429 1496
1430 /* This does 16 byte alignment, exactly what we need. 1497 skb->protocol = eth_type_trans(skb, ndev);
1431 * The packet length includes FCS, but we don't want to
1432 * include that when passing upstream as it messes up
1433 * bridging applications.
1434 */
1435 skb = netdev_alloc_skb(ndev, pkt_len - 4 + NET_IP_ALIGN);
1436 1498
1437 if (unlikely(!skb)) { 1499 /* Get receive timestamp from the skb */
1438 ndev->stats.rx_dropped++; 1500 if (fep->hwts_rx_en && fep->bufdesc_ex)
1439 } else { 1501 fec_enet_hwtstamp(fep, ebdp->ts,
1440 int payload_offset = (2 * ETH_ALEN); 1502 skb_hwtstamps(skb));
1441 skb_reserve(skb, NET_IP_ALIGN); 1503
1442 skb_put(skb, pkt_len - 4); /* Make room */ 1504 if (fep->bufdesc_ex &&
1443 1505 (fep->csum_flags & FLAG_RX_CSUM_ENABLED)) {
1444 /* Extract the frame data without the VLAN header. */ 1506 if (!(ebdp->cbd_esc & FLAG_RX_CSUM_ERROR)) {
1445 skb_copy_to_linear_data(skb, data, (2 * ETH_ALEN)); 1507 /* don't check it */
1446 if (vlan_packet_rcvd) 1508 skb->ip_summed = CHECKSUM_UNNECESSARY;
1447 payload_offset = (2 * ETH_ALEN) + VLAN_HLEN; 1509 } else {
1448 skb_copy_to_linear_data_offset(skb, (2 * ETH_ALEN), 1510 skb_checksum_none_assert(skb);
1449 data + payload_offset,
1450 pkt_len - 4 - (2 * ETH_ALEN));
1451
1452 skb->protocol = eth_type_trans(skb, ndev);
1453
1454 /* Get receive timestamp from the skb */
1455 if (fep->hwts_rx_en && fep->bufdesc_ex)
1456 fec_enet_hwtstamp(fep, ebdp->ts,
1457 skb_hwtstamps(skb));
1458
1459 if (fep->bufdesc_ex &&
1460 (fep->csum_flags & FLAG_RX_CSUM_ENABLED)) {
1461 if (!(ebdp->cbd_esc & FLAG_RX_CSUM_ERROR)) {
1462 /* don't check it */
1463 skb->ip_summed = CHECKSUM_UNNECESSARY;
1464 } else {
1465 skb_checksum_none_assert(skb);
1466 }
1467 } 1511 }
1512 }
1468 1513
1469 /* Handle received VLAN packets */ 1514 /* Handle received VLAN packets */
1470 if (vlan_packet_rcvd) 1515 if (vlan_packet_rcvd)
1471 __vlan_hwaccel_put_tag(skb, 1516 __vlan_hwaccel_put_tag(skb,
1472 htons(ETH_P_8021Q), 1517 htons(ETH_P_8021Q),
1473 vlan_tag); 1518 vlan_tag);
1474 1519
1475 napi_gro_receive(&fep->napi, skb); 1520 napi_gro_receive(&fep->napi, skb);
1521
1522 if (is_copybreak) {
1523 dma_sync_single_for_device(&fep->pdev->dev, bdp->cbd_bufaddr,
1524 FEC_ENET_RX_FRSIZE - fep->rx_align,
1525 DMA_FROM_DEVICE);
1526 } else {
1527 rxq->rx_skbuff[index] = skb_new;
1528 fec_enet_new_rxbdp(ndev, bdp, skb_new);
1476 } 1529 }
1477 1530
1478 dma_sync_single_for_device(&fep->pdev->dev, bdp->cbd_bufaddr,
1479 FEC_ENET_RX_FRSIZE - fep->rx_align,
1480 DMA_FROM_DEVICE);
1481rx_processing_done: 1531rx_processing_done:
1482 /* Clear the status flags for this buffer */ 1532 /* Clear the status flags for this buffer */
1483 status &= ~BD_ENET_RX_STATS; 1533 status &= ~BD_ENET_RX_STATS;
@@ -2392,6 +2442,44 @@ static void fec_enet_itr_coal_init(struct net_device *ndev)
2392 fec_enet_set_coalesce(ndev, &ec); 2442 fec_enet_set_coalesce(ndev, &ec);
2393} 2443}
2394 2444
2445static int fec_enet_get_tunable(struct net_device *netdev,
2446 const struct ethtool_tunable *tuna,
2447 void *data)
2448{
2449 struct fec_enet_private *fep = netdev_priv(netdev);
2450 int ret = 0;
2451
2452 switch (tuna->id) {
2453 case ETHTOOL_RX_COPYBREAK:
2454 *(u32 *)data = fep->rx_copybreak;
2455 break;
2456 default:
2457 ret = -EINVAL;
2458 break;
2459 }
2460
2461 return ret;
2462}
2463
2464static int fec_enet_set_tunable(struct net_device *netdev,
2465 const struct ethtool_tunable *tuna,
2466 const void *data)
2467{
2468 struct fec_enet_private *fep = netdev_priv(netdev);
2469 int ret = 0;
2470
2471 switch (tuna->id) {
2472 case ETHTOOL_RX_COPYBREAK:
2473 fep->rx_copybreak = *(u32 *)data;
2474 break;
2475 default:
2476 ret = -EINVAL;
2477 break;
2478 }
2479
2480 return ret;
2481}
2482
2395static const struct ethtool_ops fec_enet_ethtool_ops = { 2483static const struct ethtool_ops fec_enet_ethtool_ops = {
2396 .get_settings = fec_enet_get_settings, 2484 .get_settings = fec_enet_get_settings,
2397 .set_settings = fec_enet_set_settings, 2485 .set_settings = fec_enet_set_settings,
@@ -2408,6 +2496,8 @@ static const struct ethtool_ops fec_enet_ethtool_ops = {
2408 .get_sset_count = fec_enet_get_sset_count, 2496 .get_sset_count = fec_enet_get_sset_count,
2409#endif 2497#endif
2410 .get_ts_info = fec_enet_get_ts_info, 2498 .get_ts_info = fec_enet_get_ts_info,
2499 .get_tunable = fec_enet_get_tunable,
2500 .set_tunable = fec_enet_set_tunable,
2411}; 2501};
2412 2502
2413static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) 2503static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
@@ -2553,33 +2643,20 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue)
2553 struct sk_buff *skb; 2643 struct sk_buff *skb;
2554 struct bufdesc *bdp; 2644 struct bufdesc *bdp;
2555 struct fec_enet_priv_rx_q *rxq; 2645 struct fec_enet_priv_rx_q *rxq;
2556 unsigned int off;
2557 2646
2558 rxq = fep->rx_queue[queue]; 2647 rxq = fep->rx_queue[queue];
2559 bdp = rxq->rx_bd_base; 2648 bdp = rxq->rx_bd_base;
2560 for (i = 0; i < rxq->rx_ring_size; i++) { 2649 for (i = 0; i < rxq->rx_ring_size; i++) {
2561 dma_addr_t addr;
2562
2563 skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE); 2650 skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE);
2564 if (!skb) 2651 if (!skb)
2565 goto err_alloc; 2652 goto err_alloc;
2566 2653
2567 off = ((unsigned long)skb->data) & fep->rx_align; 2654 if (fec_enet_new_rxbdp(ndev, bdp, skb)) {
2568 if (off)
2569 skb_reserve(skb, fep->rx_align + 1 - off);
2570
2571 addr = dma_map_single(&fep->pdev->dev, skb->data,
2572 FEC_ENET_RX_FRSIZE - fep->rx_align, DMA_FROM_DEVICE);
2573
2574 if (dma_mapping_error(&fep->pdev->dev, addr)) {
2575 dev_kfree_skb(skb); 2655 dev_kfree_skb(skb);
2576 if (net_ratelimit())
2577 netdev_err(ndev, "Rx DMA memory map failed\n");
2578 goto err_alloc; 2656 goto err_alloc;
2579 } 2657 }
2580 2658
2581 rxq->rx_skbuff[i] = skb; 2659 rxq->rx_skbuff[i] = skb;
2582 bdp->cbd_bufaddr = addr;
2583 bdp->cbd_sc = BD_ENET_RX_EMPTY; 2660 bdp->cbd_sc = BD_ENET_RX_EMPTY;
2584 2661
2585 if (fep->bufdesc_ex) { 2662 if (fep->bufdesc_ex) {
@@ -3240,6 +3317,7 @@ fec_probe(struct platform_device *pdev)
3240 if (fep->bufdesc_ex && fep->ptp_clock) 3317 if (fep->bufdesc_ex && fep->ptp_clock)
3241 netdev_info(ndev, "registered PHC device %d\n", fep->dev_id); 3318 netdev_info(ndev, "registered PHC device %d\n", fep->dev_id);
3242 3319
3320 fep->rx_copybreak = COPYBREAK_DEFAULT;
3243 INIT_WORK(&fep->tx_timeout_work, fec_enet_timeout_work); 3321 INIT_WORK(&fep->tx_timeout_work, fec_enet_timeout_work);
3244 return 0; 3322 return 0;
3245 3323