diff options
-rw-r--r-- | drivers/net/ps3_gelic_net.c | 140 |
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) | |||
351 | static void gelic_net_release_tx_descr(struct gelic_net_card *card, | 351 | static 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 | } |
428 | out: | 422 | out: |
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 | */ |
619 | static void gelic_net_set_txdescr_cmdstat(struct gelic_net_descr *descr, | 609 | static 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 | ||
639 | static 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) { |