Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

qlcnic: enable LRO on IPv6 without dest ip check

parent c84e340a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -436,6 +436,7 @@ struct qlcnic_hardware_context {
	u16 act_pci_func;

	u32 capabilities;
	u32 capabilities2;
	u32 temp;
	u32 int_vec_bit;
	u32 fw_hal_version;
@@ -798,6 +799,7 @@ struct qlcnic_mac_list_s {
#define QLCNIC_FW_CAPABILITY_MORE_CAPS		BIT_31

#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

/* module types */
+14 −1
Original line number Diff line number Diff line
@@ -687,6 +687,11 @@ void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter)
			"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)
{
	struct qlcnic_nic_req req;
@@ -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);
	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);
	if (rv != 0)
+16 −6
Original line number Diff line number Diff line
@@ -973,6 +973,7 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter,
	struct sk_buff *skb;
	struct qlcnic_host_rds_ring *rds_ring;
	struct iphdr *iph;
	struct ipv6hdr *ipv6h;
	struct tcphdr *th;
	bool push, timestamp;
	int index, l2_hdr_offset, l4_hdr_offset;
@@ -1016,12 +1017,21 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter,
	}

	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;
		th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
		length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
		iph->tot_len = htons(length);
		iph->check = 0;
		iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
	}

	th->psh = push;
	th->seq = htonl(seq_number);
	length = skb->len;
+6 −0
Original line number Diff line number Diff line
@@ -781,6 +781,12 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
	adapter->ahw->max_tx_ques = nic_info.max_tx_ques;
	adapter->ahw->max_rx_ques = nic_info.max_rx_ques;
	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_mtu = nic_info.max_mtu;