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>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
cc4b8dfc3f
commit
b824adc968
@@ -2582,6 +2582,7 @@ static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
|
|||||||
u64 phys_addr;
|
u64 phys_addr;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned long queue_id=0;
|
unsigned long queue_id=0;
|
||||||
|
int offload_cksum = 0;
|
||||||
|
|
||||||
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbSgl",
|
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbSgl",
|
||||||
pSgl, SxgSgl, 0, 0);
|
pSgl, SxgSgl, 0, 0);
|
||||||
@@ -2620,9 +2621,11 @@ static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
|
|||||||
struct iphdr *ip;
|
struct iphdr *ip;
|
||||||
|
|
||||||
ip = ip_hdr(skb);
|
ip = ip_hdr(skb);
|
||||||
if (ip->protocol != IPPROTO_TCP || !tcp_hdr(skb))
|
if (ip->protocol == IPPROTO_TCP)
|
||||||
|
offload_cksum = 1;
|
||||||
|
if (!offload_cksum || !tcp_hdr(skb))
|
||||||
queue_id = 0;
|
queue_id = 0;
|
||||||
else if ((ip->protocol == IPPROTO_TCP)&&(DataLength >= sizeof(
|
else if (offload_cksum && (DataLength >= sizeof(
|
||||||
struct tcphdr))){
|
struct tcphdr))){
|
||||||
queue_id = ((ntohs(tcp_hdr(skb)->dest) == ISCSI_PORT) ?
|
queue_id = ((ntohs(tcp_hdr(skb)->dest) == ISCSI_PORT) ?
|
||||||
(ntohs (tcp_hdr(skb)->source) &
|
(ntohs (tcp_hdr(skb)->source) &
|
||||||
@@ -2631,10 +2634,11 @@ static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
|
|||||||
SXG_LARGE_SEND_QUEUE_MASK));
|
SXG_LARGE_SEND_QUEUE_MASK));
|
||||||
}
|
}
|
||||||
} else if (skb->protocol == htons(ETH_P_IPV6)) {
|
} else if (skb->protocol == htons(ETH_P_IPV6)) {
|
||||||
if (ipv6_hdr(skb)->nexthdr != IPPROTO_TCP || !tcp_hdr(skb))
|
if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
|
||||||
|
offload_cksum = 1;
|
||||||
|
if (!offload_cksum || !tcp_hdr(skb))
|
||||||
queue_id = 0;
|
queue_id = 0;
|
||||||
else if ((ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) && (DataLength
|
else if (offload_cksum && (DataLength>=sizeof(struct tcphdr))){
|
||||||
>= sizeof(struct tcphdr)) ) {
|
|
||||||
queue_id = ((ntohs(tcp_hdr(skb)->dest) == ISCSI_PORT) ?
|
queue_id = ((ntohs(tcp_hdr(skb)->dest) == ISCSI_PORT) ?
|
||||||
(ntohs (tcp_hdr(skb)->source) &
|
(ntohs (tcp_hdr(skb)->source) &
|
||||||
SXG_LARGE_SEND_QUEUE_MASK):
|
SXG_LARGE_SEND_QUEUE_MASK):
|
||||||
@@ -2663,23 +2667,38 @@ static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
|
|||||||
}
|
}
|
||||||
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbCmd",
|
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbCmd",
|
||||||
XmtCmd, XmtRingInfo->Head, XmtRingInfo->Tail, 0);
|
XmtCmd, XmtRingInfo->Head, XmtRingInfo->Tail, 0);
|
||||||
/* Update stats */
|
memset(XmtCmd, '\0', sizeof(*XmtCmd));
|
||||||
adapter->stats.tx_packets++;
|
XmtCmd->SgEntries = 1;
|
||||||
adapter->stats.tx_bytes += DataLength;
|
XmtCmd->Flags = 0;
|
||||||
#if XXXTODO /* Stats stuff */
|
if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||||
if (SXG_MULTICAST_PACKET(EtherHdr)) {
|
/*
|
||||||
if (SXG_BROADCAST_PACKET(EtherHdr)) {
|
* We need to set the Checkum in IP header to 0. This is
|
||||||
adapter->Stats.DumbXmtBcastPkts++;
|
* required by hardware.
|
||||||
adapter->Stats.DumbXmtBcastBytes += DataLength;
|
*/
|
||||||
|
if (offload_cksum) {
|
||||||
|
ip_hdr(skb)->check = 0x0;
|
||||||
|
XmtCmd->CsumFlags.Flags |= SXG_SLOWCMD_CSUM_IP;
|
||||||
|
XmtCmd->CsumFlags.Flags |= SXG_SLOWCMD_CSUM_TCP;
|
||||||
|
/*
|
||||||
|
* Dont know if length will require a change in
|
||||||
|
* case of VLAN
|
||||||
|
*/
|
||||||
|
XmtCmd->CsumFlags.MacLen = ETH_HLEN;
|
||||||
|
XmtCmd->CsumFlags.IpHl = skb_network_header_len(skb) >>
|
||||||
|
SXG_NW_HDR_LEN_SHIFT;
|
||||||
} else {
|
} else {
|
||||||
adapter->Stats.DumbXmtMcastPkts++;
|
if (skb_checksum_help(skb)){
|
||||||
adapter->Stats.DumbXmtMcastBytes += DataLength;
|
printk(KERN_EMERG "Dropped UDP packet for"
|
||||||
|
" incorrect checksum calculation\n");
|
||||||
|
if (XmtCmd)
|
||||||
|
SXG_ABORT_CMD(XmtRingInfo);
|
||||||
|
spin_unlock_irqrestore(&adapter->XmtZeroLock,
|
||||||
|
flags);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
adapter->Stats.DumbXmtUcastPkts++;
|
|
||||||
adapter->Stats.DumbXmtUcastBytes += DataLength;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
/*
|
/*
|
||||||
* Fill in the command
|
* Fill in the command
|
||||||
* Copy out the first SGE to the command and adjust for offset
|
* 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,
|
|||||||
(SXG_INVALID_SGL(phys_addr,skb->data_len)))
|
(SXG_INVALID_SGL(phys_addr,skb->data_len)))
|
||||||
{
|
{
|
||||||
spin_unlock_irqrestore(&adapter->XmtZeroLock, flags);
|
spin_unlock_irqrestore(&adapter->XmtZeroLock, flags);
|
||||||
|
if (XmtCmd)
|
||||||
|
SXG_ABORT_CMD(XmtRingInfo);
|
||||||
/* Silently drop this packet */
|
/* Silently drop this packet */
|
||||||
printk(KERN_EMERG"Dropped a packet for 64k boundary problem\n");
|
printk(KERN_EMERG"Dropped a packet for 64k boundary problem\n");
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
memset(XmtCmd, '\0', sizeof(*XmtCmd));
|
|
||||||
XmtCmd->Buffer.FirstSgeAddress = phys_addr;
|
XmtCmd->Buffer.FirstSgeAddress = phys_addr;
|
||||||
XmtCmd->Buffer.FirstSgeLength = DataLength;
|
XmtCmd->Buffer.FirstSgeLength = DataLength;
|
||||||
XmtCmd->Buffer.SgeOffset = 0;
|
XmtCmd->Buffer.SgeOffset = 0;
|
||||||
XmtCmd->Buffer.TotalLength = DataLength;
|
XmtCmd->Buffer.TotalLength = DataLength;
|
||||||
XmtCmd->SgEntries = 1;
|
|
||||||
XmtCmd->Flags = 0;
|
|
||||||
|
|
||||||
if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
|
||||||
/*
|
|
||||||
* We need to set the Checkum in IP header to 0. This is
|
|
||||||
* required by hardware.
|
|
||||||
*/
|
|
||||||
ip_hdr(skb)->check = 0x0;
|
|
||||||
XmtCmd->CsumFlags.Flags |= SXG_SLOWCMD_CSUM_IP;
|
|
||||||
XmtCmd->CsumFlags.Flags |= SXG_SLOWCMD_CSUM_TCP;
|
|
||||||
/* Dont know if length will require a change in case of VLAN */
|
|
||||||
XmtCmd->CsumFlags.MacLen = ETH_HLEN;
|
|
||||||
XmtCmd->CsumFlags.IpHl = skb_network_header_len(skb) >>
|
|
||||||
SXG_NW_HDR_LEN_SHIFT;
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* Advance transmit cmd descripter by 1.
|
* Advance transmit cmd descripter by 1.
|
||||||
* NOTE - See comments in SxgTcpOutput where we write
|
* NOTE - See comments in SxgTcpOutput where we write
|
||||||
@@ -2733,6 +2738,24 @@ static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
|
|||||||
ASSERT((queue_id & ~SXG_LARGE_SEND_QUEUE_MASK) == 0);
|
ASSERT((queue_id & ~SXG_LARGE_SEND_QUEUE_MASK) == 0);
|
||||||
WRITE_REG(adapter->UcodeRegs[0].XmtCmd, ((queue_id << 16) | 1), TRUE);
|
WRITE_REG(adapter->UcodeRegs[0].XmtCmd, ((queue_id << 16) | 1), TRUE);
|
||||||
adapter->Stats.XmtQLen++; /* Stats within lock */
|
adapter->Stats.XmtQLen++; /* Stats within lock */
|
||||||
|
/* Update stats */
|
||||||
|
adapter->stats.tx_packets++;
|
||||||
|
adapter->stats.tx_bytes += DataLength;
|
||||||
|
#if XXXTODO /* Stats stuff */
|
||||||
|
if (SXG_MULTICAST_PACKET(EtherHdr)) {
|
||||||
|
if (SXG_BROADCAST_PACKET(EtherHdr)) {
|
||||||
|
adapter->Stats.DumbXmtBcastPkts++;
|
||||||
|
adapter->Stats.DumbXmtBcastBytes += DataLength;
|
||||||
|
} else {
|
||||||
|
adapter->Stats.DumbXmtMcastPkts++;
|
||||||
|
adapter->Stats.DumbXmtMcastBytes += DataLength;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
adapter->Stats.DumbXmtUcastPkts++;
|
||||||
|
adapter->Stats.DumbXmtUcastBytes += DataLength;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
spin_unlock_irqrestore(&adapter->XmtZeroLock, flags);
|
spin_unlock_irqrestore(&adapter->XmtZeroLock, flags);
|
||||||
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XDumSgl2",
|
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XDumSgl2",
|
||||||
XmtCmd, pSgl, SxgSgl, 0);
|
XmtCmd, pSgl, SxgSgl, 0);
|
||||||
|
Reference in New Issue
Block a user