Commit 9914f053 authored by Mithlesh Thukral's avatar Mithlesh Thukral Committed by Greg Kroah-Hartman

Staging: sxg: Add Checksum Offload support for Sahara SXG driver

* This patch adds support for offloading checksum to hardware.
  IP checksum have been tested for IPv4 and IPv6.
Signed-off-by: default avatarLinSysSoft Sahara Team <saharaproj@linsyssoft.com>
Signed-off-by: default avatarMithlesh Thukral <mithlesh@linsyssoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent c1f46a00
...@@ -1078,6 +1078,7 @@ static int sxg_entry_probe(struct pci_dev *pcidev, ...@@ -1078,6 +1078,7 @@ static int sxg_entry_probe(struct pci_dev *pcidev,
netdev->get_stats = sxg_get_stats; netdev->get_stats = sxg_get_stats;
netdev->set_multicast_list = sxg_mcast_set_list; netdev->set_multicast_list = sxg_mcast_set_list;
SET_ETHTOOL_OPS(netdev, &sxg_nic_ethtool_ops); SET_ETHTOOL_OPS(netdev, &sxg_nic_ethtool_ops);
netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
err = sxg_set_interrupt_capability(adapter); err = sxg_set_interrupt_capability(adapter);
if (err != STATUS_SUCCESS) if (err != STATUS_SUCCESS)
DBG_ERROR("Cannot enable MSI-X capability\n"); DBG_ERROR("Cannot enable MSI-X capability\n");
...@@ -1432,6 +1433,31 @@ static int sxg_process_isr(struct adapter_t *adapter, u32 MessageId) ...@@ -1432,6 +1433,31 @@ static int sxg_process_isr(struct adapter_t *adapter, u32 MessageId)
return (NewIsr); return (NewIsr);
} }
/*
* sxg_rcv_checksum - Set the checksum for received packet
*
* Arguements:
* @skb - Packet which is receieved
* @Event - Event read from hardware
*/
void sxg_rcv_checksum(struct sk_buff *skb, struct sxg_event *Event)
{
skb->ip_summed = CHECKSUM_NONE;
if(Event->Status & EVENT_STATUS_TCPIP) {
if(!(Event->Status & EVENT_STATUS_TCPBAD)) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
if(!(Event->Status & EVENT_STATUS_IPBAD)) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
} else if(Event->Status & EVENT_STATUS_IPONLY) {
if(!(Event->Status & EVENT_STATUS_IPBAD)) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
}
}
/* /*
* sxg_process_event_queue - Process our event queue * sxg_process_event_queue - Process our event queue
* *
...@@ -1506,9 +1532,7 @@ static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId, ...@@ -1506,9 +1532,7 @@ static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId,
rx_bytes = Event->Length; rx_bytes = Event->Length;
adapter->stats.rx_packets++; adapter->stats.rx_packets++;
adapter->stats.rx_bytes += rx_bytes; adapter->stats.rx_bytes += rx_bytes;
#if SXG_OFFLOAD_IP_CHECKSUM sxg_rcv_checksum(skb, Event);
skb->ip_summed = CHECKSUM_UNNECESSARY;
#endif
skb->dev = adapter->netdev; skb->dev = adapter->netdev;
netif_receive_skb(skb); netif_receive_skb(skb);
#endif #endif
...@@ -2555,7 +2579,7 @@ static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl, ...@@ -2555,7 +2579,7 @@ 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) && (DataLength >= if ((ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) && (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) &
...@@ -2629,6 +2653,20 @@ static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl, ...@@ -2629,6 +2653,20 @@ static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
XmtCmd->Buffer.TotalLength = DataLength; XmtCmd->Buffer.TotalLength = DataLength;
XmtCmd->SgEntries = 1; XmtCmd->SgEntries = 1;
XmtCmd->Flags = 0; 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
...@@ -4064,6 +4102,8 @@ static int sxg_initialize_adapter(struct adapter_t *adapter) ...@@ -4064,6 +4102,8 @@ static int sxg_initialize_adapter(struct adapter_t *adapter)
WRITE_REG(adapter->UcodeRegs[0].ReceiveChecksum, WRITE_REG(adapter->UcodeRegs[0].ReceiveChecksum,
SXG_RCV_TCP_CSUM_ENABLED | SXG_RCV_IP_CSUM_ENABLED, TRUE); SXG_RCV_TCP_CSUM_ENABLED | SXG_RCV_IP_CSUM_ENABLED, TRUE);
adapter->flags |= (SXG_RCV_TCP_CSUM_ENABLED | SXG_RCV_IP_CSUM_ENABLED );
/* Initialize the MAC, XAUI */ /* Initialize the MAC, XAUI */
DBG_ERROR("sxg: %s ENTER sxg_initialize_link\n", __func__); DBG_ERROR("sxg: %s ENTER sxg_initialize_link\n", __func__);
status = sxg_initialize_link(adapter); status = sxg_initialize_link(adapter);
......
...@@ -1004,4 +1004,8 @@ struct sxg_ucode_stats { ...@@ -1004,4 +1004,8 @@ struct sxg_ucode_stats {
u32 XNoBufs; /* Xmt drop due to no DRAM Xmit buffer or PxyBuf */ u32 XNoBufs; /* Xmt drop due to no DRAM Xmit buffer or PxyBuf */
}; };
/*
* Macros for handling the Offload engine values
*/
/* Number of positions to shift Network Header Length before passing to card */
#define SXG_NW_HDR_LEN_SHIFT 2
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment