diff options
-rw-r--r-- | drivers/net/pch_gbe/pch_gbe_main.c | 97 |
1 files changed, 55 insertions, 42 deletions
diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c index 4c9a7d4f3fca..f52d852569fb 100644 --- a/drivers/net/pch_gbe/pch_gbe_main.c +++ b/drivers/net/pch_gbe/pch_gbe_main.c | |||
@@ -29,6 +29,7 @@ const char pch_driver_version[] = DRV_VERSION; | |||
29 | #define PCH_GBE_SHORT_PKT 64 | 29 | #define PCH_GBE_SHORT_PKT 64 |
30 | #define DSC_INIT16 0xC000 | 30 | #define DSC_INIT16 0xC000 |
31 | #define PCH_GBE_DMA_ALIGN 0 | 31 | #define PCH_GBE_DMA_ALIGN 0 |
32 | #define PCH_GBE_DMA_PADDING 2 | ||
32 | #define PCH_GBE_WATCHDOG_PERIOD (1 * HZ) /* watchdog time */ | 33 | #define PCH_GBE_WATCHDOG_PERIOD (1 * HZ) /* watchdog time */ |
33 | #define PCH_GBE_COPYBREAK_DEFAULT 256 | 34 | #define PCH_GBE_COPYBREAK_DEFAULT 256 |
34 | #define PCH_GBE_PCI_BAR 1 | 35 | #define PCH_GBE_PCI_BAR 1 |
@@ -1365,16 +1366,13 @@ pch_gbe_clean_rx(struct pch_gbe_adapter *adapter, | |||
1365 | struct pch_gbe_buffer *buffer_info; | 1366 | struct pch_gbe_buffer *buffer_info; |
1366 | struct pch_gbe_rx_desc *rx_desc; | 1367 | struct pch_gbe_rx_desc *rx_desc; |
1367 | u32 length; | 1368 | u32 length; |
1368 | unsigned char tmp_packet[ETH_HLEN]; | ||
1369 | unsigned int i; | 1369 | unsigned int i; |
1370 | unsigned int cleaned_count = 0; | 1370 | unsigned int cleaned_count = 0; |
1371 | bool cleaned = false; | 1371 | bool cleaned = false; |
1372 | struct sk_buff *skb; | 1372 | struct sk_buff *skb, *new_skb; |
1373 | u8 dma_status; | 1373 | u8 dma_status; |
1374 | u16 gbec_status; | 1374 | u16 gbec_status; |
1375 | u32 tcp_ip_status; | 1375 | u32 tcp_ip_status; |
1376 | u8 skb_copy_flag = 0; | ||
1377 | u8 skb_padding_flag = 0; | ||
1378 | 1376 | ||
1379 | i = rx_ring->next_to_clean; | 1377 | i = rx_ring->next_to_clean; |
1380 | 1378 | ||
@@ -1418,55 +1416,70 @@ pch_gbe_clean_rx(struct pch_gbe_adapter *adapter, | |||
1418 | pr_err("Receive CRC Error\n"); | 1416 | pr_err("Receive CRC Error\n"); |
1419 | } else { | 1417 | } else { |
1420 | /* get receive length */ | 1418 | /* get receive length */ |
1421 | /* length convert[-3], padding[-2] */ | 1419 | /* length convert[-3] */ |
1422 | length = (rx_desc->rx_words_eob) - 3 - 2; | 1420 | length = (rx_desc->rx_words_eob) - 3; |
1423 | 1421 | ||
1424 | /* Decide the data conversion method */ | 1422 | /* Decide the data conversion method */ |
1425 | if (!adapter->rx_csum) { | 1423 | if (!adapter->rx_csum) { |
1426 | /* [Header:14][payload] */ | 1424 | /* [Header:14][payload] */ |
1427 | skb_padding_flag = 0; | 1425 | if (NET_IP_ALIGN) { |
1428 | skb_copy_flag = 1; | 1426 | /* Because alignment differs, |
1427 | * the new_skb is newly allocated, | ||
1428 | * and data is copied to new_skb.*/ | ||
1429 | new_skb = netdev_alloc_skb(netdev, | ||
1430 | length + NET_IP_ALIGN); | ||
1431 | if (!new_skb) { | ||
1432 | /* dorrop error */ | ||
1433 | pr_err("New skb allocation " | ||
1434 | "Error\n"); | ||
1435 | goto dorrop; | ||
1436 | } | ||
1437 | skb_reserve(new_skb, NET_IP_ALIGN); | ||
1438 | memcpy(new_skb->data, skb->data, | ||
1439 | length); | ||
1440 | skb = new_skb; | ||
1441 | } else { | ||
1442 | /* DMA buffer is used as SKB as it is.*/ | ||
1443 | buffer_info->skb = NULL; | ||
1444 | } | ||
1429 | } else { | 1445 | } else { |
1430 | /* [Header:14][padding:2][payload] */ | 1446 | /* [Header:14][padding:2][payload] */ |
1431 | skb_padding_flag = 1; | 1447 | /* The length includes padding length */ |
1432 | if (length < copybreak) | 1448 | length = length - PCH_GBE_DMA_PADDING; |
1433 | skb_copy_flag = 1; | 1449 | if ((length < copybreak) || |
1434 | else | 1450 | (NET_IP_ALIGN != PCH_GBE_DMA_PADDING)) { |
1435 | skb_copy_flag = 0; | 1451 | /* Because alignment differs, |
1436 | } | 1452 | * the new_skb is newly allocated, |
1437 | 1453 | * and data is copied to new_skb. | |
1438 | /* Data conversion */ | 1454 | * Padding data is deleted |
1439 | if (skb_copy_flag) { /* recycle skb */ | 1455 | * at the time of a copy.*/ |
1440 | struct sk_buff *new_skb; | 1456 | new_skb = netdev_alloc_skb(netdev, |
1441 | new_skb = | 1457 | length + NET_IP_ALIGN); |
1442 | netdev_alloc_skb(netdev, | 1458 | if (!new_skb) { |
1443 | length + NET_IP_ALIGN); | 1459 | /* dorrop error */ |
1444 | if (new_skb) { | 1460 | pr_err("New skb allocation " |
1445 | if (!skb_padding_flag) { | 1461 | "Error\n"); |
1446 | skb_reserve(new_skb, | 1462 | goto dorrop; |
1447 | NET_IP_ALIGN); | ||
1448 | } | 1463 | } |
1464 | skb_reserve(new_skb, NET_IP_ALIGN); | ||
1449 | memcpy(new_skb->data, skb->data, | 1465 | memcpy(new_skb->data, skb->data, |
1450 | length); | 1466 | ETH_HLEN); |
1451 | /* save the skb | 1467 | memcpy(&new_skb->data[ETH_HLEN], |
1452 | * in buffer_info as good */ | 1468 | &skb->data[ETH_HLEN + |
1469 | PCH_GBE_DMA_PADDING], | ||
1470 | length - ETH_HLEN); | ||
1453 | skb = new_skb; | 1471 | skb = new_skb; |
1454 | } else if (!skb_padding_flag) { | 1472 | } else { |
1455 | /* dorrop error */ | 1473 | /* Padding data is deleted |
1456 | pr_err("New skb allocation Error\n"); | 1474 | * by moving header data.*/ |
1457 | goto dorrop; | 1475 | memmove(&skb->data[PCH_GBE_DMA_PADDING], |
1476 | &skb->data[0], ETH_HLEN); | ||
1477 | skb_reserve(skb, NET_IP_ALIGN); | ||
1478 | buffer_info->skb = NULL; | ||
1458 | } | 1479 | } |
1459 | } else { | ||
1460 | buffer_info->skb = NULL; | ||
1461 | } | 1480 | } |
1462 | if (skb_padding_flag) { | 1481 | /* The length includes FCS length */ |
1463 | memcpy(&tmp_packet[0], &skb->data[0], ETH_HLEN); | 1482 | length = length - ETH_FCS_LEN; |
1464 | memcpy(&skb->data[NET_IP_ALIGN], &tmp_packet[0], | ||
1465 | ETH_HLEN); | ||
1466 | skb_reserve(skb, NET_IP_ALIGN); | ||
1467 | |||
1468 | } | ||
1469 | |||
1470 | /* update status of driver */ | 1483 | /* update status of driver */ |
1471 | adapter->stats.rx_bytes += length; | 1484 | adapter->stats.rx_bytes += length; |
1472 | adapter->stats.rx_packets++; | 1485 | adapter->stats.rx_packets++; |