aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasakazu Mokuno <mokuno@sm.sony.co.jp>2007-08-31 09:22:32 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:51:00 -0400
commit173261ed37e7a98cedfcc808eb07eeceee66e078 (patch)
treece28d915a993b8925acdc5589292c00cd6b3d9d7
parent829185e97fba67ededd3eb025147bafcc0ca7557 (diff)
PS3: changed the way to handle tx skbs
The PS3 virtual network device requires a vlan tag in the sending packet to select the destination device, ethernet port or wireless. As the vlan tag field is in the middle of the passed data, we should insert it into the packet data. To avoid copying much of the packet data, the driver used two tx descriptors for one tx skb; one descriptor was for sending a small static buffer which contained vlan tag and copied header (two mac addresses), one was for the residual data after the vlan field. This patch changes the way to insert the vlan tag. By changing netdev->hard_header_len, we can make the headroom for moving mac address fields in the skb buffer. Then we can send one tx skb with one tx descriptor. This also gives us a tx throughut gain of approx. 20% according to netperf results. Signed-off-by: Masakazu Mokuno <mokuno@sm.sony.co.jp> CC: Geoff Levand <geoffrey.levand@am.sony.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/net/ps3_gelic_net.c140
1 files changed, 63 insertions, 77 deletions
diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c
index 92561c0450bc..31c3092e66af 100644
--- a/drivers/net/ps3_gelic_net.c
+++ b/drivers/net/ps3_gelic_net.c
@@ -351,19 +351,13 @@ static int gelic_net_alloc_rx_skbs(struct gelic_net_card *card)
351static void gelic_net_release_tx_descr(struct gelic_net_card *card, 351static void gelic_net_release_tx_descr(struct gelic_net_card *card,
352 struct gelic_net_descr *descr) 352 struct gelic_net_descr *descr)
353{ 353{
354 struct sk_buff *skb; 354 struct sk_buff *skb = descr->skb;
355 355
356 BUG_ON(!(descr->data_status & (1 << GELIC_NET_TXDESC_TAIL)));
356 357
357 if (descr->data_status & (1 << GELIC_NET_TXDESC_TAIL)) { 358 dma_unmap_single(ctodev(card), descr->buf_addr, skb->len,
358 /* 2nd descriptor */ 359 DMA_TO_DEVICE);
359 skb = descr->skb; 360 dev_kfree_skb_any(skb);
360 dma_unmap_single(ctodev(card), descr->buf_addr, skb->len,
361 DMA_TO_DEVICE);
362 dev_kfree_skb_any(skb);
363 } else {
364 dma_unmap_single(ctodev(card), descr->buf_addr,
365 descr->buf_size, DMA_TO_DEVICE);
366 }
367 361
368 descr->buf_addr = 0; 362 descr->buf_addr = 0;
369 descr->buf_size = 0; 363 descr->buf_size = 0;
@@ -426,7 +420,7 @@ static void gelic_net_release_tx_chain(struct gelic_net_card *card, int stop)
426 release ++; 420 release ++;
427 } 421 }
428out: 422out:
429 if (!stop && (2 < release)) 423 if (!stop && release)
430 netif_wake_queue(card->netdev); 424 netif_wake_queue(card->netdev);
431} 425}
432 426
@@ -593,13 +587,10 @@ gelic_net_get_next_tx_descr(struct gelic_net_card *card)
593{ 587{
594 if (!card->tx_chain.head) 588 if (!card->tx_chain.head)
595 return NULL; 589 return NULL;
596 /* see if we can two consecutive free descrs */ 590 /* see if the next descriptor is free */
597 if (card->tx_chain.tail != card->tx_chain.head->next && 591 if (card->tx_chain.tail != card->tx_chain.head->next &&
598 gelic_net_get_descr_status(card->tx_chain.head) == 592 gelic_net_get_descr_status(card->tx_chain.head) ==
599 GELIC_NET_DESCR_NOT_IN_USE && 593 GELIC_NET_DESCR_NOT_IN_USE)
600 card->tx_chain.tail != card->tx_chain.head->next->next &&
601 gelic_net_get_descr_status(card->tx_chain.head->next) ==
602 GELIC_NET_DESCR_NOT_IN_USE )
603 return card->tx_chain.head; 594 return card->tx_chain.head;
604 else 595 else
605 return NULL; 596 return NULL;
@@ -610,44 +601,66 @@ gelic_net_get_next_tx_descr(struct gelic_net_card *card)
610 * gelic_net_set_txdescr_cmdstat - sets the tx descriptor command field 601 * gelic_net_set_txdescr_cmdstat - sets the tx descriptor command field
611 * @descr: descriptor structure to fill out 602 * @descr: descriptor structure to fill out
612 * @skb: packet to consider 603 * @skb: packet to consider
613 * @middle: middle of frame
614 * 604 *
615 * fills out the command and status field of the descriptor structure, 605 * fills out the command and status field of the descriptor structure,
616 * depending on hardware checksum settings. This function assumes a wmb() 606 * depending on hardware checksum settings. This function assumes a wmb()
617 * has executed before. 607 * has executed before.
618 */ 608 */
619static void gelic_net_set_txdescr_cmdstat(struct gelic_net_descr *descr, 609static void gelic_net_set_txdescr_cmdstat(struct gelic_net_descr *descr,
620 struct sk_buff *skb, int middle) 610 struct sk_buff *skb)
621{ 611{
622 u32 eofr;
623
624 if (middle)
625 eofr = 0;
626 else
627 eofr = GELIC_NET_DMAC_CMDSTAT_END_FRAME;
628
629 if (skb->ip_summed != CHECKSUM_PARTIAL) 612 if (skb->ip_summed != CHECKSUM_PARTIAL)
630 descr->dmac_cmd_status = GELIC_NET_DMAC_CMDSTAT_NOCS | eofr; 613 descr->dmac_cmd_status = GELIC_NET_DMAC_CMDSTAT_NOCS |
614 GELIC_NET_DMAC_CMDSTAT_END_FRAME;
631 else { 615 else {
632 /* is packet ip? 616 /* is packet ip?
633 * if yes: tcp? udp? */ 617 * if yes: tcp? udp? */
634 if (skb->protocol == htons(ETH_P_IP)) { 618 if (skb->protocol == htons(ETH_P_IP)) {
635 if (ip_hdr(skb)->protocol == IPPROTO_TCP) 619 if (ip_hdr(skb)->protocol == IPPROTO_TCP)
636 descr->dmac_cmd_status = 620 descr->dmac_cmd_status =
637 GELIC_NET_DMAC_CMDSTAT_TCPCS | eofr; 621 GELIC_NET_DMAC_CMDSTAT_TCPCS |
622 GELIC_NET_DMAC_CMDSTAT_END_FRAME;
623
638 else if (ip_hdr(skb)->protocol == IPPROTO_UDP) 624 else if (ip_hdr(skb)->protocol == IPPROTO_UDP)
639 descr->dmac_cmd_status = 625 descr->dmac_cmd_status =
640 GELIC_NET_DMAC_CMDSTAT_UDPCS | eofr; 626 GELIC_NET_DMAC_CMDSTAT_UDPCS |
627 GELIC_NET_DMAC_CMDSTAT_END_FRAME;
641 else /* 628 else /*
642 * the stack should checksum non-tcp and non-udp 629 * the stack should checksum non-tcp and non-udp
643 * packets on his own: NETIF_F_IP_CSUM 630 * packets on his own: NETIF_F_IP_CSUM
644 */ 631 */
645 descr->dmac_cmd_status = 632 descr->dmac_cmd_status =
646 GELIC_NET_DMAC_CMDSTAT_NOCS | eofr; 633 GELIC_NET_DMAC_CMDSTAT_NOCS |
634 GELIC_NET_DMAC_CMDSTAT_END_FRAME;
647 } 635 }
648 } 636 }
649} 637}
650 638
639static inline struct sk_buff *gelic_put_vlan_tag(struct sk_buff *skb,
640 unsigned short tag)
641{
642 struct vlan_ethhdr *veth;
643 static unsigned int c;
644
645 if (skb_headroom(skb) < VLAN_HLEN) {
646 struct sk_buff *sk_tmp = skb;
647 pr_debug("%s: hd=%d c=%ud\n", __func__, skb_headroom(skb), c);
648 skb = skb_realloc_headroom(sk_tmp, VLAN_HLEN);
649 if (!skb)
650 return NULL;
651 dev_kfree_skb_any(sk_tmp);
652 }
653 veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN);
654
655 /* Move the mac addresses to the top of buffer */
656 memmove(skb->data, skb->data + VLAN_HLEN, 2 * ETH_ALEN);
657
658 veth->h_vlan_proto = __constant_htons(ETH_P_8021Q);
659 veth->h_vlan_TCI = htons(tag);
660
661 return skb;
662}
663
651/** 664/**
652 * gelic_net_prepare_tx_descr_v - get dma address of skb_data 665 * gelic_net_prepare_tx_descr_v - get dma address of skb_data
653 * @card: card structure 666 * @card: card structure
@@ -661,65 +674,35 @@ static int gelic_net_prepare_tx_descr_v(struct gelic_net_card *card,
661 struct gelic_net_descr *descr, 674 struct gelic_net_descr *descr,
662 struct sk_buff *skb) 675 struct sk_buff *skb)
663{ 676{
664 dma_addr_t buf[2]; 677 dma_addr_t buf;
665 unsigned int vlan_len;
666 struct gelic_net_descr *sec_descr = descr->next;
667
668 if (skb->len < GELIC_NET_VLAN_POS)
669 return -EINVAL;
670 678
671 vlan_len = GELIC_NET_VLAN_POS;
672 memcpy(&descr->vlan, skb->data, vlan_len);
673 if (card->vlan_index != -1) { 679 if (card->vlan_index != -1) {
674 /* internal vlan tag used */ 680 struct sk_buff *skb_tmp;
675 descr->vlan.h_vlan_proto = htons(ETH_P_8021Q); /* vlan 0x8100*/ 681 skb_tmp = gelic_put_vlan_tag(skb,
676 descr->vlan.h_vlan_TCI = htons(card->vlan_id[card->vlan_index]); 682 card->vlan_id[card->vlan_index]);
677 vlan_len += VLAN_HLEN; /* added for above two lines */ 683 if (!skb_tmp)
678 } 684 return -ENOMEM;
679 685 skb = skb_tmp;
680 /* map data area */
681 buf[0] = dma_map_single(ctodev(card), &descr->vlan,
682 vlan_len, DMA_TO_DEVICE);
683
684 if (!buf[0]) {
685 dev_err(ctodev(card),
686 "dma map 1 failed (%p, %i). Dropping packet\n",
687 skb->data, vlan_len);
688 return -ENOMEM;
689 } 686 }
690 687
691 buf[1] = dma_map_single(ctodev(card), skb->data + GELIC_NET_VLAN_POS, 688 buf = dma_map_single(ctodev(card), skb->data, skb->len, DMA_TO_DEVICE);
692 skb->len - GELIC_NET_VLAN_POS,
693 DMA_TO_DEVICE);
694 689
695 if (!buf[1]) { 690 if (!buf) {
696 dev_err(ctodev(card), 691 dev_err(ctodev(card),
697 "dma map 2 failed (%p, %i). Dropping packet\n", 692 "dma map 2 failed (%p, %i). Dropping packet\n",
698 skb->data + GELIC_NET_VLAN_POS, 693 skb->data, skb->len);
699 skb->len - GELIC_NET_VLAN_POS);
700 dma_unmap_single(ctodev(card), buf[0], vlan_len,
701 DMA_TO_DEVICE);
702 return -ENOMEM; 694 return -ENOMEM;
703 } 695 }
704 696
705 /* first descr */ 697 descr->buf_addr = buf;
706 descr->buf_addr = buf[0]; 698 descr->buf_size = skb->len;
707 descr->buf_size = vlan_len; 699 descr->skb = skb;
708 descr->skb = NULL; /* not used */
709 descr->data_status = 0; 700 descr->data_status = 0;
710 descr->next_descr_addr = descr->next->bus_addr; 701 descr->next_descr_addr = 0; /* terminate hw descr */
711 gelic_net_set_txdescr_cmdstat(descr, skb, 1); /* not the frame end */ 702 gelic_net_set_txdescr_cmdstat(descr, skb);
712
713 /* second descr */
714 sec_descr->buf_addr = buf[1];
715 sec_descr->buf_size = skb->len - GELIC_NET_VLAN_POS;
716 sec_descr->skb = skb;
717 sec_descr->data_status = 0;
718 sec_descr->next_descr_addr = 0; /* terminate hw descr */
719 gelic_net_set_txdescr_cmdstat(sec_descr, skb, 0);
720 703
721 /* bump free descriptor pointer */ 704 /* bump free descriptor pointer */
722 card->tx_chain.head = sec_descr->next; 705 card->tx_chain.head = descr->next;
723 return 0; 706 return 0;
724} 707}
725 708
@@ -1425,8 +1408,11 @@ static int gelic_net_setup_netdev(struct gelic_net_card *card)
1425 dev_dbg(ctodev(card), "vlan_id:%d, %lx\n", i, v1); 1408 dev_dbg(ctodev(card), "vlan_id:%d, %lx\n", i, v1);
1426 } 1409 }
1427 } 1410 }
1428 if (card->vlan_id[GELIC_NET_VLAN_WIRED - 1]) 1411
1412 if (card->vlan_id[GELIC_NET_VLAN_WIRED - 1]) {
1429 card->vlan_index = GELIC_NET_VLAN_WIRED - 1; 1413 card->vlan_index = GELIC_NET_VLAN_WIRED - 1;
1414 netdev->hard_header_len += VLAN_HLEN;
1415 }
1430 1416
1431 status = register_netdev(netdev); 1417 status = register_netdev(netdev);
1432 if (status) { 1418 if (status) {