aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/netxen
diff options
context:
space:
mode:
authorDhananjay Phadke <dhananjay@netxen.com>2009-07-26 16:07:40 -0400
committerDavid S. Miller <davem@davemloft.net>2009-07-27 13:57:33 -0400
commit1bcfd790c49341fcbdce9526a007c4e2b9d54c7c (patch)
tree7f1d8909e32a0b2b301a28c61ad4dccd8ab866f6 /drivers/net/netxen
parent83ac51fa747c3a74372417629fcad4b110857b77 (diff)
netxen: refactor tso code
o move all tso / checksum offload code into netxen_tso_check(). o optimize the tso header copy into simple loop. o clean up unnecessary unions from cmd_desc_type0 struct. Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/netxen')
-rw-r--r--drivers/net/netxen/netxen_nic.h49
-rw-r--r--drivers/net/netxen/netxen_nic_main.c152
2 files changed, 83 insertions, 118 deletions
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 3368af0c129b..3a4cbd5dcbd9 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -316,56 +316,29 @@ struct netxen_ring_ctx {
316 cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7)) 316 cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7))
317 317
318#define netxen_set_tx_frags_len(_desc, _frags, _len) \ 318#define netxen_set_tx_frags_len(_desc, _frags, _len) \
319 (_desc)->num_of_buffers_total_length = \ 319 (_desc)->nfrags__length = \
320 cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8)) 320 cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8))
321 321
322struct cmd_desc_type0 { 322struct cmd_desc_type0 {
323 u8 tcp_hdr_offset; /* For LSO only */ 323 u8 tcp_hdr_offset; /* For LSO only */
324 u8 ip_hdr_offset; /* For LSO only */ 324 u8 ip_hdr_offset; /* For LSO only */
325 /* Bit pattern: 0-6 flags, 7-12 opcode, 13-15 unused */ 325 __le16 flags_opcode; /* 15:13 unused, 12:7 opcode, 6:0 flags */
326 __le16 flags_opcode; 326 __le32 nfrags__length; /* 31:8 total len, 7:0 frag count */
327 /* Bit pattern: 0-7 total number of segments, 327
328 8-31 Total size of the packet */ 328 __le64 addr_buffer2;
329 __le32 num_of_buffers_total_length;
330 union {
331 struct {
332 __le32 addr_low_part2;
333 __le32 addr_high_part2;
334 };
335 __le64 addr_buffer2;
336 };
337 329
338 __le16 reference_handle; /* changed to u16 to add mss */ 330 __le16 reference_handle;
339 __le16 mss; /* passed by NDIS_PACKET for LSO */ 331 __le16 mss;
340 /* Bit pattern 0-3 port, 0-3 ctx id */ 332 u8 port_ctxid; /* 7:4 ctxid 3:0 port */
341 u8 port_ctxid;
342 u8 total_hdr_length; /* LSO only : MAC+IP+TCP Hdr size */ 333 u8 total_hdr_length; /* LSO only : MAC+IP+TCP Hdr size */
343 __le16 conn_id; /* IPSec offoad only */ 334 __le16 conn_id; /* IPSec offoad only */
344 335
345 union { 336 __le64 addr_buffer3;
346 struct { 337 __le64 addr_buffer1;
347 __le32 addr_low_part3;
348 __le32 addr_high_part3;
349 };
350 __le64 addr_buffer3;
351 };
352 union {
353 struct {
354 __le32 addr_low_part1;
355 __le32 addr_high_part1;
356 };
357 __le64 addr_buffer1;
358 };
359 338
360 __le16 buffer_length[4]; 339 __le16 buffer_length[4];
361 340
362 union { 341 __le64 addr_buffer4;
363 struct {
364 __le32 addr_low_part4;
365 __le32 addr_high_part4;
366 };
367 __le64 addr_buffer4;
368 };
369 342
370 __le64 unused; 343 __le64 unused;
371 344
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index fb976cbf9c71..381bd8f027c0 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -1310,13 +1310,18 @@ static int netxen_nic_close(struct net_device *netdev)
1310 return 0; 1310 return 0;
1311} 1311}
1312 1312
1313static bool netxen_tso_check(struct net_device *netdev, 1313static void
1314 struct cmd_desc_type0 *desc, struct sk_buff *skb) 1314netxen_tso_check(struct net_device *netdev,
1315 struct nx_host_tx_ring *tx_ring,
1316 struct cmd_desc_type0 *first_desc,
1317 struct sk_buff *skb)
1315{ 1318{
1316 bool tso = false;
1317 u8 opcode = TX_ETHER_PKT; 1319 u8 opcode = TX_ETHER_PKT;
1318 __be16 protocol = skb->protocol; 1320 __be16 protocol = skb->protocol;
1319 u16 flags = 0; 1321 u16 flags = 0;
1322 u32 producer;
1323 int copied, offset, copy_len, hdr_len = 0, tso = 0;
1324 struct cmd_desc_type0 *hwdesc;
1320 1325
1321 if (protocol == cpu_to_be16(ETH_P_8021Q)) { 1326 if (protocol == cpu_to_be16(ETH_P_8021Q)) {
1322 struct vlan_ethhdr *vh = (struct vlan_ethhdr *)skb->data; 1327 struct vlan_ethhdr *vh = (struct vlan_ethhdr *)skb->data;
@@ -1327,13 +1332,14 @@ static bool netxen_tso_check(struct net_device *netdev,
1327 if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && 1332 if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
1328 skb_shinfo(skb)->gso_size > 0) { 1333 skb_shinfo(skb)->gso_size > 0) {
1329 1334
1330 desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); 1335 hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
1331 desc->total_hdr_length = 1336
1332 skb_transport_offset(skb) + tcp_hdrlen(skb); 1337 first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
1338 first_desc->total_hdr_length = hdr_len;
1333 1339
1334 opcode = (protocol == cpu_to_be16(ETH_P_IPV6)) ? 1340 opcode = (protocol == cpu_to_be16(ETH_P_IPV6)) ?
1335 TX_TCP_LSO6 : TX_TCP_LSO; 1341 TX_TCP_LSO6 : TX_TCP_LSO;
1336 tso = true; 1342 tso = 1;
1337 1343
1338 } else if (skb->ip_summed == CHECKSUM_PARTIAL) { 1344 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
1339 u8 l4proto; 1345 u8 l4proto;
@@ -1354,10 +1360,39 @@ static bool netxen_tso_check(struct net_device *netdev,
1354 opcode = TX_UDPV6_PKT; 1360 opcode = TX_UDPV6_PKT;
1355 } 1361 }
1356 } 1362 }
1357 desc->tcp_hdr_offset = skb_transport_offset(skb); 1363 first_desc->tcp_hdr_offset = skb_transport_offset(skb);
1358 desc->ip_hdr_offset = skb_network_offset(skb); 1364 first_desc->ip_hdr_offset = skb_network_offset(skb);
1359 netxen_set_tx_flags_opcode(desc, flags, opcode); 1365 netxen_set_tx_flags_opcode(first_desc, flags, opcode);
1360 return tso; 1366
1367 if (!tso)
1368 return;
1369
1370 /* For LSO, we need to copy the MAC/IP/TCP headers into
1371 * the descriptor ring
1372 */
1373 producer = tx_ring->producer;
1374 copied = 0;
1375 offset = 2;
1376
1377 while (copied < hdr_len) {
1378
1379 copy_len = min((int)sizeof(struct cmd_desc_type0) - offset,
1380 (hdr_len - copied));
1381
1382 hwdesc = &tx_ring->desc_head[producer];
1383 tx_ring->cmd_buf_arr[producer].skb = NULL;
1384
1385 skb_copy_from_linear_data_offset(skb, copied,
1386 (char *)hwdesc + offset, copy_len);
1387
1388 copied += copy_len;
1389 offset = 0;
1390
1391 producer = get_next_index(producer, tx_ring->num_desc);
1392 }
1393
1394 tx_ring->producer = producer;
1395 barrier();
1361} 1396}
1362 1397
1363static void 1398static void
@@ -1381,9 +1416,8 @@ netxen_clean_tx_dma_mapping(struct pci_dev *pdev,
1381static inline void 1416static inline void
1382netxen_clear_cmddesc(u64 *desc) 1417netxen_clear_cmddesc(u64 *desc)
1383{ 1418{
1384 int i; 1419 desc[0] = 0ULL;
1385 for (i = 0; i < 8; i++) 1420 desc[2] = 0ULL;
1386 desc[i] = 0ULL;
1387} 1421}
1388 1422
1389static int 1423static int
@@ -1391,18 +1425,18 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1391{ 1425{
1392 struct netxen_adapter *adapter = netdev_priv(netdev); 1426 struct netxen_adapter *adapter = netdev_priv(netdev);
1393 struct nx_host_tx_ring *tx_ring = adapter->tx_ring; 1427 struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
1394 unsigned int first_seg_len = skb->len - skb->data_len; 1428 struct skb_frag_struct *frag;
1395 struct netxen_cmd_buffer *pbuf; 1429 struct netxen_cmd_buffer *pbuf;
1396 struct netxen_skb_frag *buffrag; 1430 struct netxen_skb_frag *buffrag;
1397 struct cmd_desc_type0 *hwdesc; 1431 struct cmd_desc_type0 *hwdesc, *first_desc;
1398 struct pci_dev *pdev = adapter->pdev; 1432 struct pci_dev *pdev;
1399 dma_addr_t temp_dma; 1433 dma_addr_t temp_dma;
1400 int i, k; 1434 int i, k;
1435 unsigned long offset;
1401 1436
1402 u32 producer; 1437 u32 producer;
1403 int frag_count, no_of_desc; 1438 int len, frag_count, no_of_desc;
1404 u32 num_txd = tx_ring->num_desc; 1439 u32 num_txd = tx_ring->num_desc;
1405 bool is_tso = false;
1406 1440
1407 frag_count = skb_shinfo(skb)->nr_frags + 1; 1441 frag_count = skb_shinfo(skb)->nr_frags + 1;
1408 1442
@@ -1416,32 +1450,30 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1416 1450
1417 producer = tx_ring->producer; 1451 producer = tx_ring->producer;
1418 1452
1419 hwdesc = &tx_ring->desc_head[producer]; 1453 pdev = adapter->pdev;
1420 netxen_clear_cmddesc((u64 *)hwdesc); 1454 len = skb->len - skb->data_len;
1421 pbuf = &tx_ring->cmd_buf_arr[producer];
1422 1455
1423 is_tso = netxen_tso_check(netdev, hwdesc, skb); 1456 temp_dma = pci_map_single(pdev, skb->data, len, PCI_DMA_TODEVICE);
1457 if (pci_dma_mapping_error(pdev, temp_dma))
1458 goto drop_packet;
1424 1459
1460 pbuf = &tx_ring->cmd_buf_arr[producer];
1425 pbuf->skb = skb; 1461 pbuf->skb = skb;
1426 pbuf->frag_count = frag_count; 1462 pbuf->frag_count = frag_count;
1427 buffrag = &pbuf->frag_array[0];
1428 temp_dma = pci_map_single(pdev, skb->data, first_seg_len,
1429 PCI_DMA_TODEVICE);
1430 if (pci_dma_mapping_error(pdev, temp_dma))
1431 goto drop_packet;
1432 1463
1464 buffrag = &pbuf->frag_array[0];
1433 buffrag->dma = temp_dma; 1465 buffrag->dma = temp_dma;
1434 buffrag->length = first_seg_len; 1466 buffrag->length = len;
1467
1468 first_desc = hwdesc = &tx_ring->desc_head[producer];
1469 netxen_clear_cmddesc((u64 *)hwdesc);
1435 netxen_set_tx_frags_len(hwdesc, frag_count, skb->len); 1470 netxen_set_tx_frags_len(hwdesc, frag_count, skb->len);
1436 netxen_set_tx_port(hwdesc, adapter->portnum); 1471 netxen_set_tx_port(hwdesc, adapter->portnum);
1437 1472
1438 hwdesc->buffer_length[0] = cpu_to_le16(first_seg_len); 1473 hwdesc->buffer_length[0] = cpu_to_le16(len);
1439 hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma); 1474 hwdesc->addr_buffer1 = cpu_to_le64(temp_dma);
1440 1475
1441 for (i = 1, k = 1; i < frag_count; i++, k++) { 1476 for (i = 1, k = 1; i < frag_count; i++, k++) {
1442 struct skb_frag_struct *frag;
1443 int len, temp_len;
1444 unsigned long offset;
1445 1477
1446 /* move to next desc. if there is a need */ 1478 /* move to next desc. if there is a need */
1447 if ((i & 0x3) == 0) { 1479 if ((i & 0x3) == 0) {
@@ -1452,11 +1484,11 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1452 pbuf = &tx_ring->cmd_buf_arr[producer]; 1484 pbuf = &tx_ring->cmd_buf_arr[producer];
1453 pbuf->skb = NULL; 1485 pbuf->skb = NULL;
1454 } 1486 }
1487 buffrag = &pbuf->frag_array[i];
1455 frag = &skb_shinfo(skb)->frags[i - 1]; 1488 frag = &skb_shinfo(skb)->frags[i - 1];
1456 len = frag->size; 1489 len = frag->size;
1457 offset = frag->page_offset; 1490 offset = frag->page_offset;
1458 1491
1459 temp_len = len;
1460 temp_dma = pci_map_page(pdev, frag->page, offset, 1492 temp_dma = pci_map_page(pdev, frag->page, offset,
1461 len, PCI_DMA_TODEVICE); 1493 len, PCI_DMA_TODEVICE);
1462 if (pci_dma_mapping_error(pdev, temp_dma)) { 1494 if (pci_dma_mapping_error(pdev, temp_dma)) {
@@ -1464,11 +1496,10 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1464 goto drop_packet; 1496 goto drop_packet;
1465 } 1497 }
1466 1498
1467 buffrag++;
1468 buffrag->dma = temp_dma; 1499 buffrag->dma = temp_dma;
1469 buffrag->length = temp_len; 1500 buffrag->length = len;
1470 1501
1471 hwdesc->buffer_length[k] = cpu_to_le16(temp_len); 1502 hwdesc->buffer_length[k] = cpu_to_le16(len);
1472 switch (k) { 1503 switch (k) {
1473 case 0: 1504 case 0:
1474 hwdesc->addr_buffer1 = cpu_to_le64(temp_dma); 1505 hwdesc->addr_buffer1 = cpu_to_le64(temp_dma);
@@ -1483,53 +1514,14 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1483 hwdesc->addr_buffer4 = cpu_to_le64(temp_dma); 1514 hwdesc->addr_buffer4 = cpu_to_le64(temp_dma);
1484 break; 1515 break;
1485 } 1516 }
1486 frag++;
1487 } 1517 }
1488 producer = get_next_index(producer, num_txd); 1518 tx_ring->producer = get_next_index(producer, num_txd);
1489 1519
1490 /* For LSO, we need to copy the MAC/IP/TCP headers into 1520 netxen_tso_check(netdev, tx_ring, first_desc, skb);
1491 * the descriptor ring
1492 */
1493 if (is_tso) {
1494 int hdr_len, first_hdr_len, more_hdr;
1495 hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
1496 if (hdr_len > (sizeof(struct cmd_desc_type0) - 2)) {
1497 first_hdr_len = sizeof(struct cmd_desc_type0) - 2;
1498 more_hdr = 1;
1499 } else {
1500 first_hdr_len = hdr_len;
1501 more_hdr = 0;
1502 }
1503 /* copy the MAC/IP/TCP headers to the cmd descriptor list */
1504 hwdesc = &tx_ring->desc_head[producer];
1505 pbuf = &tx_ring->cmd_buf_arr[producer];
1506 pbuf->skb = NULL;
1507
1508 /* copy the first 64 bytes */
1509 memcpy(((void *)hwdesc) + 2,
1510 (void *)(skb->data), first_hdr_len);
1511 producer = get_next_index(producer, num_txd);
1512
1513 if (more_hdr) {
1514 hwdesc = &tx_ring->desc_head[producer];
1515 pbuf = &tx_ring->cmd_buf_arr[producer];
1516 pbuf->skb = NULL;
1517 /* copy the next 64 bytes - should be enough except
1518 * for pathological case
1519 */
1520 skb_copy_from_linear_data_offset(skb, first_hdr_len,
1521 hwdesc,
1522 (hdr_len -
1523 first_hdr_len));
1524 producer = get_next_index(producer, num_txd);
1525 }
1526 }
1527
1528 tx_ring->producer = producer;
1529 adapter->stats.txbytes += skb->len;
1530 1521
1531 netxen_nic_update_cmd_producer(adapter, tx_ring); 1522 netxen_nic_update_cmd_producer(adapter, tx_ring);
1532 1523
1524 adapter->stats.txbytes += skb->len;
1533 adapter->stats.xmitcalled++; 1525 adapter->stats.xmitcalled++;
1534 1526
1535 return NETDEV_TX_OK; 1527 return NETDEV_TX_OK;