summaryrefslogtreecommitdiffstats
path: root/drivers/net/netxen/netxen_nic_main.c
diff options
context:
space:
mode:
authorDhananjay Phadke2009-07-26 22:07:45 +0200
committerDavid S. Miller2009-07-27 20:15:31 +0200
commit028afe719855a157e32450c36b7a12e1f9e85abe (patch)
tree5aac51f5fd2def91942bf7b9b46040aeb7d4b503 /drivers/net/netxen/netxen_nic_main.c
parentnetxen: fix skb alloc size for legacy firmware (diff)
downloadkernel-qcow2-linux-028afe719855a157e32450c36b7a12e1f9e85abe.tar.gz
kernel-qcow2-linux-028afe719855a157e32450c36b7a12e1f9e85abe.tar.xz
kernel-qcow2-linux-028afe719855a157e32450c36b7a12e1f9e85abe.zip
netxen: add vlan tx acceleration support
Enable vlan tx acceleration for NX3031 if firmware advertises capability. Signed-off-by: Amit Kumar Salecha <amit@netxen.com> Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/netxen/netxen_nic_main.c')
-rw-r--r--drivers/net/netxen/netxen_nic_main.c52
1 files changed, 47 insertions, 5 deletions
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 43a99f6a23df..ff7ee9c43ef5 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -1016,6 +1016,9 @@ netxen_setup_netdev(struct netxen_adapter *adapter,
netdev->vlan_features |= NETIF_F_HIGHDMA;
}
+ if (adapter->capabilities & NX_FW_CAPABILITY_FVLANTX)
+ netdev->features |= (NETIF_F_HW_VLAN_TX);
+
netdev->irq = adapter->msix_entries[0].vector;
err = netxen_napi_add(adapter, netdev);
@@ -1333,15 +1336,24 @@ netxen_tso_check(struct net_device *netdev,
{
u8 opcode = TX_ETHER_PKT;
__be16 protocol = skb->protocol;
- u16 flags = 0;
+ u16 flags = 0, vid = 0;
u32 producer;
- int copied, offset, copy_len, hdr_len = 0, tso = 0;
+ int copied, offset, copy_len, hdr_len = 0, tso = 0, vlan_oob = 0;
struct cmd_desc_type0 *hwdesc;
+ struct vlan_ethhdr *vh;
if (protocol == cpu_to_be16(ETH_P_8021Q)) {
- struct vlan_ethhdr *vh = (struct vlan_ethhdr *)skb->data;
+
+ vh = (struct vlan_ethhdr *)skb->data;
protocol = vh->h_vlan_encapsulated_proto;
flags = FLAGS_VLAN_TAGGED;
+
+ } else if (vlan_tx_tag_present(skb)) {
+
+ flags = FLAGS_VLAN_OOB;
+ vid = vlan_tx_tag_get(skb);
+ netxen_set_tx_vlan_tci(first_desc, vid);
+ vlan_oob = 1;
}
if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
@@ -1351,6 +1363,13 @@ netxen_tso_check(struct net_device *netdev,
first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
first_desc->total_hdr_length = hdr_len;
+ if (vlan_oob) {
+ first_desc->total_hdr_length += VLAN_HLEN;
+ first_desc->tcp_hdr_offset = VLAN_HLEN;
+ first_desc->ip_hdr_offset = VLAN_HLEN;
+ /* Only in case of TSO on vlan device */
+ flags |= FLAGS_VLAN_TAGGED;
+ }
opcode = (protocol == cpu_to_be16(ETH_P_IPV6)) ?
TX_TCP_LSO6 : TX_TCP_LSO;
@@ -1375,8 +1394,9 @@ netxen_tso_check(struct net_device *netdev,
opcode = TX_UDPV6_PKT;
}
}
- first_desc->tcp_hdr_offset = skb_transport_offset(skb);
- first_desc->ip_hdr_offset = skb_network_offset(skb);
+
+ first_desc->tcp_hdr_offset += skb_transport_offset(skb);
+ first_desc->ip_hdr_offset += skb_network_offset(skb);
netxen_set_tx_flags_opcode(first_desc, flags, opcode);
if (!tso)
@@ -1389,6 +1409,28 @@ netxen_tso_check(struct net_device *netdev,
copied = 0;
offset = 2;
+ if (vlan_oob) {
+ /* Create a TSO vlan header template for firmware */
+
+ hwdesc = &tx_ring->desc_head[producer];
+ tx_ring->cmd_buf_arr[producer].skb = NULL;
+
+ copy_len = min((int)sizeof(struct cmd_desc_type0) - offset,
+ hdr_len + VLAN_HLEN);
+
+ vh = (struct vlan_ethhdr *)((char *)hwdesc + 2);
+ skb_copy_from_linear_data(skb, vh, 12);
+ vh->h_vlan_proto = htons(ETH_P_8021Q);
+ vh->h_vlan_TCI = htons(vid);
+ skb_copy_from_linear_data_offset(skb, 12,
+ (char *)vh + 16, copy_len - 16);
+
+ copied = copy_len;
+ offset = 0;
+
+ producer = get_next_index(producer, tx_ring->num_desc);
+ }
+
while (copied < hdr_len) {
copy_len = min((int)sizeof(struct cmd_desc_type0) - offset,