aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMithlesh Thukral <mithlesh@linsyssoft.com>2009-03-25 06:21:49 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-04-17 14:06:31 -0400
commitb824adc9686fb9a6edca164c13107bfed3e41d4e (patch)
tree44d7f0a710882e68e8679dcb06d2e4190fcf851b
parentcc4b8dfc3ff32f890cd5de0ce22de44f124d0d05 (diff)
Staging: sxg: Fix leaks and checksum errors in transmit code path
Fix the transmit function for the following: * Free XmtCmd in the error code path. This use to leak memory in error conditions. * Do pci mapping after the checksum operations are over. They can reallocate the skb at a different location. * Fix UDP checksum errors which were seen in wireshark Signed-off-by: LinSysSoft Sahara Team <saharaproj@linsyssoft.com> Signed-off-by: Mithlesh Thukral <mithlesh@linsyssoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/staging/sxg/sxg.c93
1 files changed, 58 insertions, 35 deletions
diff --git a/drivers/staging/sxg/sxg.c b/drivers/staging/sxg/sxg.c
index 583fbb470e9..076b3f7d39e 100644
--- a/drivers/staging/sxg/sxg.c
+++ b/drivers/staging/sxg/sxg.c
@@ -2582,6 +2582,7 @@ static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
2582 u64 phys_addr; 2582 u64 phys_addr;
2583 unsigned long flags; 2583 unsigned long flags;
2584 unsigned long queue_id=0; 2584 unsigned long queue_id=0;
2585 int offload_cksum = 0;
2585 2586
2586 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbSgl", 2587 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbSgl",
2587 pSgl, SxgSgl, 0, 0); 2588 pSgl, SxgSgl, 0, 0);
@@ -2620,9 +2621,11 @@ static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
2620 struct iphdr *ip; 2621 struct iphdr *ip;
2621 2622
2622 ip = ip_hdr(skb); 2623 ip = ip_hdr(skb);
2623 if (ip->protocol != IPPROTO_TCP || !tcp_hdr(skb)) 2624 if (ip->protocol == IPPROTO_TCP)
2625 offload_cksum = 1;
2626 if (!offload_cksum || !tcp_hdr(skb))
2624 queue_id = 0; 2627 queue_id = 0;
2625 else if ((ip->protocol == IPPROTO_TCP)&&(DataLength >= sizeof( 2628 else if (offload_cksum && (DataLength >= sizeof(
2626 struct tcphdr))){ 2629 struct tcphdr))){
2627 queue_id = ((ntohs(tcp_hdr(skb)->dest) == ISCSI_PORT) ? 2630 queue_id = ((ntohs(tcp_hdr(skb)->dest) == ISCSI_PORT) ?
2628 (ntohs (tcp_hdr(skb)->source) & 2631 (ntohs (tcp_hdr(skb)->source) &
@@ -2631,10 +2634,11 @@ static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
2631 SXG_LARGE_SEND_QUEUE_MASK)); 2634 SXG_LARGE_SEND_QUEUE_MASK));
2632 } 2635 }
2633 } else if (skb->protocol == htons(ETH_P_IPV6)) { 2636 } else if (skb->protocol == htons(ETH_P_IPV6)) {
2634 if (ipv6_hdr(skb)->nexthdr != IPPROTO_TCP || !tcp_hdr(skb)) 2637 if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
2638 offload_cksum = 1;
2639 if (!offload_cksum || !tcp_hdr(skb))
2635 queue_id = 0; 2640 queue_id = 0;
2636 else if ((ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) && (DataLength 2641 else if (offload_cksum && (DataLength>=sizeof(struct tcphdr))){
2637 >= sizeof(struct tcphdr)) ) {
2638 queue_id = ((ntohs(tcp_hdr(skb)->dest) == ISCSI_PORT) ? 2642 queue_id = ((ntohs(tcp_hdr(skb)->dest) == ISCSI_PORT) ?
2639 (ntohs (tcp_hdr(skb)->source) & 2643 (ntohs (tcp_hdr(skb)->source) &
2640 SXG_LARGE_SEND_QUEUE_MASK): 2644 SXG_LARGE_SEND_QUEUE_MASK):
@@ -2663,23 +2667,38 @@ static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
2663 } 2667 }
2664 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbCmd", 2668 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbCmd",
2665 XmtCmd, XmtRingInfo->Head, XmtRingInfo->Tail, 0); 2669 XmtCmd, XmtRingInfo->Head, XmtRingInfo->Tail, 0);
2666 /* Update stats */ 2670 memset(XmtCmd, '\0', sizeof(*XmtCmd));
2667 adapter->stats.tx_packets++; 2671 XmtCmd->SgEntries = 1;
2668 adapter->stats.tx_bytes += DataLength; 2672 XmtCmd->Flags = 0;
2669#if XXXTODO /* Stats stuff */ 2673 if (skb->ip_summed == CHECKSUM_PARTIAL) {
2670 if (SXG_MULTICAST_PACKET(EtherHdr)) { 2674 /*
2671 if (SXG_BROADCAST_PACKET(EtherHdr)) { 2675 * We need to set the Checkum in IP header to 0. This is
2672 adapter->Stats.DumbXmtBcastPkts++; 2676 * required by hardware.
2673 adapter->Stats.DumbXmtBcastBytes += DataLength; 2677 */
2678 if (offload_cksum) {
2679 ip_hdr(skb)->check = 0x0;
2680 XmtCmd->CsumFlags.Flags |= SXG_SLOWCMD_CSUM_IP;
2681 XmtCmd->CsumFlags.Flags |= SXG_SLOWCMD_CSUM_TCP;
2682 /*
2683 * Dont know if length will require a change in
2684 * case of VLAN
2685 */
2686 XmtCmd->CsumFlags.MacLen = ETH_HLEN;
2687 XmtCmd->CsumFlags.IpHl = skb_network_header_len(skb) >>
2688 SXG_NW_HDR_LEN_SHIFT;
2674 } else { 2689 } else {
2675 adapter->Stats.DumbXmtMcastPkts++; 2690 if (skb_checksum_help(skb)){
2676 adapter->Stats.DumbXmtMcastBytes += DataLength; 2691 printk(KERN_EMERG "Dropped UDP packet for"
2692 " incorrect checksum calculation\n");
2693 if (XmtCmd)
2694 SXG_ABORT_CMD(XmtRingInfo);
2695 spin_unlock_irqrestore(&adapter->XmtZeroLock,
2696 flags);
2697 return STATUS_SUCCESS;
2698 }
2677 } 2699 }
2678 } else {
2679 adapter->Stats.DumbXmtUcastPkts++;
2680 adapter->Stats.DumbXmtUcastBytes += DataLength;
2681 } 2700 }
2682#endif 2701
2683 /* 2702 /*
2684 * Fill in the command 2703 * Fill in the command
2685 * Copy out the first SGE to the command and adjust for offset 2704 * Copy out the first SGE to the command and adjust for offset
@@ -2697,31 +2716,17 @@ static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
2697 (SXG_INVALID_SGL(phys_addr,skb->data_len))) 2716 (SXG_INVALID_SGL(phys_addr,skb->data_len)))
2698 { 2717 {
2699 spin_unlock_irqrestore(&adapter->XmtZeroLock, flags); 2718 spin_unlock_irqrestore(&adapter->XmtZeroLock, flags);
2719 if (XmtCmd)
2720 SXG_ABORT_CMD(XmtRingInfo);
2700 /* Silently drop this packet */ 2721 /* Silently drop this packet */
2701 printk(KERN_EMERG"Dropped a packet for 64k boundary problem\n"); 2722 printk(KERN_EMERG"Dropped a packet for 64k boundary problem\n");
2702 return STATUS_SUCCESS; 2723 return STATUS_SUCCESS;
2703 } 2724 }
2704 memset(XmtCmd, '\0', sizeof(*XmtCmd));
2705 XmtCmd->Buffer.FirstSgeAddress = phys_addr; 2725 XmtCmd->Buffer.FirstSgeAddress = phys_addr;
2706 XmtCmd->Buffer.FirstSgeLength = DataLength; 2726 XmtCmd->Buffer.FirstSgeLength = DataLength;
2707 XmtCmd->Buffer.SgeOffset = 0; 2727 XmtCmd->Buffer.SgeOffset = 0;
2708 XmtCmd->Buffer.TotalLength = DataLength; 2728 XmtCmd->Buffer.TotalLength = DataLength;
2709 XmtCmd->SgEntries = 1;
2710 XmtCmd->Flags = 0;
2711 2729
2712 if (skb->ip_summed == CHECKSUM_PARTIAL) {
2713 /*
2714 * We need to set the Checkum in IP header to 0. This is
2715 * required by hardware.
2716 */
2717 ip_hdr(skb)->check = 0x0;
2718 XmtCmd->CsumFlags.Flags |= SXG_SLOWCMD_CSUM_IP;
2719 XmtCmd->CsumFlags.Flags |= SXG_SLOWCMD_CSUM_TCP;
2720 /* Dont know if length will require a change in case of VLAN */
2721 XmtCmd->CsumFlags.MacLen = ETH_HLEN;
2722 XmtCmd->CsumFlags.IpHl = skb_network_header_len(skb) >>
2723 SXG_NW_HDR_LEN_SHIFT;
2724 }
2725 /* 2730 /*
2726 * Advance transmit cmd descripter by 1. 2731 * Advance transmit cmd descripter by 1.
2727 * NOTE - See comments in SxgTcpOutput where we write 2732 * NOTE - See comments in SxgTcpOutput where we write
@@ -2733,6 +2738,24 @@ static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
2733 ASSERT((queue_id & ~SXG_LARGE_SEND_QUEUE_MASK) == 0); 2738 ASSERT((queue_id & ~SXG_LARGE_SEND_QUEUE_MASK) == 0);
2734 WRITE_REG(adapter->UcodeRegs[0].XmtCmd, ((queue_id << 16) | 1), TRUE); 2739 WRITE_REG(adapter->UcodeRegs[0].XmtCmd, ((queue_id << 16) | 1), TRUE);
2735 adapter->Stats.XmtQLen++; /* Stats within lock */ 2740 adapter->Stats.XmtQLen++; /* Stats within lock */
2741 /* Update stats */
2742 adapter->stats.tx_packets++;
2743 adapter->stats.tx_bytes += DataLength;
2744#if XXXTODO /* Stats stuff */
2745 if (SXG_MULTICAST_PACKET(EtherHdr)) {
2746 if (SXG_BROADCAST_PACKET(EtherHdr)) {
2747 adapter->Stats.DumbXmtBcastPkts++;
2748 adapter->Stats.DumbXmtBcastBytes += DataLength;
2749 } else {
2750 adapter->Stats.DumbXmtMcastPkts++;
2751 adapter->Stats.DumbXmtMcastBytes += DataLength;
2752 }
2753 } else {
2754 adapter->Stats.DumbXmtUcastPkts++;
2755 adapter->Stats.DumbXmtUcastBytes += DataLength;
2756 }
2757#endif
2758
2736 spin_unlock_irqrestore(&adapter->XmtZeroLock, flags); 2759 spin_unlock_irqrestore(&adapter->XmtZeroLock, flags);
2737 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XDumSgl2", 2760 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XDumSgl2",
2738 XmtCmd, pSgl, SxgSgl, 0); 2761 XmtCmd, pSgl, SxgSgl, 0);