+++ /dev/null
-From 391587c3447d99b842a647f8e701895c9eea050b Mon Sep 17 00:00:00 2001
-From: Dhananjay Phadke <dhananjay@netxen.com>
-Date: Wed, 14 Jan 2009 20:48:11 -0800
-Subject: netxen: fix ipv6 offload and tx cleanup
-Acked-by: Karsten Keil <kkeil@novell.com>
-Reference: bnc#472416
-
-o fix the ip/tcp hdr offset in tx descriptors for ipv6.
-o cleanup xmit function, move the tso checks into separate function,
- this reduces unnecessary endian conversions back and forth.
-o optimize macros to initialize tx descriptors.
-
-Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
- drivers/net/netxen/netxen_nic.h | 43 ++++----------
- drivers/net/netxen/netxen_nic_hw.c | 4 -
- drivers/net/netxen/netxen_nic_main.c | 101 +++++++++++++++-------------------
- 3 files changed, 57 insertions(+), 91 deletions(-)
-
-Index: linux-2.6.27-kketmp/drivers/net/netxen/netxen_nic.h
-===================================================================
---- linux-2.6.27-kketmp.orig/drivers/net/netxen/netxen_nic.h
-+++ linux-2.6.27-kketmp/drivers/net/netxen/netxen_nic.h
-@@ -308,27 +308,16 @@ struct netxen_ring_ctx {
- #define netxen_set_cmd_desc_ctxid(cmd_desc, var) \
- ((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0))
-
--#define netxen_set_cmd_desc_flags(cmd_desc, val) \
-- (cmd_desc)->flags_opcode = ((cmd_desc)->flags_opcode & \
-- ~cpu_to_le16(0x7f)) | cpu_to_le16((val) & 0x7f)
--#define netxen_set_cmd_desc_opcode(cmd_desc, val) \
-- (cmd_desc)->flags_opcode = ((cmd_desc)->flags_opcode & \
-- ~cpu_to_le16((u16)0x3f << 7)) | cpu_to_le16(((val) & 0x3f) << 7)
--
--#define netxen_set_cmd_desc_num_of_buff(cmd_desc, val) \
-- (cmd_desc)->num_of_buffers_total_length = \
-- ((cmd_desc)->num_of_buffers_total_length & \
-- ~cpu_to_le32(0xff)) | cpu_to_le32((val) & 0xff)
--#define netxen_set_cmd_desc_totallength(cmd_desc, val) \
-- (cmd_desc)->num_of_buffers_total_length = \
-- ((cmd_desc)->num_of_buffers_total_length & \
-- ~cpu_to_le32((u32)0xffffff << 8)) | \
-- cpu_to_le32(((val) & 0xffffff) << 8)
--
--#define netxen_get_cmd_desc_opcode(cmd_desc) \
-- ((le16_to_cpu((cmd_desc)->flags_opcode) >> 7) & 0x003f)
--#define netxen_get_cmd_desc_totallength(cmd_desc) \
-- ((le32_to_cpu((cmd_desc)->num_of_buffers_total_length) >> 8) & 0xffffff)
-+#define netxen_set_tx_port(_desc, _port) \
-+ (_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0)
-+
-+#define netxen_set_tx_flags_opcode(_desc, _flags, _opcode) \
-+ (_desc)->flags_opcode = \
-+ cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7))
-+
-+#define netxen_set_tx_frags_len(_desc, _frags, _len) \
-+ (_desc)->num_of_buffers_total_length = \
-+ cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8))
-
- struct cmd_desc_type0 {
- u8 tcp_hdr_offset; /* For LSO only */
-@@ -757,7 +746,7 @@ extern char netxen_nic_driver_name[];
- */
- struct netxen_skb_frag {
- u64 dma;
-- u32 length;
-+ ulong length;
- };
-
- #define _netxen_set_bits(config_word, start, bits, val) {\
-@@ -783,13 +772,7 @@ struct netxen_skb_frag {
- struct netxen_cmd_buffer {
- struct sk_buff *skb;
- struct netxen_skb_frag frag_array[MAX_BUFFERS_PER_CMD + 1];
-- u32 total_length;
-- u32 mss;
-- u16 port;
-- u8 cmd;
-- u8 frag_count;
-- unsigned long time_stamp;
-- u32 state;
-+ u32 frag_count;
- };
-
- /* In rx_buffer, we do not need multiple fragments as is a single buffer */
-@@ -1486,8 +1469,6 @@ void netxen_release_tx_buffers(struct ne
-
- void netxen_initialize_adapter_ops(struct netxen_adapter *adapter);
- int netxen_init_firmware(struct netxen_adapter *adapter);
--void netxen_tso_check(struct netxen_adapter *adapter,
-- struct cmd_desc_type0 *desc, struct sk_buff *skb);
- void netxen_nic_clear_stats(struct netxen_adapter *adapter);
- void netxen_watchdog_task(struct work_struct *work);
- void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx,
-Index: linux-2.6.27-kketmp/drivers/net/netxen/netxen_nic_hw.c
-===================================================================
---- linux-2.6.27-kketmp.orig/drivers/net/netxen/netxen_nic_hw.c
-+++ linux-2.6.27-kketmp/drivers/net/netxen/netxen_nic_hw.c
-@@ -508,12 +508,8 @@ netxen_send_cmd_descs(struct netxen_adap
- cmd_desc = &cmd_desc_arr[i];
-
- pbuf = &adapter->cmd_buf_arr[producer];
-- pbuf->mss = 0;
-- pbuf->total_length = 0;
- pbuf->skb = NULL;
-- pbuf->cmd = 0;
- pbuf->frag_count = 0;
-- pbuf->port = 0;
-
- /* adapter->ahw.cmd_desc_head[producer] = *cmd_desc; */
- memcpy(&adapter->ahw.cmd_desc_head[producer],
-Index: linux-2.6.27-kketmp/drivers/net/netxen/netxen_nic_main.c
-===================================================================
---- linux-2.6.27-kketmp.orig/drivers/net/netxen/netxen_nic_main.c
-+++ linux-2.6.27-kketmp/drivers/net/netxen/netxen_nic_main.c
-@@ -39,6 +39,7 @@
- #include "netxen_nic_phan_reg.h"
-
- #include <linux/dma-mapping.h>
-+#include <linux/if_vlan.h>
- #include <net/ip.h>
-
- MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver");
-@@ -1126,29 +1127,46 @@ static int netxen_nic_close(struct net_d
- return 0;
- }
-
--void netxen_tso_check(struct netxen_adapter *adapter,
-+static bool netxen_tso_check(struct net_device *netdev,
- struct cmd_desc_type0 *desc, struct sk_buff *skb)
- {
-- if (desc->mss) {
-- desc->total_hdr_length = (sizeof(struct ethhdr) +
-- ip_hdrlen(skb) + tcp_hdrlen(skb));
--
-- if ((NX_IS_REVISION_P3(adapter->ahw.revision_id)) &&
-- (skb->protocol == htons(ETH_P_IPV6)))
-- netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO6);
-- else
-- netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO);
-+ bool tso = false;
-+ u8 opcode = TX_ETHER_PKT;
-+
-+ if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
-+ skb_shinfo(skb)->gso_size > 0) {
-+
-+ desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
-+ desc->total_hdr_length =
-+ skb_transport_offset(skb) + tcp_hdrlen(skb);
-+
-+ opcode = (skb->protocol == htons(ETH_P_IPV6)) ?
-+ TX_TCP_LSO6 : TX_TCP_LSO;
-+ tso = true;
-
- } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
-- if (ip_hdr(skb)->protocol == IPPROTO_TCP)
-- netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT);
-- else if (ip_hdr(skb)->protocol == IPPROTO_UDP)
-- netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT);
-- else
-- return;
-+ u8 l4proto;
-+
-+ if (skb->protocol == htons(ETH_P_IP)) {
-+ l4proto = ip_hdr(skb)->protocol;
-+
-+ if (l4proto == IPPROTO_TCP)
-+ opcode = TX_TCP_PKT;
-+ else if(l4proto == IPPROTO_UDP)
-+ opcode = TX_UDP_PKT;
-+ } else if (skb->protocol == htons(ETH_P_IPV6)) {
-+ l4proto = ipv6_hdr(skb)->nexthdr;
-+
-+ if (l4proto == IPPROTO_TCP)
-+ opcode = TX_TCPV6_PKT;
-+ else if(l4proto == IPPROTO_UDP)
-+ opcode = TX_UDPV6_PKT;
-+ }
- }
- desc->tcp_hdr_offset = skb_transport_offset(skb);
- desc->ip_hdr_offset = skb_network_offset(skb);
-+ netxen_set_tx_flags_opcode(desc, 0, opcode);
-+ return tso;
- }
-
- static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
-@@ -1156,33 +1174,20 @@ static int netxen_nic_xmit_frame(struct
- struct netxen_adapter *adapter = netdev_priv(netdev);
- struct netxen_hardware_context *hw = &adapter->ahw;
- unsigned int first_seg_len = skb->len - skb->data_len;
-+ struct netxen_cmd_buffer *pbuf;
- struct netxen_skb_frag *buffrag;
-- unsigned int i;
-+ struct cmd_desc_type0 *hwdesc;
-+ int i, k;
-
- u32 producer, consumer;
-- u32 saved_producer = 0;
-- struct cmd_desc_type0 *hwdesc;
-- int k;
-- struct netxen_cmd_buffer *pbuf = NULL;
-- int frag_count;
-- int no_of_desc;
-+ int frag_count, no_of_desc;
- u32 num_txd = adapter->max_tx_desc_count;
-+ bool is_tso = false;
-
- frag_count = skb_shinfo(skb)->nr_frags + 1;
-
- /* There 4 fragments per descriptor */
- no_of_desc = (frag_count + 3) >> 2;
-- if (netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) {
-- if (skb_shinfo(skb)->gso_size > 0) {
--
-- no_of_desc++;
-- if ((ip_hdrlen(skb) + tcp_hdrlen(skb) +
-- sizeof(struct ethhdr)) >
-- (sizeof(struct cmd_desc_type0) - 2)) {
-- no_of_desc++;
-- }
-- }
-- }
-
- producer = adapter->cmd_producer;
- smp_mb();
-@@ -1194,34 +1199,22 @@ static int netxen_nic_xmit_frame(struct
- }
-
- /* Copy the descriptors into the hardware */
-- saved_producer = producer;
- hwdesc = &hw->cmd_desc_head[producer];
- memset(hwdesc, 0, sizeof(struct cmd_desc_type0));
- /* Take skb->data itself */
- pbuf = &adapter->cmd_buf_arr[producer];
-- if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
-- skb_shinfo(skb)->gso_size > 0) {
-- pbuf->mss = skb_shinfo(skb)->gso_size;
-- hwdesc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
-- } else {
-- pbuf->mss = 0;
-- hwdesc->mss = 0;
-- }
-- pbuf->total_length = skb->len;
-+
-+ is_tso = netxen_tso_check(netdev, hwdesc, skb);
-+
- pbuf->skb = skb;
-- pbuf->cmd = TX_ETHER_PKT;
- pbuf->frag_count = frag_count;
-- pbuf->port = adapter->portnum;
- buffrag = &pbuf->frag_array[0];
- buffrag->dma = pci_map_single(adapter->pdev, skb->data, first_seg_len,
- PCI_DMA_TODEVICE);
- buffrag->length = first_seg_len;
-- netxen_set_cmd_desc_totallength(hwdesc, skb->len);
-- netxen_set_cmd_desc_num_of_buff(hwdesc, frag_count);
-- netxen_set_cmd_desc_opcode(hwdesc, TX_ETHER_PKT);
-+ netxen_set_tx_frags_len(hwdesc, frag_count, skb->len);
-+ netxen_set_tx_port(hwdesc, adapter->portnum);
-
-- netxen_set_cmd_desc_port(hwdesc, adapter->portnum);
-- netxen_set_cmd_desc_ctxid(hwdesc, adapter->portnum);
- hwdesc->buffer1_length = cpu_to_le16(first_seg_len);
- hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
-
-@@ -1274,16 +1267,12 @@ static int netxen_nic_xmit_frame(struct
- }
- producer = get_next_index(producer, num_txd);
-
-- /* might change opcode to TX_TCP_LSO */
-- netxen_tso_check(adapter, &hw->cmd_desc_head[saved_producer], skb);
--
- /* For LSO, we need to copy the MAC/IP/TCP headers into
- * the descriptor ring
- */
-- if (netxen_get_cmd_desc_opcode(&hw->cmd_desc_head[saved_producer])
-- == TX_TCP_LSO) {
-+ if (is_tso) {
- int hdr_len, first_hdr_len, more_hdr;
-- hdr_len = hw->cmd_desc_head[saved_producer].total_hdr_length;
-+ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
- if (hdr_len > (sizeof(struct cmd_desc_type0) - 2)) {
- first_hdr_len = sizeof(struct cmd_desc_type0) - 2;
- more_hdr = 1;