Commit 776e7bde authored by Shahed Shaikh's avatar Shahed Shaikh Committed by David S. Miller

qlcnic: enable LRO on IPv6 without dest ip check

Signed-off-by: default avatarShahed Shaikh <shahed.shaikh@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c84e340a
...@@ -436,6 +436,7 @@ struct qlcnic_hardware_context { ...@@ -436,6 +436,7 @@ struct qlcnic_hardware_context {
u16 act_pci_func; u16 act_pci_func;
u32 capabilities; u32 capabilities;
u32 capabilities2;
u32 temp; u32 temp;
u32 int_vec_bit; u32 int_vec_bit;
u32 fw_hal_version; u32 fw_hal_version;
...@@ -798,6 +799,7 @@ struct qlcnic_mac_list_s { ...@@ -798,6 +799,7 @@ struct qlcnic_mac_list_s {
#define QLCNIC_FW_CAPABILITY_MORE_CAPS BIT_31 #define QLCNIC_FW_CAPABILITY_MORE_CAPS BIT_31
#define QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG BIT_2 #define QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG BIT_2
#define QLCNIC_FW_CAP2_HW_LRO_IPV6 BIT_3
#define QLCNIC_FW_CAPABILITY_2_OCBB BIT_5 #define QLCNIC_FW_CAPABILITY_2_OCBB BIT_5
/* module types */ /* module types */
......
...@@ -687,6 +687,11 @@ void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter) ...@@ -687,6 +687,11 @@ void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter)
"Could not send interrupt coalescing parameters\n"); "Could not send interrupt coalescing parameters\n");
} }
#define QLCNIC_ENABLE_IPV4_LRO 1
#define QLCNIC_ENABLE_IPV6_LRO 2
#define QLCNIC_NO_DEST_IPV4_CHECK (1 << 8)
#define QLCNIC_NO_DEST_IPV6_CHECK (2 << 8)
int qlcnic_82xx_config_hw_lro(struct qlcnic_adapter *adapter, int enable) int qlcnic_82xx_config_hw_lro(struct qlcnic_adapter *adapter, int enable)
{ {
struct qlcnic_nic_req req; struct qlcnic_nic_req req;
...@@ -703,7 +708,15 @@ int qlcnic_82xx_config_hw_lro(struct qlcnic_adapter *adapter, int enable) ...@@ -703,7 +708,15 @@ int qlcnic_82xx_config_hw_lro(struct qlcnic_adapter *adapter, int enable)
word = QLCNIC_H2C_OPCODE_CONFIG_HW_LRO | ((u64)adapter->portnum << 16); word = QLCNIC_H2C_OPCODE_CONFIG_HW_LRO | ((u64)adapter->portnum << 16);
req.req_hdr = cpu_to_le64(word); req.req_hdr = cpu_to_le64(word);
req.words[0] = cpu_to_le64(enable); word = 0;
if (enable) {
word = QLCNIC_ENABLE_IPV4_LRO | QLCNIC_NO_DEST_IPV4_CHECK;
if (adapter->ahw->capabilities2 & QLCNIC_FW_CAP2_HW_LRO_IPV6)
word |= QLCNIC_ENABLE_IPV6_LRO |
QLCNIC_NO_DEST_IPV6_CHECK;
}
req.words[0] = cpu_to_le64(word);
rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
if (rv != 0) if (rv != 0)
......
...@@ -973,6 +973,7 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, ...@@ -973,6 +973,7 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter,
struct sk_buff *skb; struct sk_buff *skb;
struct qlcnic_host_rds_ring *rds_ring; struct qlcnic_host_rds_ring *rds_ring;
struct iphdr *iph; struct iphdr *iph;
struct ipv6hdr *ipv6h;
struct tcphdr *th; struct tcphdr *th;
bool push, timestamp; bool push, timestamp;
int index, l2_hdr_offset, l4_hdr_offset; int index, l2_hdr_offset, l4_hdr_offset;
...@@ -1016,12 +1017,21 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, ...@@ -1016,12 +1017,21 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter,
} }
skb->protocol = eth_type_trans(skb, netdev); skb->protocol = eth_type_trans(skb, netdev);
if (htons(skb->protocol) == ETH_P_IPV6) {
ipv6h = (struct ipv6hdr *)skb->data;
th = (struct tcphdr *)(skb->data + sizeof(struct ipv6hdr));
length = (th->doff << 2) + lro_length;
ipv6h->payload_len = htons(length);
} else {
iph = (struct iphdr *)skb->data; iph = (struct iphdr *)skb->data;
th = (struct tcphdr *)(skb->data + (iph->ihl << 2)); th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
length = (iph->ihl << 2) + (th->doff << 2) + lro_length; length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
iph->tot_len = htons(length); iph->tot_len = htons(length);
iph->check = 0; iph->check = 0;
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
}
th->psh = push; th->psh = push;
th->seq = htonl(seq_number); th->seq = htonl(seq_number);
length = skb->len; length = skb->len;
......
...@@ -781,6 +781,12 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter) ...@@ -781,6 +781,12 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
adapter->ahw->max_tx_ques = nic_info.max_tx_ques; adapter->ahw->max_tx_ques = nic_info.max_tx_ques;
adapter->ahw->max_rx_ques = nic_info.max_rx_ques; adapter->ahw->max_rx_ques = nic_info.max_rx_ques;
adapter->ahw->capabilities = nic_info.capabilities; adapter->ahw->capabilities = nic_info.capabilities;
if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) {
u32 temp;
temp = QLCRD32(adapter, CRB_FW_CAPABILITIES_2);
adapter->ahw->capabilities2 = temp;
}
adapter->ahw->max_mac_filters = nic_info.max_mac_filters; adapter->ahw->max_mac_filters = nic_info.max_mac_filters;
adapter->ahw->max_mtu = nic_info.max_mtu; adapter->ahw->max_mtu = nic_info.max_mtu;
......
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