aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorToshiharu Okada <toshiharu-linux@dsn.okisemi.com>2011-02-08 17:15:59 -0500
committerDavid S. Miller <davem@davemloft.net>2011-02-14 00:50:19 -0500
commitac09664248e300342e92b937c9894a8149ddf189 (patch)
treefccdb0361ff3bb153ffc16d889229ecf872fcd4d /drivers/net
parent539c9aa5ba7c5f71794ef0948c6dd29552f033e4 (diff)
pch_gbe: Fix the issue that the receiving data is not normal.
This PCH_GBE driver had an issue that the receiving data is not normal. This driver had not removed correctly the padding data which the DMA include in receiving data. This patch fixed this issue. Signed-off-by: Toshiharu Okada <toshiharu-linux@dsn.okisemi.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/pch_gbe/pch_gbe_main.c97
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++;