Commit 028afe71 authored by Dhananjay Phadke's avatar Dhananjay Phadke Committed by David S. Miller

netxen: add vlan tx acceleration support

Enable vlan tx acceleration for NX3031 if firmware advertises
capability.
Signed-off-by: default avatarAmit Kumar Salecha <amit@netxen.com>
Signed-off-by: default avatarDhananjay Phadke <dhananjay@netxen.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9b08beba
...@@ -304,6 +304,10 @@ struct netxen_ring_ctx { ...@@ -304,6 +304,10 @@ struct netxen_ring_ctx {
#define FLAGS_IPSEC_SA_ADD 0x04 #define FLAGS_IPSEC_SA_ADD 0x04
#define FLAGS_IPSEC_SA_DELETE 0x08 #define FLAGS_IPSEC_SA_DELETE 0x08
#define FLAGS_VLAN_TAGGED 0x10 #define FLAGS_VLAN_TAGGED 0x10
#define FLAGS_VLAN_OOB 0x40
#define netxen_set_tx_vlan_tci(cmd_desc, v) \
(cmd_desc)->vlan_TCI = cpu_to_le16(v);
#define netxen_set_cmd_desc_port(cmd_desc, var) \ #define netxen_set_cmd_desc_port(cmd_desc, var) \
((cmd_desc)->port_ctxid |= ((var) & 0x0F)) ((cmd_desc)->port_ctxid |= ((var) & 0x0F))
...@@ -342,7 +346,9 @@ struct cmd_desc_type0 { ...@@ -342,7 +346,9 @@ struct cmd_desc_type0 {
__le64 addr_buffer4; __le64 addr_buffer4;
__le64 unused; __le16 vlan_TCI;
__le16 reserved;
__le32 reserved2;
} __attribute__ ((aligned(64))); } __attribute__ ((aligned(64)));
...@@ -1111,6 +1117,9 @@ typedef struct { ...@@ -1111,6 +1117,9 @@ typedef struct {
#define NX_FW_CAPABILITY_LINK_NOTIFICATION (1 << 5) #define NX_FW_CAPABILITY_LINK_NOTIFICATION (1 << 5)
#define NX_FW_CAPABILITY_SWITCHING (1 << 6) #define NX_FW_CAPABILITY_SWITCHING (1 << 6)
#define NX_FW_CAPABILITY_PEXQ (1 << 7)
#define NX_FW_CAPABILITY_BDG (1 << 8)
#define NX_FW_CAPABILITY_FVLANTX (1 << 9)
/* module types */ /* module types */
#define LINKEVENT_MODULE_NOT_PRESENT 1 #define LINKEVENT_MODULE_NOT_PRESENT 1
......
...@@ -1016,6 +1016,9 @@ netxen_setup_netdev(struct netxen_adapter *adapter, ...@@ -1016,6 +1016,9 @@ netxen_setup_netdev(struct netxen_adapter *adapter,
netdev->vlan_features |= NETIF_F_HIGHDMA; 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; netdev->irq = adapter->msix_entries[0].vector;
err = netxen_napi_add(adapter, netdev); err = netxen_napi_add(adapter, netdev);
...@@ -1333,15 +1336,24 @@ netxen_tso_check(struct net_device *netdev, ...@@ -1333,15 +1336,24 @@ netxen_tso_check(struct net_device *netdev,
{ {
u8 opcode = TX_ETHER_PKT; u8 opcode = TX_ETHER_PKT;
__be16 protocol = skb->protocol; __be16 protocol = skb->protocol;
u16 flags = 0; u16 flags = 0, vid = 0;
u32 producer; 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 cmd_desc_type0 *hwdesc;
struct vlan_ethhdr *vh;
if (protocol == cpu_to_be16(ETH_P_8021Q)) { 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; protocol = vh->h_vlan_encapsulated_proto;
flags = FLAGS_VLAN_TAGGED; 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)) && if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
...@@ -1351,6 +1363,13 @@ netxen_tso_check(struct net_device *netdev, ...@@ -1351,6 +1363,13 @@ netxen_tso_check(struct net_device *netdev,
first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
first_desc->total_hdr_length = hdr_len; 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)) ? opcode = (protocol == cpu_to_be16(ETH_P_IPV6)) ?
TX_TCP_LSO6 : TX_TCP_LSO; TX_TCP_LSO6 : TX_TCP_LSO;
...@@ -1375,8 +1394,9 @@ netxen_tso_check(struct net_device *netdev, ...@@ -1375,8 +1394,9 @@ netxen_tso_check(struct net_device *netdev,
opcode = TX_UDPV6_PKT; 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); netxen_set_tx_flags_opcode(first_desc, flags, opcode);
if (!tso) if (!tso)
...@@ -1389,6 +1409,28 @@ netxen_tso_check(struct net_device *netdev, ...@@ -1389,6 +1409,28 @@ netxen_tso_check(struct net_device *netdev,
copied = 0; copied = 0;
offset = 2; 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) { while (copied < hdr_len) {
copy_len = min((int)sizeof(struct cmd_desc_type0) - offset, copy_len = min((int)sizeof(struct cmd_desc_type0) - offset,
......
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