xref: /openbmc/linux/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c (revision e6eff2056b64376910b72e90fb9140500979da0b)
15ec8b7d1SJesse Brandeburg // SPDX-License-Identifier: GPL-2.0
25ec8b7d1SJesse Brandeburg /* Copyright(c) 2013 - 2018 Intel Corporation. */
35ec8b7d1SJesse Brandeburg 
45ec8b7d1SJesse Brandeburg #include "iavf.h"
566bc8e0fSJesse Brandeburg #include "iavf_prototype.h"
65ec8b7d1SJesse Brandeburg #include "iavf_client.h"
75ec8b7d1SJesse Brandeburg 
85ec8b7d1SJesse Brandeburg /**
95ec8b7d1SJesse Brandeburg  * iavf_send_pf_msg
105ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
115ec8b7d1SJesse Brandeburg  * @op: virtual channel opcode
125ec8b7d1SJesse Brandeburg  * @msg: pointer to message buffer
135ec8b7d1SJesse Brandeburg  * @len: message length
145ec8b7d1SJesse Brandeburg  *
155ec8b7d1SJesse Brandeburg  * Send message to PF and print status if failure.
165ec8b7d1SJesse Brandeburg  **/
iavf_send_pf_msg(struct iavf_adapter * adapter,enum virtchnl_ops op,u8 * msg,u16 len)175ec8b7d1SJesse Brandeburg static int iavf_send_pf_msg(struct iavf_adapter *adapter,
185ec8b7d1SJesse Brandeburg 			    enum virtchnl_ops op, u8 *msg, u16 len)
195ec8b7d1SJesse Brandeburg {
20f349daa5SJesse Brandeburg 	struct iavf_hw *hw = &adapter->hw;
21bae569d0SMateusz Palczewski 	enum iavf_status status;
225ec8b7d1SJesse Brandeburg 
235ec8b7d1SJesse Brandeburg 	if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
245ec8b7d1SJesse Brandeburg 		return 0; /* nothing to see here, move along */
255ec8b7d1SJesse Brandeburg 
26bae569d0SMateusz Palczewski 	status = iavf_aq_send_msg_to_pf(hw, op, 0, msg, len, NULL);
27bae569d0SMateusz Palczewski 	if (status)
28bae569d0SMateusz Palczewski 		dev_dbg(&adapter->pdev->dev, "Unable to send opcode %d to PF, status %s, aq_err %s\n",
29bae569d0SMateusz Palczewski 			op, iavf_stat_str(hw, status),
305ec8b7d1SJesse Brandeburg 			iavf_aq_str(hw, hw->aq.asq_last_status));
31bae569d0SMateusz Palczewski 	return iavf_status_to_errno(status);
325ec8b7d1SJesse Brandeburg }
335ec8b7d1SJesse Brandeburg 
345ec8b7d1SJesse Brandeburg /**
355ec8b7d1SJesse Brandeburg  * iavf_send_api_ver
365ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
375ec8b7d1SJesse Brandeburg  *
385ec8b7d1SJesse Brandeburg  * Send API version admin queue message to the PF. The reply is not checked
395ec8b7d1SJesse Brandeburg  * in this function. Returns 0 if the message was successfully
40fdad1d54SAlice Michael  * sent, or one of the IAVF_ADMIN_QUEUE_ERROR_ statuses if not.
415ec8b7d1SJesse Brandeburg  **/
iavf_send_api_ver(struct iavf_adapter * adapter)425ec8b7d1SJesse Brandeburg int iavf_send_api_ver(struct iavf_adapter *adapter)
435ec8b7d1SJesse Brandeburg {
445ec8b7d1SJesse Brandeburg 	struct virtchnl_version_info vvi;
455ec8b7d1SJesse Brandeburg 
465ec8b7d1SJesse Brandeburg 	vvi.major = VIRTCHNL_VERSION_MAJOR;
475ec8b7d1SJesse Brandeburg 	vvi.minor = VIRTCHNL_VERSION_MINOR;
485ec8b7d1SJesse Brandeburg 
495ec8b7d1SJesse Brandeburg 	return iavf_send_pf_msg(adapter, VIRTCHNL_OP_VERSION, (u8 *)&vvi,
505ec8b7d1SJesse Brandeburg 				sizeof(vvi));
515ec8b7d1SJesse Brandeburg }
525ec8b7d1SJesse Brandeburg 
535ec8b7d1SJesse Brandeburg /**
548fc16be6SMateusz Palczewski  * iavf_poll_virtchnl_msg
558fc16be6SMateusz Palczewski  * @hw: HW configuration structure
568fc16be6SMateusz Palczewski  * @event: event to populate on success
578fc16be6SMateusz Palczewski  * @op_to_poll: requested virtchnl op to poll for
588fc16be6SMateusz Palczewski  *
598fc16be6SMateusz Palczewski  * Initialize poll for virtchnl msg matching the requested_op. Returns 0
608fc16be6SMateusz Palczewski  * if a message of the correct opcode is in the queue or an error code
618fc16be6SMateusz Palczewski  * if no message matching the op code is waiting and other failures.
628fc16be6SMateusz Palczewski  */
638fc16be6SMateusz Palczewski static int
iavf_poll_virtchnl_msg(struct iavf_hw * hw,struct iavf_arq_event_info * event,enum virtchnl_ops op_to_poll)648fc16be6SMateusz Palczewski iavf_poll_virtchnl_msg(struct iavf_hw *hw, struct iavf_arq_event_info *event,
658fc16be6SMateusz Palczewski 		       enum virtchnl_ops op_to_poll)
668fc16be6SMateusz Palczewski {
678fc16be6SMateusz Palczewski 	enum virtchnl_ops received_op;
688fc16be6SMateusz Palczewski 	enum iavf_status status;
698fc16be6SMateusz Palczewski 	u32 v_retval;
708fc16be6SMateusz Palczewski 
718fc16be6SMateusz Palczewski 	while (1) {
728fc16be6SMateusz Palczewski 		/* When the AQ is empty, iavf_clean_arq_element will return
738fc16be6SMateusz Palczewski 		 * nonzero and this loop will terminate.
748fc16be6SMateusz Palczewski 		 */
758fc16be6SMateusz Palczewski 		status = iavf_clean_arq_element(hw, event, NULL);
768fc16be6SMateusz Palczewski 		if (status != IAVF_SUCCESS)
778fc16be6SMateusz Palczewski 			return iavf_status_to_errno(status);
788fc16be6SMateusz Palczewski 		received_op =
798fc16be6SMateusz Palczewski 		    (enum virtchnl_ops)le32_to_cpu(event->desc.cookie_high);
808fc16be6SMateusz Palczewski 		if (op_to_poll == received_op)
818fc16be6SMateusz Palczewski 			break;
828fc16be6SMateusz Palczewski 	}
838fc16be6SMateusz Palczewski 
848fc16be6SMateusz Palczewski 	v_retval = le32_to_cpu(event->desc.cookie_low);
858fc16be6SMateusz Palczewski 	return virtchnl_status_to_errno((enum virtchnl_status_code)v_retval);
868fc16be6SMateusz Palczewski }
878fc16be6SMateusz Palczewski 
888fc16be6SMateusz Palczewski /**
895ec8b7d1SJesse Brandeburg  * iavf_verify_api_ver
905ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
915ec8b7d1SJesse Brandeburg  *
925ec8b7d1SJesse Brandeburg  * Compare API versions with the PF. Must be called after admin queue is
935ec8b7d1SJesse Brandeburg  * initialized. Returns 0 if API versions match, -EIO if they do not,
948821b3faSAlice Michael  * IAVF_ERR_ADMIN_QUEUE_NO_WORK if the admin queue is empty, and any errors
955ec8b7d1SJesse Brandeburg  * from the firmware are propagated.
965ec8b7d1SJesse Brandeburg  **/
iavf_verify_api_ver(struct iavf_adapter * adapter)975ec8b7d1SJesse Brandeburg int iavf_verify_api_ver(struct iavf_adapter *adapter)
985ec8b7d1SJesse Brandeburg {
997af36e32SAlice Michael 	struct iavf_arq_event_info event;
1008fc16be6SMateusz Palczewski 	int err;
1015ec8b7d1SJesse Brandeburg 
1025ec8b7d1SJesse Brandeburg 	event.buf_len = IAVF_MAX_AQ_BUF_SIZE;
1038fc16be6SMateusz Palczewski 	event.msg_buf = kzalloc(IAVF_MAX_AQ_BUF_SIZE, GFP_KERNEL);
1048fc16be6SMateusz Palczewski 	if (!event.msg_buf)
1058fc16be6SMateusz Palczewski 		return -ENOMEM;
1065ec8b7d1SJesse Brandeburg 
1078fc16be6SMateusz Palczewski 	err = iavf_poll_virtchnl_msg(&adapter->hw, &event, VIRTCHNL_OP_VERSION);
1088fc16be6SMateusz Palczewski 	if (!err) {
1098fc16be6SMateusz Palczewski 		struct virtchnl_version_info *pf_vvi =
1108fc16be6SMateusz Palczewski 			(struct virtchnl_version_info *)event.msg_buf;
1115ec8b7d1SJesse Brandeburg 		adapter->pf_version = *pf_vvi;
1125ec8b7d1SJesse Brandeburg 
1138fc16be6SMateusz Palczewski 		if (pf_vvi->major > VIRTCHNL_VERSION_MAJOR ||
1148fc16be6SMateusz Palczewski 		    (pf_vvi->major == VIRTCHNL_VERSION_MAJOR &&
1158fc16be6SMateusz Palczewski 		     pf_vvi->minor > VIRTCHNL_VERSION_MINOR))
1165ec8b7d1SJesse Brandeburg 			err = -EIO;
1178fc16be6SMateusz Palczewski 	}
1185ec8b7d1SJesse Brandeburg 
1195ec8b7d1SJesse Brandeburg 	kfree(event.msg_buf);
1208fc16be6SMateusz Palczewski 
1215ec8b7d1SJesse Brandeburg 	return err;
1225ec8b7d1SJesse Brandeburg }
1235ec8b7d1SJesse Brandeburg 
1245ec8b7d1SJesse Brandeburg /**
1255ec8b7d1SJesse Brandeburg  * iavf_send_vf_config_msg
1265ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
1275ec8b7d1SJesse Brandeburg  *
1285ec8b7d1SJesse Brandeburg  * Send VF configuration request admin queue message to the PF. The reply
1295ec8b7d1SJesse Brandeburg  * is not checked in this function. Returns 0 if the message was
130fdad1d54SAlice Michael  * successfully sent, or one of the IAVF_ADMIN_QUEUE_ERROR_ statuses if not.
1315ec8b7d1SJesse Brandeburg  **/
iavf_send_vf_config_msg(struct iavf_adapter * adapter)1325ec8b7d1SJesse Brandeburg int iavf_send_vf_config_msg(struct iavf_adapter *adapter)
1335ec8b7d1SJesse Brandeburg {
1345ec8b7d1SJesse Brandeburg 	u32 caps;
1355ec8b7d1SJesse Brandeburg 
1365ec8b7d1SJesse Brandeburg 	caps = VIRTCHNL_VF_OFFLOAD_L2 |
1375ec8b7d1SJesse Brandeburg 	       VIRTCHNL_VF_OFFLOAD_RSS_PF |
1385ec8b7d1SJesse Brandeburg 	       VIRTCHNL_VF_OFFLOAD_RSS_AQ |
1395ec8b7d1SJesse Brandeburg 	       VIRTCHNL_VF_OFFLOAD_RSS_REG |
1405ec8b7d1SJesse Brandeburg 	       VIRTCHNL_VF_OFFLOAD_VLAN |
1415ec8b7d1SJesse Brandeburg 	       VIRTCHNL_VF_OFFLOAD_WB_ON_ITR |
1425ec8b7d1SJesse Brandeburg 	       VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2 |
1435ec8b7d1SJesse Brandeburg 	       VIRTCHNL_VF_OFFLOAD_ENCAP |
144209f2f9cSBrett Creeley 	       VIRTCHNL_VF_OFFLOAD_VLAN_V2 |
1455ec8b7d1SJesse Brandeburg 	       VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM |
1465ec8b7d1SJesse Brandeburg 	       VIRTCHNL_VF_OFFLOAD_REQ_QUEUES |
147e0ef26fbSBrett Creeley 	       VIRTCHNL_VF_OFFLOAD_ADQ |
148c91a4f9fSBrett Creeley 	       VIRTCHNL_VF_OFFLOAD_USO |
1490dbfbabbSHaiyue Wang 	       VIRTCHNL_VF_OFFLOAD_FDIR_PF |
1500aaeb4fbSHaiyue Wang 	       VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF |
151e0ef26fbSBrett Creeley 	       VIRTCHNL_VF_CAP_ADV_LINK_SPEED;
1525ec8b7d1SJesse Brandeburg 
1535ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_GET_VF_RESOURCES;
1545ec8b7d1SJesse Brandeburg 	adapter->aq_required &= ~IAVF_FLAG_AQ_GET_CONFIG;
1555ec8b7d1SJesse Brandeburg 	if (PF_IS_V11(adapter))
1565ec8b7d1SJesse Brandeburg 		return iavf_send_pf_msg(adapter, VIRTCHNL_OP_GET_VF_RESOURCES,
1575ec8b7d1SJesse Brandeburg 					(u8 *)&caps, sizeof(caps));
1585ec8b7d1SJesse Brandeburg 	else
1595ec8b7d1SJesse Brandeburg 		return iavf_send_pf_msg(adapter, VIRTCHNL_OP_GET_VF_RESOURCES,
1605ec8b7d1SJesse Brandeburg 					NULL, 0);
1615ec8b7d1SJesse Brandeburg }
1625ec8b7d1SJesse Brandeburg 
iavf_send_vf_offload_vlan_v2_msg(struct iavf_adapter * adapter)163209f2f9cSBrett Creeley int iavf_send_vf_offload_vlan_v2_msg(struct iavf_adapter *adapter)
164209f2f9cSBrett Creeley {
165209f2f9cSBrett Creeley 	adapter->aq_required &= ~IAVF_FLAG_AQ_GET_OFFLOAD_VLAN_V2_CAPS;
166209f2f9cSBrett Creeley 
167209f2f9cSBrett Creeley 	if (!VLAN_V2_ALLOWED(adapter))
168209f2f9cSBrett Creeley 		return -EOPNOTSUPP;
169209f2f9cSBrett Creeley 
170209f2f9cSBrett Creeley 	adapter->current_op = VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS;
171209f2f9cSBrett Creeley 
172209f2f9cSBrett Creeley 	return iavf_send_pf_msg(adapter, VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS,
173209f2f9cSBrett Creeley 				NULL, 0);
174209f2f9cSBrett Creeley }
175209f2f9cSBrett Creeley 
1765ec8b7d1SJesse Brandeburg /**
1775ec8b7d1SJesse Brandeburg  * iavf_validate_num_queues
1785ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
1795ec8b7d1SJesse Brandeburg  *
1805ec8b7d1SJesse Brandeburg  * Validate that the number of queues the PF has sent in
1815ec8b7d1SJesse Brandeburg  * VIRTCHNL_OP_GET_VF_RESOURCES is not larger than the VF can handle.
1825ec8b7d1SJesse Brandeburg  **/
iavf_validate_num_queues(struct iavf_adapter * adapter)1835ec8b7d1SJesse Brandeburg static void iavf_validate_num_queues(struct iavf_adapter *adapter)
1845ec8b7d1SJesse Brandeburg {
1855ec8b7d1SJesse Brandeburg 	if (adapter->vf_res->num_queue_pairs > IAVF_MAX_REQ_QUEUES) {
1865ec8b7d1SJesse Brandeburg 		struct virtchnl_vsi_resource *vsi_res;
1875ec8b7d1SJesse Brandeburg 		int i;
1885ec8b7d1SJesse Brandeburg 
1895ec8b7d1SJesse Brandeburg 		dev_info(&adapter->pdev->dev, "Received %d queues, but can only have a max of %d\n",
1905ec8b7d1SJesse Brandeburg 			 adapter->vf_res->num_queue_pairs,
1915ec8b7d1SJesse Brandeburg 			 IAVF_MAX_REQ_QUEUES);
1925ec8b7d1SJesse Brandeburg 		dev_info(&adapter->pdev->dev, "Fixing by reducing queues to %d\n",
1935ec8b7d1SJesse Brandeburg 			 IAVF_MAX_REQ_QUEUES);
1945ec8b7d1SJesse Brandeburg 		adapter->vf_res->num_queue_pairs = IAVF_MAX_REQ_QUEUES;
1955ec8b7d1SJesse Brandeburg 		for (i = 0; i < adapter->vf_res->num_vsis; i++) {
1965ec8b7d1SJesse Brandeburg 			vsi_res = &adapter->vf_res->vsi_res[i];
1975ec8b7d1SJesse Brandeburg 			vsi_res->num_queue_pairs = IAVF_MAX_REQ_QUEUES;
1985ec8b7d1SJesse Brandeburg 		}
1995ec8b7d1SJesse Brandeburg 	}
2005ec8b7d1SJesse Brandeburg }
2015ec8b7d1SJesse Brandeburg 
2025ec8b7d1SJesse Brandeburg /**
2035ec8b7d1SJesse Brandeburg  * iavf_get_vf_config
2045ec8b7d1SJesse Brandeburg  * @adapter: private adapter structure
2055ec8b7d1SJesse Brandeburg  *
2065ec8b7d1SJesse Brandeburg  * Get VF configuration from PF and populate hw structure. Must be called after
2075ec8b7d1SJesse Brandeburg  * admin queue is initialized. Busy waits until response is received from PF,
2085ec8b7d1SJesse Brandeburg  * with maximum timeout. Response from PF is returned in the buffer for further
2095ec8b7d1SJesse Brandeburg  * processing by the caller.
2105ec8b7d1SJesse Brandeburg  **/
iavf_get_vf_config(struct iavf_adapter * adapter)2115ec8b7d1SJesse Brandeburg int iavf_get_vf_config(struct iavf_adapter *adapter)
2125ec8b7d1SJesse Brandeburg {
213f349daa5SJesse Brandeburg 	struct iavf_hw *hw = &adapter->hw;
2147af36e32SAlice Michael 	struct iavf_arq_event_info event;
2155ec8b7d1SJesse Brandeburg 	u16 len;
2168fc16be6SMateusz Palczewski 	int err;
2175ec8b7d1SJesse Brandeburg 
2185e7f59faSAlexander Lobakin 	len = IAVF_VIRTCHNL_VF_RESOURCE_SIZE;
2195ec8b7d1SJesse Brandeburg 	event.buf_len = len;
2208fc16be6SMateusz Palczewski 	event.msg_buf = kzalloc(len, GFP_KERNEL);
2218fc16be6SMateusz Palczewski 	if (!event.msg_buf)
2228fc16be6SMateusz Palczewski 		return -ENOMEM;
2235ec8b7d1SJesse Brandeburg 
2248fc16be6SMateusz Palczewski 	err = iavf_poll_virtchnl_msg(hw, &event, VIRTCHNL_OP_GET_VF_RESOURCES);
2255ec8b7d1SJesse Brandeburg 	memcpy(adapter->vf_res, event.msg_buf, min(event.msg_len, len));
2265ec8b7d1SJesse Brandeburg 
2275ec8b7d1SJesse Brandeburg 	/* some PFs send more queues than we should have so validate that
2285ec8b7d1SJesse Brandeburg 	 * we aren't getting too many queues
2295ec8b7d1SJesse Brandeburg 	 */
2305ec8b7d1SJesse Brandeburg 	if (!err)
2315ec8b7d1SJesse Brandeburg 		iavf_validate_num_queues(adapter);
2325ec8b7d1SJesse Brandeburg 	iavf_vf_parse_hw_config(hw, adapter->vf_res);
2338fc16be6SMateusz Palczewski 
2345ec8b7d1SJesse Brandeburg 	kfree(event.msg_buf);
2358fc16be6SMateusz Palczewski 
2365ec8b7d1SJesse Brandeburg 	return err;
2375ec8b7d1SJesse Brandeburg }
2385ec8b7d1SJesse Brandeburg 
iavf_get_vf_vlan_v2_caps(struct iavf_adapter * adapter)239209f2f9cSBrett Creeley int iavf_get_vf_vlan_v2_caps(struct iavf_adapter *adapter)
240209f2f9cSBrett Creeley {
241209f2f9cSBrett Creeley 	struct iavf_arq_event_info event;
2428fc16be6SMateusz Palczewski 	int err;
243209f2f9cSBrett Creeley 	u16 len;
244209f2f9cSBrett Creeley 
245209f2f9cSBrett Creeley 	len = sizeof(struct virtchnl_vlan_caps);
246209f2f9cSBrett Creeley 	event.buf_len = len;
2478fc16be6SMateusz Palczewski 	event.msg_buf = kzalloc(len, GFP_KERNEL);
2488fc16be6SMateusz Palczewski 	if (!event.msg_buf)
2498fc16be6SMateusz Palczewski 		return -ENOMEM;
250209f2f9cSBrett Creeley 
2518fc16be6SMateusz Palczewski 	err = iavf_poll_virtchnl_msg(&adapter->hw, &event,
2528fc16be6SMateusz Palczewski 				     VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS);
2538fc16be6SMateusz Palczewski 	if (!err)
2548fc16be6SMateusz Palczewski 		memcpy(&adapter->vlan_v2_caps, event.msg_buf,
2558fc16be6SMateusz Palczewski 		       min(event.msg_len, len));
256209f2f9cSBrett Creeley 
257209f2f9cSBrett Creeley 	kfree(event.msg_buf);
2588fc16be6SMateusz Palczewski 
259209f2f9cSBrett Creeley 	return err;
260209f2f9cSBrett Creeley }
261209f2f9cSBrett Creeley 
2625ec8b7d1SJesse Brandeburg /**
2635ec8b7d1SJesse Brandeburg  * iavf_configure_queues
2645ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
2655ec8b7d1SJesse Brandeburg  *
2665ec8b7d1SJesse Brandeburg  * Request that the PF set up our (previously allocated) queues.
2675ec8b7d1SJesse Brandeburg  **/
iavf_configure_queues(struct iavf_adapter * adapter)2685ec8b7d1SJesse Brandeburg void iavf_configure_queues(struct iavf_adapter *adapter)
2695ec8b7d1SJesse Brandeburg {
2705ec8b7d1SJesse Brandeburg 	struct virtchnl_vsi_queue_config_info *vqci;
271399c98c4SMichal Jaron 	int i, max_frame = adapter->vf_res->max_mtu;
2725ec8b7d1SJesse Brandeburg 	int pairs = adapter->num_active_queues;
273399c98c4SMichal Jaron 	struct virtchnl_queue_pair_info *vqpi;
274af07adbbSGustavo A. R. Silva 	size_t len;
2755ec8b7d1SJesse Brandeburg 
276399c98c4SMichal Jaron 	if (max_frame > IAVF_MAX_RXBUFFER || !max_frame)
277399c98c4SMichal Jaron 		max_frame = IAVF_MAX_RXBUFFER;
278399c98c4SMichal Jaron 
2795ec8b7d1SJesse Brandeburg 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
2805ec8b7d1SJesse Brandeburg 		/* bail because we already have a command pending */
2815ec8b7d1SJesse Brandeburg 		dev_err(&adapter->pdev->dev, "Cannot configure queues, command %d pending\n",
2825ec8b7d1SJesse Brandeburg 			adapter->current_op);
2835ec8b7d1SJesse Brandeburg 		return;
2845ec8b7d1SJesse Brandeburg 	}
2855ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_CONFIG_VSI_QUEUES;
2865e7f59faSAlexander Lobakin 	len = virtchnl_struct_size(vqci, qpair, pairs);
2875ec8b7d1SJesse Brandeburg 	vqci = kzalloc(len, GFP_KERNEL);
2885ec8b7d1SJesse Brandeburg 	if (!vqci)
2895ec8b7d1SJesse Brandeburg 		return;
2905ec8b7d1SJesse Brandeburg 
2915ec8b7d1SJesse Brandeburg 	/* Limit maximum frame size when jumbo frames is not enabled */
2925ec8b7d1SJesse Brandeburg 	if (!(adapter->flags & IAVF_FLAG_LEGACY_RX) &&
2935ec8b7d1SJesse Brandeburg 	    (adapter->netdev->mtu <= ETH_DATA_LEN))
29456184e01SJesse Brandeburg 		max_frame = IAVF_RXBUFFER_1536 - NET_IP_ALIGN;
2955ec8b7d1SJesse Brandeburg 
2965ec8b7d1SJesse Brandeburg 	vqci->vsi_id = adapter->vsi_res->vsi_id;
2975ec8b7d1SJesse Brandeburg 	vqci->num_queue_pairs = pairs;
2985ec8b7d1SJesse Brandeburg 	vqpi = vqci->qpair;
2995ec8b7d1SJesse Brandeburg 	/* Size check is not needed here - HW max is 16 queue pairs, and we
3005ec8b7d1SJesse Brandeburg 	 * can fit info for 31 of them into the AQ buffer before it overflows.
3015ec8b7d1SJesse Brandeburg 	 */
3025ec8b7d1SJesse Brandeburg 	for (i = 0; i < pairs; i++) {
3035ec8b7d1SJesse Brandeburg 		vqpi->txq.vsi_id = vqci->vsi_id;
3045ec8b7d1SJesse Brandeburg 		vqpi->txq.queue_id = i;
3055ec8b7d1SJesse Brandeburg 		vqpi->txq.ring_len = adapter->tx_rings[i].count;
3065ec8b7d1SJesse Brandeburg 		vqpi->txq.dma_ring_addr = adapter->tx_rings[i].dma;
3075ec8b7d1SJesse Brandeburg 		vqpi->rxq.vsi_id = vqci->vsi_id;
3085ec8b7d1SJesse Brandeburg 		vqpi->rxq.queue_id = i;
3095ec8b7d1SJesse Brandeburg 		vqpi->rxq.ring_len = adapter->rx_rings[i].count;
3105ec8b7d1SJesse Brandeburg 		vqpi->rxq.dma_ring_addr = adapter->rx_rings[i].dma;
3115ec8b7d1SJesse Brandeburg 		vqpi->rxq.max_pkt_size = max_frame;
3125ec8b7d1SJesse Brandeburg 		vqpi->rxq.databuffer_size =
3135ec8b7d1SJesse Brandeburg 			ALIGN(adapter->rx_rings[i].rx_buf_len,
31456184e01SJesse Brandeburg 			      BIT_ULL(IAVF_RXQ_CTX_DBUFF_SHIFT));
3155ec8b7d1SJesse Brandeburg 		vqpi++;
3165ec8b7d1SJesse Brandeburg 	}
3175ec8b7d1SJesse Brandeburg 
3185ec8b7d1SJesse Brandeburg 	adapter->aq_required &= ~IAVF_FLAG_AQ_CONFIGURE_QUEUES;
3195ec8b7d1SJesse Brandeburg 	iavf_send_pf_msg(adapter, VIRTCHNL_OP_CONFIG_VSI_QUEUES,
3205ec8b7d1SJesse Brandeburg 			 (u8 *)vqci, len);
3215ec8b7d1SJesse Brandeburg 	kfree(vqci);
3225ec8b7d1SJesse Brandeburg }
3235ec8b7d1SJesse Brandeburg 
3245ec8b7d1SJesse Brandeburg /**
3255ec8b7d1SJesse Brandeburg  * iavf_enable_queues
3265ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
3275ec8b7d1SJesse Brandeburg  *
3285ec8b7d1SJesse Brandeburg  * Request that the PF enable all of our queues.
3295ec8b7d1SJesse Brandeburg  **/
iavf_enable_queues(struct iavf_adapter * adapter)3305ec8b7d1SJesse Brandeburg void iavf_enable_queues(struct iavf_adapter *adapter)
3315ec8b7d1SJesse Brandeburg {
3325ec8b7d1SJesse Brandeburg 	struct virtchnl_queue_select vqs;
3335ec8b7d1SJesse Brandeburg 
3345ec8b7d1SJesse Brandeburg 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
3355ec8b7d1SJesse Brandeburg 		/* bail because we already have a command pending */
3365ec8b7d1SJesse Brandeburg 		dev_err(&adapter->pdev->dev, "Cannot enable queues, command %d pending\n",
3375ec8b7d1SJesse Brandeburg 			adapter->current_op);
3385ec8b7d1SJesse Brandeburg 		return;
3395ec8b7d1SJesse Brandeburg 	}
3405ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_ENABLE_QUEUES;
3415ec8b7d1SJesse Brandeburg 	vqs.vsi_id = adapter->vsi_res->vsi_id;
3425ec8b7d1SJesse Brandeburg 	vqs.tx_queues = BIT(adapter->num_active_queues) - 1;
3435ec8b7d1SJesse Brandeburg 	vqs.rx_queues = vqs.tx_queues;
3445ec8b7d1SJesse Brandeburg 	adapter->aq_required &= ~IAVF_FLAG_AQ_ENABLE_QUEUES;
3455ec8b7d1SJesse Brandeburg 	iavf_send_pf_msg(adapter, VIRTCHNL_OP_ENABLE_QUEUES,
3465ec8b7d1SJesse Brandeburg 			 (u8 *)&vqs, sizeof(vqs));
3475ec8b7d1SJesse Brandeburg }
3485ec8b7d1SJesse Brandeburg 
3495ec8b7d1SJesse Brandeburg /**
3505ec8b7d1SJesse Brandeburg  * iavf_disable_queues
3515ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
3525ec8b7d1SJesse Brandeburg  *
3535ec8b7d1SJesse Brandeburg  * Request that the PF disable all of our queues.
3545ec8b7d1SJesse Brandeburg  **/
iavf_disable_queues(struct iavf_adapter * adapter)3555ec8b7d1SJesse Brandeburg void iavf_disable_queues(struct iavf_adapter *adapter)
3565ec8b7d1SJesse Brandeburg {
3575ec8b7d1SJesse Brandeburg 	struct virtchnl_queue_select vqs;
3585ec8b7d1SJesse Brandeburg 
3595ec8b7d1SJesse Brandeburg 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
3605ec8b7d1SJesse Brandeburg 		/* bail because we already have a command pending */
3615ec8b7d1SJesse Brandeburg 		dev_err(&adapter->pdev->dev, "Cannot disable queues, command %d pending\n",
3625ec8b7d1SJesse Brandeburg 			adapter->current_op);
3635ec8b7d1SJesse Brandeburg 		return;
3645ec8b7d1SJesse Brandeburg 	}
3655ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_DISABLE_QUEUES;
3665ec8b7d1SJesse Brandeburg 	vqs.vsi_id = adapter->vsi_res->vsi_id;
3675ec8b7d1SJesse Brandeburg 	vqs.tx_queues = BIT(adapter->num_active_queues) - 1;
3685ec8b7d1SJesse Brandeburg 	vqs.rx_queues = vqs.tx_queues;
3695ec8b7d1SJesse Brandeburg 	adapter->aq_required &= ~IAVF_FLAG_AQ_DISABLE_QUEUES;
3705ec8b7d1SJesse Brandeburg 	iavf_send_pf_msg(adapter, VIRTCHNL_OP_DISABLE_QUEUES,
3715ec8b7d1SJesse Brandeburg 			 (u8 *)&vqs, sizeof(vqs));
3725ec8b7d1SJesse Brandeburg }
3735ec8b7d1SJesse Brandeburg 
3745ec8b7d1SJesse Brandeburg /**
3755ec8b7d1SJesse Brandeburg  * iavf_map_queues
3765ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
3775ec8b7d1SJesse Brandeburg  *
3785ec8b7d1SJesse Brandeburg  * Request that the PF map queues to interrupt vectors. Misc causes, including
3795ec8b7d1SJesse Brandeburg  * admin queue, are always mapped to vector 0.
3805ec8b7d1SJesse Brandeburg  **/
iavf_map_queues(struct iavf_adapter * adapter)3815ec8b7d1SJesse Brandeburg void iavf_map_queues(struct iavf_adapter *adapter)
3825ec8b7d1SJesse Brandeburg {
3835ec8b7d1SJesse Brandeburg 	struct virtchnl_irq_map_info *vimi;
3845ec8b7d1SJesse Brandeburg 	struct virtchnl_vector_map *vecmap;
38556184e01SJesse Brandeburg 	struct iavf_q_vector *q_vector;
386af07adbbSGustavo A. R. Silva 	int v_idx, q_vectors;
387af07adbbSGustavo A. R. Silva 	size_t len;
3885ec8b7d1SJesse Brandeburg 
3895ec8b7d1SJesse Brandeburg 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
3905ec8b7d1SJesse Brandeburg 		/* bail because we already have a command pending */
3915ec8b7d1SJesse Brandeburg 		dev_err(&adapter->pdev->dev, "Cannot map queues to vectors, command %d pending\n",
3925ec8b7d1SJesse Brandeburg 			adapter->current_op);
3935ec8b7d1SJesse Brandeburg 		return;
3945ec8b7d1SJesse Brandeburg 	}
3955ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_CONFIG_IRQ_MAP;
3965ec8b7d1SJesse Brandeburg 
3975ec8b7d1SJesse Brandeburg 	q_vectors = adapter->num_msix_vectors - NONQ_VECS;
3985ec8b7d1SJesse Brandeburg 
3995e7f59faSAlexander Lobakin 	len = virtchnl_struct_size(vimi, vecmap, adapter->num_msix_vectors);
4005ec8b7d1SJesse Brandeburg 	vimi = kzalloc(len, GFP_KERNEL);
4015ec8b7d1SJesse Brandeburg 	if (!vimi)
4025ec8b7d1SJesse Brandeburg 		return;
4035ec8b7d1SJesse Brandeburg 
4045ec8b7d1SJesse Brandeburg 	vimi->num_vectors = adapter->num_msix_vectors;
4055ec8b7d1SJesse Brandeburg 	/* Queue vectors first */
4065ec8b7d1SJesse Brandeburg 	for (v_idx = 0; v_idx < q_vectors; v_idx++) {
4075ec8b7d1SJesse Brandeburg 		q_vector = &adapter->q_vectors[v_idx];
4085ec8b7d1SJesse Brandeburg 		vecmap = &vimi->vecmap[v_idx];
4095ec8b7d1SJesse Brandeburg 
4105ec8b7d1SJesse Brandeburg 		vecmap->vsi_id = adapter->vsi_res->vsi_id;
4115ec8b7d1SJesse Brandeburg 		vecmap->vector_id = v_idx + NONQ_VECS;
4125ec8b7d1SJesse Brandeburg 		vecmap->txq_map = q_vector->ring_mask;
4135ec8b7d1SJesse Brandeburg 		vecmap->rxq_map = q_vector->ring_mask;
41456184e01SJesse Brandeburg 		vecmap->rxitr_idx = IAVF_RX_ITR;
41556184e01SJesse Brandeburg 		vecmap->txitr_idx = IAVF_TX_ITR;
4165ec8b7d1SJesse Brandeburg 	}
4175ec8b7d1SJesse Brandeburg 	/* Misc vector last - this is only for AdminQ messages */
4185ec8b7d1SJesse Brandeburg 	vecmap = &vimi->vecmap[v_idx];
4195ec8b7d1SJesse Brandeburg 	vecmap->vsi_id = adapter->vsi_res->vsi_id;
4205ec8b7d1SJesse Brandeburg 	vecmap->vector_id = 0;
4215ec8b7d1SJesse Brandeburg 	vecmap->txq_map = 0;
4225ec8b7d1SJesse Brandeburg 	vecmap->rxq_map = 0;
4235ec8b7d1SJesse Brandeburg 
4245ec8b7d1SJesse Brandeburg 	adapter->aq_required &= ~IAVF_FLAG_AQ_MAP_VECTORS;
4255ec8b7d1SJesse Brandeburg 	iavf_send_pf_msg(adapter, VIRTCHNL_OP_CONFIG_IRQ_MAP,
4265ec8b7d1SJesse Brandeburg 			 (u8 *)vimi, len);
4275ec8b7d1SJesse Brandeburg 	kfree(vimi);
4285ec8b7d1SJesse Brandeburg }
4295ec8b7d1SJesse Brandeburg 
4305ec8b7d1SJesse Brandeburg /**
431a3e839d5SMateusz Palczewski  * iavf_set_mac_addr_type - Set the correct request type from the filter type
432a3e839d5SMateusz Palczewski  * @virtchnl_ether_addr: pointer to requested list element
433a3e839d5SMateusz Palczewski  * @filter: pointer to requested filter
434a3e839d5SMateusz Palczewski  **/
435a3e839d5SMateusz Palczewski static void
iavf_set_mac_addr_type(struct virtchnl_ether_addr * virtchnl_ether_addr,const struct iavf_mac_filter * filter)436a3e839d5SMateusz Palczewski iavf_set_mac_addr_type(struct virtchnl_ether_addr *virtchnl_ether_addr,
437a3e839d5SMateusz Palczewski 		       const struct iavf_mac_filter *filter)
438a3e839d5SMateusz Palczewski {
439a3e839d5SMateusz Palczewski 	virtchnl_ether_addr->type = filter->is_primary ?
440a3e839d5SMateusz Palczewski 		VIRTCHNL_ETHER_ADDR_PRIMARY :
441a3e839d5SMateusz Palczewski 		VIRTCHNL_ETHER_ADDR_EXTRA;
442a3e839d5SMateusz Palczewski }
443a3e839d5SMateusz Palczewski 
444a3e839d5SMateusz Palczewski /**
4455ec8b7d1SJesse Brandeburg  * iavf_add_ether_addrs
4465ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
4475ec8b7d1SJesse Brandeburg  *
4485ec8b7d1SJesse Brandeburg  * Request that the PF add one or more addresses to our filters.
4495ec8b7d1SJesse Brandeburg  **/
iavf_add_ether_addrs(struct iavf_adapter * adapter)4505ec8b7d1SJesse Brandeburg void iavf_add_ether_addrs(struct iavf_adapter *adapter)
4515ec8b7d1SJesse Brandeburg {
4525ec8b7d1SJesse Brandeburg 	struct virtchnl_ether_addr_list *veal;
4535ec8b7d1SJesse Brandeburg 	struct iavf_mac_filter *f;
454af07adbbSGustavo A. R. Silva 	int i = 0, count = 0;
4555ec8b7d1SJesse Brandeburg 	bool more = false;
456af07adbbSGustavo A. R. Silva 	size_t len;
4575ec8b7d1SJesse Brandeburg 
4585ec8b7d1SJesse Brandeburg 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
4595ec8b7d1SJesse Brandeburg 		/* bail because we already have a command pending */
4605ec8b7d1SJesse Brandeburg 		dev_err(&adapter->pdev->dev, "Cannot add filters, command %d pending\n",
4615ec8b7d1SJesse Brandeburg 			adapter->current_op);
4625ec8b7d1SJesse Brandeburg 		return;
4635ec8b7d1SJesse Brandeburg 	}
4645ec8b7d1SJesse Brandeburg 
4655ec8b7d1SJesse Brandeburg 	spin_lock_bh(&adapter->mac_vlan_list_lock);
4665ec8b7d1SJesse Brandeburg 
4675ec8b7d1SJesse Brandeburg 	list_for_each_entry(f, &adapter->mac_filter_list, list) {
4685ec8b7d1SJesse Brandeburg 		if (f->add)
4695ec8b7d1SJesse Brandeburg 			count++;
4705ec8b7d1SJesse Brandeburg 	}
4715ec8b7d1SJesse Brandeburg 	if (!count) {
4725ec8b7d1SJesse Brandeburg 		adapter->aq_required &= ~IAVF_FLAG_AQ_ADD_MAC_FILTER;
4735ec8b7d1SJesse Brandeburg 		spin_unlock_bh(&adapter->mac_vlan_list_lock);
4745ec8b7d1SJesse Brandeburg 		return;
4755ec8b7d1SJesse Brandeburg 	}
4765ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_ADD_ETH_ADDR;
4775ec8b7d1SJesse Brandeburg 
4785e7f59faSAlexander Lobakin 	len = virtchnl_struct_size(veal, list, count);
4795ec8b7d1SJesse Brandeburg 	if (len > IAVF_MAX_AQ_BUF_SIZE) {
4805ec8b7d1SJesse Brandeburg 		dev_warn(&adapter->pdev->dev, "Too many add MAC changes in one request\n");
4815e7f59faSAlexander Lobakin 		while (len > IAVF_MAX_AQ_BUF_SIZE)
4825e7f59faSAlexander Lobakin 			len = virtchnl_struct_size(veal, list, --count);
4835ec8b7d1SJesse Brandeburg 		more = true;
4845ec8b7d1SJesse Brandeburg 	}
4855ec8b7d1SJesse Brandeburg 
4865ec8b7d1SJesse Brandeburg 	veal = kzalloc(len, GFP_ATOMIC);
4875ec8b7d1SJesse Brandeburg 	if (!veal) {
4885ec8b7d1SJesse Brandeburg 		spin_unlock_bh(&adapter->mac_vlan_list_lock);
4895ec8b7d1SJesse Brandeburg 		return;
4905ec8b7d1SJesse Brandeburg 	}
4915ec8b7d1SJesse Brandeburg 
4925ec8b7d1SJesse Brandeburg 	veal->vsi_id = adapter->vsi_res->vsi_id;
4935ec8b7d1SJesse Brandeburg 	veal->num_elements = count;
4945ec8b7d1SJesse Brandeburg 	list_for_each_entry(f, &adapter->mac_filter_list, list) {
4955ec8b7d1SJesse Brandeburg 		if (f->add) {
4965ec8b7d1SJesse Brandeburg 			ether_addr_copy(veal->list[i].addr, f->macaddr);
497a3e839d5SMateusz Palczewski 			iavf_set_mac_addr_type(&veal->list[i], f);
4985ec8b7d1SJesse Brandeburg 			i++;
4995ec8b7d1SJesse Brandeburg 			f->add = false;
5005ec8b7d1SJesse Brandeburg 			if (i == count)
5015ec8b7d1SJesse Brandeburg 				break;
5025ec8b7d1SJesse Brandeburg 		}
5035ec8b7d1SJesse Brandeburg 	}
5045ec8b7d1SJesse Brandeburg 	if (!more)
5055ec8b7d1SJesse Brandeburg 		adapter->aq_required &= ~IAVF_FLAG_AQ_ADD_MAC_FILTER;
5065ec8b7d1SJesse Brandeburg 
5075ec8b7d1SJesse Brandeburg 	spin_unlock_bh(&adapter->mac_vlan_list_lock);
5085ec8b7d1SJesse Brandeburg 
5095ec8b7d1SJesse Brandeburg 	iavf_send_pf_msg(adapter, VIRTCHNL_OP_ADD_ETH_ADDR, (u8 *)veal, len);
5105ec8b7d1SJesse Brandeburg 	kfree(veal);
5115ec8b7d1SJesse Brandeburg }
5125ec8b7d1SJesse Brandeburg 
5135ec8b7d1SJesse Brandeburg /**
5145ec8b7d1SJesse Brandeburg  * iavf_del_ether_addrs
5155ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
5165ec8b7d1SJesse Brandeburg  *
5175ec8b7d1SJesse Brandeburg  * Request that the PF remove one or more addresses from our filters.
5185ec8b7d1SJesse Brandeburg  **/
iavf_del_ether_addrs(struct iavf_adapter * adapter)5195ec8b7d1SJesse Brandeburg void iavf_del_ether_addrs(struct iavf_adapter *adapter)
5205ec8b7d1SJesse Brandeburg {
5215ec8b7d1SJesse Brandeburg 	struct virtchnl_ether_addr_list *veal;
5225ec8b7d1SJesse Brandeburg 	struct iavf_mac_filter *f, *ftmp;
523af07adbbSGustavo A. R. Silva 	int i = 0, count = 0;
5245ec8b7d1SJesse Brandeburg 	bool more = false;
525af07adbbSGustavo A. R. Silva 	size_t len;
5265ec8b7d1SJesse Brandeburg 
5275ec8b7d1SJesse Brandeburg 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
5285ec8b7d1SJesse Brandeburg 		/* bail because we already have a command pending */
5295ec8b7d1SJesse Brandeburg 		dev_err(&adapter->pdev->dev, "Cannot remove filters, command %d pending\n",
5305ec8b7d1SJesse Brandeburg 			adapter->current_op);
5315ec8b7d1SJesse Brandeburg 		return;
5325ec8b7d1SJesse Brandeburg 	}
5335ec8b7d1SJesse Brandeburg 
5345ec8b7d1SJesse Brandeburg 	spin_lock_bh(&adapter->mac_vlan_list_lock);
5355ec8b7d1SJesse Brandeburg 
5365ec8b7d1SJesse Brandeburg 	list_for_each_entry(f, &adapter->mac_filter_list, list) {
5375ec8b7d1SJesse Brandeburg 		if (f->remove)
5385ec8b7d1SJesse Brandeburg 			count++;
5395ec8b7d1SJesse Brandeburg 	}
5405ec8b7d1SJesse Brandeburg 	if (!count) {
5415ec8b7d1SJesse Brandeburg 		adapter->aq_required &= ~IAVF_FLAG_AQ_DEL_MAC_FILTER;
5425ec8b7d1SJesse Brandeburg 		spin_unlock_bh(&adapter->mac_vlan_list_lock);
5435ec8b7d1SJesse Brandeburg 		return;
5445ec8b7d1SJesse Brandeburg 	}
5455ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_DEL_ETH_ADDR;
5465ec8b7d1SJesse Brandeburg 
5475e7f59faSAlexander Lobakin 	len = virtchnl_struct_size(veal, list, count);
5485ec8b7d1SJesse Brandeburg 	if (len > IAVF_MAX_AQ_BUF_SIZE) {
5495ec8b7d1SJesse Brandeburg 		dev_warn(&adapter->pdev->dev, "Too many delete MAC changes in one request\n");
5505e7f59faSAlexander Lobakin 		while (len > IAVF_MAX_AQ_BUF_SIZE)
5515e7f59faSAlexander Lobakin 			len = virtchnl_struct_size(veal, list, --count);
5525ec8b7d1SJesse Brandeburg 		more = true;
5535ec8b7d1SJesse Brandeburg 	}
5545ec8b7d1SJesse Brandeburg 	veal = kzalloc(len, GFP_ATOMIC);
5555ec8b7d1SJesse Brandeburg 	if (!veal) {
5565ec8b7d1SJesse Brandeburg 		spin_unlock_bh(&adapter->mac_vlan_list_lock);
5575ec8b7d1SJesse Brandeburg 		return;
5585ec8b7d1SJesse Brandeburg 	}
5595ec8b7d1SJesse Brandeburg 
5605ec8b7d1SJesse Brandeburg 	veal->vsi_id = adapter->vsi_res->vsi_id;
5615ec8b7d1SJesse Brandeburg 	veal->num_elements = count;
5625ec8b7d1SJesse Brandeburg 	list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
5635ec8b7d1SJesse Brandeburg 		if (f->remove) {
5645ec8b7d1SJesse Brandeburg 			ether_addr_copy(veal->list[i].addr, f->macaddr);
565a3e839d5SMateusz Palczewski 			iavf_set_mac_addr_type(&veal->list[i], f);
5665ec8b7d1SJesse Brandeburg 			i++;
5675ec8b7d1SJesse Brandeburg 			list_del(&f->list);
5685ec8b7d1SJesse Brandeburg 			kfree(f);
5695ec8b7d1SJesse Brandeburg 			if (i == count)
5705ec8b7d1SJesse Brandeburg 				break;
5715ec8b7d1SJesse Brandeburg 		}
5725ec8b7d1SJesse Brandeburg 	}
5735ec8b7d1SJesse Brandeburg 	if (!more)
5745ec8b7d1SJesse Brandeburg 		adapter->aq_required &= ~IAVF_FLAG_AQ_DEL_MAC_FILTER;
5755ec8b7d1SJesse Brandeburg 
5765ec8b7d1SJesse Brandeburg 	spin_unlock_bh(&adapter->mac_vlan_list_lock);
5775ec8b7d1SJesse Brandeburg 
5785ec8b7d1SJesse Brandeburg 	iavf_send_pf_msg(adapter, VIRTCHNL_OP_DEL_ETH_ADDR, (u8 *)veal, len);
5795ec8b7d1SJesse Brandeburg 	kfree(veal);
5805ec8b7d1SJesse Brandeburg }
5815ec8b7d1SJesse Brandeburg 
5825ec8b7d1SJesse Brandeburg /**
5838da80c9dSSylwester Dziedziuch  * iavf_mac_add_ok
5848da80c9dSSylwester Dziedziuch  * @adapter: adapter structure
5858da80c9dSSylwester Dziedziuch  *
5868da80c9dSSylwester Dziedziuch  * Submit list of filters based on PF response.
5878da80c9dSSylwester Dziedziuch  **/
iavf_mac_add_ok(struct iavf_adapter * adapter)5888da80c9dSSylwester Dziedziuch static void iavf_mac_add_ok(struct iavf_adapter *adapter)
5898da80c9dSSylwester Dziedziuch {
5908da80c9dSSylwester Dziedziuch 	struct iavf_mac_filter *f, *ftmp;
5918da80c9dSSylwester Dziedziuch 
5928da80c9dSSylwester Dziedziuch 	spin_lock_bh(&adapter->mac_vlan_list_lock);
5938da80c9dSSylwester Dziedziuch 	list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
5948da80c9dSSylwester Dziedziuch 		f->is_new_mac = false;
59535a2443dSMateusz Palczewski 		if (!f->add && !f->add_handled)
59635a2443dSMateusz Palczewski 			f->add_handled = true;
5978da80c9dSSylwester Dziedziuch 	}
5988da80c9dSSylwester Dziedziuch 	spin_unlock_bh(&adapter->mac_vlan_list_lock);
5998da80c9dSSylwester Dziedziuch }
6008da80c9dSSylwester Dziedziuch 
6018da80c9dSSylwester Dziedziuch /**
6028da80c9dSSylwester Dziedziuch  * iavf_mac_add_reject
6038da80c9dSSylwester Dziedziuch  * @adapter: adapter structure
6048da80c9dSSylwester Dziedziuch  *
6058da80c9dSSylwester Dziedziuch  * Remove filters from list based on PF response.
6068da80c9dSSylwester Dziedziuch  **/
iavf_mac_add_reject(struct iavf_adapter * adapter)6078da80c9dSSylwester Dziedziuch static void iavf_mac_add_reject(struct iavf_adapter *adapter)
6088da80c9dSSylwester Dziedziuch {
6098da80c9dSSylwester Dziedziuch 	struct net_device *netdev = adapter->netdev;
6108da80c9dSSylwester Dziedziuch 	struct iavf_mac_filter *f, *ftmp;
6118da80c9dSSylwester Dziedziuch 
6128da80c9dSSylwester Dziedziuch 	spin_lock_bh(&adapter->mac_vlan_list_lock);
6138da80c9dSSylwester Dziedziuch 	list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
6148da80c9dSSylwester Dziedziuch 		if (f->remove && ether_addr_equal(f->macaddr, netdev->dev_addr))
6158da80c9dSSylwester Dziedziuch 			f->remove = false;
6168da80c9dSSylwester Dziedziuch 
61735a2443dSMateusz Palczewski 		if (!f->add && !f->add_handled)
61835a2443dSMateusz Palczewski 			f->add_handled = true;
61935a2443dSMateusz Palczewski 
6208da80c9dSSylwester Dziedziuch 		if (f->is_new_mac) {
6218da80c9dSSylwester Dziedziuch 			list_del(&f->list);
6228da80c9dSSylwester Dziedziuch 			kfree(f);
6238da80c9dSSylwester Dziedziuch 		}
6248da80c9dSSylwester Dziedziuch 	}
6258da80c9dSSylwester Dziedziuch 	spin_unlock_bh(&adapter->mac_vlan_list_lock);
6268da80c9dSSylwester Dziedziuch }
6278da80c9dSSylwester Dziedziuch 
6288da80c9dSSylwester Dziedziuch /**
629968996c0SPrzemyslaw Patynowski  * iavf_vlan_add_reject
630968996c0SPrzemyslaw Patynowski  * @adapter: adapter structure
631968996c0SPrzemyslaw Patynowski  *
632968996c0SPrzemyslaw Patynowski  * Remove VLAN filters from list based on PF response.
633968996c0SPrzemyslaw Patynowski  **/
iavf_vlan_add_reject(struct iavf_adapter * adapter)634968996c0SPrzemyslaw Patynowski static void iavf_vlan_add_reject(struct iavf_adapter *adapter)
635968996c0SPrzemyslaw Patynowski {
636968996c0SPrzemyslaw Patynowski 	struct iavf_vlan_filter *f, *ftmp;
637968996c0SPrzemyslaw Patynowski 
638968996c0SPrzemyslaw Patynowski 	spin_lock_bh(&adapter->mac_vlan_list_lock);
639968996c0SPrzemyslaw Patynowski 	list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) {
6400c0da0e9SAhmed Zaki 		if (f->state == IAVF_VLAN_IS_NEW) {
641968996c0SPrzemyslaw Patynowski 			list_del(&f->list);
642968996c0SPrzemyslaw Patynowski 			kfree(f);
6439c85b7faSAhmed Zaki 			adapter->num_vlan_filters--;
644968996c0SPrzemyslaw Patynowski 		}
645968996c0SPrzemyslaw Patynowski 	}
646968996c0SPrzemyslaw Patynowski 	spin_unlock_bh(&adapter->mac_vlan_list_lock);
647968996c0SPrzemyslaw Patynowski }
648968996c0SPrzemyslaw Patynowski 
649968996c0SPrzemyslaw Patynowski /**
6505ec8b7d1SJesse Brandeburg  * iavf_add_vlans
6515ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
6525ec8b7d1SJesse Brandeburg  *
6535ec8b7d1SJesse Brandeburg  * Request that the PF add one or more VLAN filters to our VSI.
6545ec8b7d1SJesse Brandeburg  **/
iavf_add_vlans(struct iavf_adapter * adapter)6555ec8b7d1SJesse Brandeburg void iavf_add_vlans(struct iavf_adapter *adapter)
6565ec8b7d1SJesse Brandeburg {
6575ec8b7d1SJesse Brandeburg 	int len, i = 0, count = 0;
6585ec8b7d1SJesse Brandeburg 	struct iavf_vlan_filter *f;
6595ec8b7d1SJesse Brandeburg 	bool more = false;
6605ec8b7d1SJesse Brandeburg 
6615ec8b7d1SJesse Brandeburg 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
6625ec8b7d1SJesse Brandeburg 		/* bail because we already have a command pending */
6635ec8b7d1SJesse Brandeburg 		dev_err(&adapter->pdev->dev, "Cannot add VLANs, command %d pending\n",
6645ec8b7d1SJesse Brandeburg 			adapter->current_op);
6655ec8b7d1SJesse Brandeburg 		return;
6665ec8b7d1SJesse Brandeburg 	}
6675ec8b7d1SJesse Brandeburg 
6685ec8b7d1SJesse Brandeburg 	spin_lock_bh(&adapter->mac_vlan_list_lock);
6695ec8b7d1SJesse Brandeburg 
6705ec8b7d1SJesse Brandeburg 	list_for_each_entry(f, &adapter->vlan_filter_list, list) {
6710c0da0e9SAhmed Zaki 		if (f->state == IAVF_VLAN_ADD)
6725ec8b7d1SJesse Brandeburg 			count++;
6735ec8b7d1SJesse Brandeburg 	}
67448ccc43eSBrett Creeley 	if (!count || !VLAN_FILTERING_ALLOWED(adapter)) {
6755ec8b7d1SJesse Brandeburg 		adapter->aq_required &= ~IAVF_FLAG_AQ_ADD_VLAN_FILTER;
6765ec8b7d1SJesse Brandeburg 		spin_unlock_bh(&adapter->mac_vlan_list_lock);
6775ec8b7d1SJesse Brandeburg 		return;
6785ec8b7d1SJesse Brandeburg 	}
67948ccc43eSBrett Creeley 
68048ccc43eSBrett Creeley 	if (VLAN_ALLOWED(adapter)) {
68148ccc43eSBrett Creeley 		struct virtchnl_vlan_filter_list *vvfl;
68248ccc43eSBrett Creeley 
6835ec8b7d1SJesse Brandeburg 		adapter->current_op = VIRTCHNL_OP_ADD_VLAN;
6845ec8b7d1SJesse Brandeburg 
6855e7f59faSAlexander Lobakin 		len = virtchnl_struct_size(vvfl, vlan_id, count);
6865ec8b7d1SJesse Brandeburg 		if (len > IAVF_MAX_AQ_BUF_SIZE) {
6875ec8b7d1SJesse Brandeburg 			dev_warn(&adapter->pdev->dev, "Too many add VLAN changes in one request\n");
6885e7f59faSAlexander Lobakin 			while (len > IAVF_MAX_AQ_BUF_SIZE)
6895e7f59faSAlexander Lobakin 				len = virtchnl_struct_size(vvfl, vlan_id,
6905e7f59faSAlexander Lobakin 							   --count);
6915ec8b7d1SJesse Brandeburg 			more = true;
6925ec8b7d1SJesse Brandeburg 		}
6935ec8b7d1SJesse Brandeburg 		vvfl = kzalloc(len, GFP_ATOMIC);
6945ec8b7d1SJesse Brandeburg 		if (!vvfl) {
6955ec8b7d1SJesse Brandeburg 			spin_unlock_bh(&adapter->mac_vlan_list_lock);
6965ec8b7d1SJesse Brandeburg 			return;
6975ec8b7d1SJesse Brandeburg 		}
6985ec8b7d1SJesse Brandeburg 
6995ec8b7d1SJesse Brandeburg 		vvfl->vsi_id = adapter->vsi_res->vsi_id;
7005ec8b7d1SJesse Brandeburg 		vvfl->num_elements = count;
7015ec8b7d1SJesse Brandeburg 		list_for_each_entry(f, &adapter->vlan_filter_list, list) {
7020c0da0e9SAhmed Zaki 			if (f->state == IAVF_VLAN_ADD) {
70348ccc43eSBrett Creeley 				vvfl->vlan_id[i] = f->vlan.vid;
7045ec8b7d1SJesse Brandeburg 				i++;
7050c0da0e9SAhmed Zaki 				f->state = IAVF_VLAN_IS_NEW;
7065ec8b7d1SJesse Brandeburg 				if (i == count)
7075ec8b7d1SJesse Brandeburg 					break;
7085ec8b7d1SJesse Brandeburg 			}
7095ec8b7d1SJesse Brandeburg 		}
7105ec8b7d1SJesse Brandeburg 		if (!more)
7115ec8b7d1SJesse Brandeburg 			adapter->aq_required &= ~IAVF_FLAG_AQ_ADD_VLAN_FILTER;
7125ec8b7d1SJesse Brandeburg 
7135ec8b7d1SJesse Brandeburg 		spin_unlock_bh(&adapter->mac_vlan_list_lock);
7145ec8b7d1SJesse Brandeburg 
7155ec8b7d1SJesse Brandeburg 		iavf_send_pf_msg(adapter, VIRTCHNL_OP_ADD_VLAN, (u8 *)vvfl, len);
7165ec8b7d1SJesse Brandeburg 		kfree(vvfl);
71748ccc43eSBrett Creeley 	} else {
718968996c0SPrzemyslaw Patynowski 		u16 max_vlans = adapter->vlan_v2_caps.filtering.max_filters;
719968996c0SPrzemyslaw Patynowski 		u16 current_vlans = iavf_get_num_vlans_added(adapter);
72048ccc43eSBrett Creeley 		struct virtchnl_vlan_filter_list_v2 *vvfl_v2;
72148ccc43eSBrett Creeley 
72248ccc43eSBrett Creeley 		adapter->current_op = VIRTCHNL_OP_ADD_VLAN_V2;
72348ccc43eSBrett Creeley 
724968996c0SPrzemyslaw Patynowski 		if ((count + current_vlans) > max_vlans &&
725968996c0SPrzemyslaw Patynowski 		    current_vlans < max_vlans) {
726968996c0SPrzemyslaw Patynowski 			count = max_vlans - iavf_get_num_vlans_added(adapter);
727968996c0SPrzemyslaw Patynowski 			more = true;
728968996c0SPrzemyslaw Patynowski 		}
729968996c0SPrzemyslaw Patynowski 
730b0654e64SAlexander Lobakin 		len = virtchnl_struct_size(vvfl_v2, filters, count);
73148ccc43eSBrett Creeley 		if (len > IAVF_MAX_AQ_BUF_SIZE) {
73248ccc43eSBrett Creeley 			dev_warn(&adapter->pdev->dev, "Too many add VLAN changes in one request\n");
733b0654e64SAlexander Lobakin 			while (len > IAVF_MAX_AQ_BUF_SIZE)
734b0654e64SAlexander Lobakin 				len = virtchnl_struct_size(vvfl_v2, filters,
735b0654e64SAlexander Lobakin 							   --count);
73648ccc43eSBrett Creeley 			more = true;
73748ccc43eSBrett Creeley 		}
73848ccc43eSBrett Creeley 
73948ccc43eSBrett Creeley 		vvfl_v2 = kzalloc(len, GFP_ATOMIC);
74048ccc43eSBrett Creeley 		if (!vvfl_v2) {
74148ccc43eSBrett Creeley 			spin_unlock_bh(&adapter->mac_vlan_list_lock);
74248ccc43eSBrett Creeley 			return;
74348ccc43eSBrett Creeley 		}
74448ccc43eSBrett Creeley 
74548ccc43eSBrett Creeley 		vvfl_v2->vport_id = adapter->vsi_res->vsi_id;
74648ccc43eSBrett Creeley 		vvfl_v2->num_elements = count;
74748ccc43eSBrett Creeley 		list_for_each_entry(f, &adapter->vlan_filter_list, list) {
7480c0da0e9SAhmed Zaki 			if (f->state == IAVF_VLAN_ADD) {
74948ccc43eSBrett Creeley 				struct virtchnl_vlan_supported_caps *filtering_support =
75048ccc43eSBrett Creeley 					&adapter->vlan_v2_caps.filtering.filtering_support;
75148ccc43eSBrett Creeley 				struct virtchnl_vlan *vlan;
75248ccc43eSBrett Creeley 
753968996c0SPrzemyslaw Patynowski 				if (i == count)
754968996c0SPrzemyslaw Patynowski 					break;
755968996c0SPrzemyslaw Patynowski 
75648ccc43eSBrett Creeley 				/* give priority over outer if it's enabled */
75748ccc43eSBrett Creeley 				if (filtering_support->outer)
75848ccc43eSBrett Creeley 					vlan = &vvfl_v2->filters[i].outer;
75948ccc43eSBrett Creeley 				else
76048ccc43eSBrett Creeley 					vlan = &vvfl_v2->filters[i].inner;
76148ccc43eSBrett Creeley 
76248ccc43eSBrett Creeley 				vlan->tci = f->vlan.vid;
76348ccc43eSBrett Creeley 				vlan->tpid = f->vlan.tpid;
76448ccc43eSBrett Creeley 
76548ccc43eSBrett Creeley 				i++;
7660c0da0e9SAhmed Zaki 				f->state = IAVF_VLAN_IS_NEW;
76748ccc43eSBrett Creeley 			}
76848ccc43eSBrett Creeley 		}
76948ccc43eSBrett Creeley 
77048ccc43eSBrett Creeley 		if (!more)
77148ccc43eSBrett Creeley 			adapter->aq_required &= ~IAVF_FLAG_AQ_ADD_VLAN_FILTER;
77248ccc43eSBrett Creeley 
77348ccc43eSBrett Creeley 		spin_unlock_bh(&adapter->mac_vlan_list_lock);
77448ccc43eSBrett Creeley 
77548ccc43eSBrett Creeley 		iavf_send_pf_msg(adapter, VIRTCHNL_OP_ADD_VLAN_V2,
77648ccc43eSBrett Creeley 				 (u8 *)vvfl_v2, len);
77748ccc43eSBrett Creeley 		kfree(vvfl_v2);
77848ccc43eSBrett Creeley 	}
7795ec8b7d1SJesse Brandeburg }
7805ec8b7d1SJesse Brandeburg 
7815ec8b7d1SJesse Brandeburg /**
7825ec8b7d1SJesse Brandeburg  * iavf_del_vlans
7835ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
7845ec8b7d1SJesse Brandeburg  *
7855ec8b7d1SJesse Brandeburg  * Request that the PF remove one or more VLAN filters from our VSI.
7865ec8b7d1SJesse Brandeburg  **/
iavf_del_vlans(struct iavf_adapter * adapter)7875ec8b7d1SJesse Brandeburg void iavf_del_vlans(struct iavf_adapter *adapter)
7885ec8b7d1SJesse Brandeburg {
7895ec8b7d1SJesse Brandeburg 	struct iavf_vlan_filter *f, *ftmp;
7905ec8b7d1SJesse Brandeburg 	int len, i = 0, count = 0;
7915ec8b7d1SJesse Brandeburg 	bool more = false;
7925ec8b7d1SJesse Brandeburg 
7935ec8b7d1SJesse Brandeburg 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
7945ec8b7d1SJesse Brandeburg 		/* bail because we already have a command pending */
7955ec8b7d1SJesse Brandeburg 		dev_err(&adapter->pdev->dev, "Cannot remove VLANs, command %d pending\n",
7965ec8b7d1SJesse Brandeburg 			adapter->current_op);
7975ec8b7d1SJesse Brandeburg 		return;
7985ec8b7d1SJesse Brandeburg 	}
7995ec8b7d1SJesse Brandeburg 
8005ec8b7d1SJesse Brandeburg 	spin_lock_bh(&adapter->mac_vlan_list_lock);
8015ec8b7d1SJesse Brandeburg 
8025951a2b9SBrett Creeley 	list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) {
8035951a2b9SBrett Creeley 		/* since VLAN capabilities are not allowed, we dont want to send
8045951a2b9SBrett Creeley 		 * a VLAN delete request because it will most likely fail and
8055951a2b9SBrett Creeley 		 * create unnecessary errors/noise, so just free the VLAN
8065951a2b9SBrett Creeley 		 * filters marked for removal to enable bailing out before
8075951a2b9SBrett Creeley 		 * sending a virtchnl message
8085951a2b9SBrett Creeley 		 */
8090c0da0e9SAhmed Zaki 		if (f->state == IAVF_VLAN_REMOVE &&
8100c0da0e9SAhmed Zaki 		    !VLAN_FILTERING_ALLOWED(adapter)) {
8115951a2b9SBrett Creeley 			list_del(&f->list);
8125951a2b9SBrett Creeley 			kfree(f);
8139c85b7faSAhmed Zaki 			adapter->num_vlan_filters--;
8149c85b7faSAhmed Zaki 		} else if (f->state == IAVF_VLAN_DISABLE &&
8159c85b7faSAhmed Zaki 		    !VLAN_FILTERING_ALLOWED(adapter)) {
8169c85b7faSAhmed Zaki 			f->state = IAVF_VLAN_INACTIVE;
8179c85b7faSAhmed Zaki 		} else if (f->state == IAVF_VLAN_REMOVE ||
8189c85b7faSAhmed Zaki 			   f->state == IAVF_VLAN_DISABLE) {
8195ec8b7d1SJesse Brandeburg 			count++;
8205ec8b7d1SJesse Brandeburg 		}
8215951a2b9SBrett Creeley 	}
82248ccc43eSBrett Creeley 	if (!count || !VLAN_FILTERING_ALLOWED(adapter)) {
8235ec8b7d1SJesse Brandeburg 		adapter->aq_required &= ~IAVF_FLAG_AQ_DEL_VLAN_FILTER;
8245ec8b7d1SJesse Brandeburg 		spin_unlock_bh(&adapter->mac_vlan_list_lock);
8255ec8b7d1SJesse Brandeburg 		return;
8265ec8b7d1SJesse Brandeburg 	}
82748ccc43eSBrett Creeley 
82848ccc43eSBrett Creeley 	if (VLAN_ALLOWED(adapter)) {
82948ccc43eSBrett Creeley 		struct virtchnl_vlan_filter_list *vvfl;
83048ccc43eSBrett Creeley 
8315ec8b7d1SJesse Brandeburg 		adapter->current_op = VIRTCHNL_OP_DEL_VLAN;
8325ec8b7d1SJesse Brandeburg 
8335e7f59faSAlexander Lobakin 		len = virtchnl_struct_size(vvfl, vlan_id, count);
8345ec8b7d1SJesse Brandeburg 		if (len > IAVF_MAX_AQ_BUF_SIZE) {
8355ec8b7d1SJesse Brandeburg 			dev_warn(&adapter->pdev->dev, "Too many delete VLAN changes in one request\n");
8365e7f59faSAlexander Lobakin 			while (len > IAVF_MAX_AQ_BUF_SIZE)
8375e7f59faSAlexander Lobakin 				len = virtchnl_struct_size(vvfl, vlan_id,
8385e7f59faSAlexander Lobakin 							   --count);
8395ec8b7d1SJesse Brandeburg 			more = true;
8405ec8b7d1SJesse Brandeburg 		}
8415ec8b7d1SJesse Brandeburg 		vvfl = kzalloc(len, GFP_ATOMIC);
8425ec8b7d1SJesse Brandeburg 		if (!vvfl) {
8435ec8b7d1SJesse Brandeburg 			spin_unlock_bh(&adapter->mac_vlan_list_lock);
8445ec8b7d1SJesse Brandeburg 			return;
8455ec8b7d1SJesse Brandeburg 		}
8465ec8b7d1SJesse Brandeburg 
8475ec8b7d1SJesse Brandeburg 		vvfl->vsi_id = adapter->vsi_res->vsi_id;
8485ec8b7d1SJesse Brandeburg 		vvfl->num_elements = count;
8495ec8b7d1SJesse Brandeburg 		list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) {
8509c85b7faSAhmed Zaki 			if (f->state == IAVF_VLAN_DISABLE) {
85148ccc43eSBrett Creeley 				vvfl->vlan_id[i] = f->vlan.vid;
8529c85b7faSAhmed Zaki 				f->state = IAVF_VLAN_INACTIVE;
8535ec8b7d1SJesse Brandeburg 				i++;
8549c85b7faSAhmed Zaki 				if (i == count)
8559c85b7faSAhmed Zaki 					break;
8569c85b7faSAhmed Zaki 			} else if (f->state == IAVF_VLAN_REMOVE) {
8579c85b7faSAhmed Zaki 				vvfl->vlan_id[i] = f->vlan.vid;
8585ec8b7d1SJesse Brandeburg 				list_del(&f->list);
8595ec8b7d1SJesse Brandeburg 				kfree(f);
8609c85b7faSAhmed Zaki 				adapter->num_vlan_filters--;
8619c85b7faSAhmed Zaki 				i++;
8625ec8b7d1SJesse Brandeburg 				if (i == count)
8635ec8b7d1SJesse Brandeburg 					break;
8645ec8b7d1SJesse Brandeburg 			}
8655ec8b7d1SJesse Brandeburg 		}
86648ccc43eSBrett Creeley 
8675ec8b7d1SJesse Brandeburg 		if (!more)
8685ec8b7d1SJesse Brandeburg 			adapter->aq_required &= ~IAVF_FLAG_AQ_DEL_VLAN_FILTER;
8695ec8b7d1SJesse Brandeburg 
8705ec8b7d1SJesse Brandeburg 		spin_unlock_bh(&adapter->mac_vlan_list_lock);
8715ec8b7d1SJesse Brandeburg 
8725ec8b7d1SJesse Brandeburg 		iavf_send_pf_msg(adapter, VIRTCHNL_OP_DEL_VLAN, (u8 *)vvfl, len);
8735ec8b7d1SJesse Brandeburg 		kfree(vvfl);
87448ccc43eSBrett Creeley 	} else {
87548ccc43eSBrett Creeley 		struct virtchnl_vlan_filter_list_v2 *vvfl_v2;
87648ccc43eSBrett Creeley 
87748ccc43eSBrett Creeley 		adapter->current_op = VIRTCHNL_OP_DEL_VLAN_V2;
87848ccc43eSBrett Creeley 
879b0654e64SAlexander Lobakin 		len = virtchnl_struct_size(vvfl_v2, filters, count);
88048ccc43eSBrett Creeley 		if (len > IAVF_MAX_AQ_BUF_SIZE) {
88148ccc43eSBrett Creeley 			dev_warn(&adapter->pdev->dev, "Too many add VLAN changes in one request\n");
882b0654e64SAlexander Lobakin 			while (len > IAVF_MAX_AQ_BUF_SIZE)
883b0654e64SAlexander Lobakin 				len = virtchnl_struct_size(vvfl_v2, filters,
884b0654e64SAlexander Lobakin 							   --count);
88548ccc43eSBrett Creeley 			more = true;
88648ccc43eSBrett Creeley 		}
88748ccc43eSBrett Creeley 
88848ccc43eSBrett Creeley 		vvfl_v2 = kzalloc(len, GFP_ATOMIC);
88948ccc43eSBrett Creeley 		if (!vvfl_v2) {
89048ccc43eSBrett Creeley 			spin_unlock_bh(&adapter->mac_vlan_list_lock);
89148ccc43eSBrett Creeley 			return;
89248ccc43eSBrett Creeley 		}
89348ccc43eSBrett Creeley 
89448ccc43eSBrett Creeley 		vvfl_v2->vport_id = adapter->vsi_res->vsi_id;
89548ccc43eSBrett Creeley 		vvfl_v2->num_elements = count;
89648ccc43eSBrett Creeley 		list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) {
8979c85b7faSAhmed Zaki 			if (f->state == IAVF_VLAN_DISABLE ||
8989c85b7faSAhmed Zaki 			    f->state == IAVF_VLAN_REMOVE) {
89948ccc43eSBrett Creeley 				struct virtchnl_vlan_supported_caps *filtering_support =
90048ccc43eSBrett Creeley 					&adapter->vlan_v2_caps.filtering.filtering_support;
90148ccc43eSBrett Creeley 				struct virtchnl_vlan *vlan;
90248ccc43eSBrett Creeley 
90348ccc43eSBrett Creeley 				/* give priority over outer if it's enabled */
90448ccc43eSBrett Creeley 				if (filtering_support->outer)
90548ccc43eSBrett Creeley 					vlan = &vvfl_v2->filters[i].outer;
90648ccc43eSBrett Creeley 				else
90748ccc43eSBrett Creeley 					vlan = &vvfl_v2->filters[i].inner;
90848ccc43eSBrett Creeley 
90948ccc43eSBrett Creeley 				vlan->tci = f->vlan.vid;
91048ccc43eSBrett Creeley 				vlan->tpid = f->vlan.tpid;
91148ccc43eSBrett Creeley 
9129c85b7faSAhmed Zaki 				if (f->state == IAVF_VLAN_DISABLE) {
9139c85b7faSAhmed Zaki 					f->state = IAVF_VLAN_INACTIVE;
9149c85b7faSAhmed Zaki 				} else {
91548ccc43eSBrett Creeley 					list_del(&f->list);
91648ccc43eSBrett Creeley 					kfree(f);
9179c85b7faSAhmed Zaki 					adapter->num_vlan_filters--;
9189c85b7faSAhmed Zaki 				}
91948ccc43eSBrett Creeley 				i++;
92048ccc43eSBrett Creeley 				if (i == count)
92148ccc43eSBrett Creeley 					break;
92248ccc43eSBrett Creeley 			}
92348ccc43eSBrett Creeley 		}
92448ccc43eSBrett Creeley 
92548ccc43eSBrett Creeley 		if (!more)
92648ccc43eSBrett Creeley 			adapter->aq_required &= ~IAVF_FLAG_AQ_DEL_VLAN_FILTER;
92748ccc43eSBrett Creeley 
92848ccc43eSBrett Creeley 		spin_unlock_bh(&adapter->mac_vlan_list_lock);
92948ccc43eSBrett Creeley 
93048ccc43eSBrett Creeley 		iavf_send_pf_msg(adapter, VIRTCHNL_OP_DEL_VLAN_V2,
93148ccc43eSBrett Creeley 				 (u8 *)vvfl_v2, len);
93248ccc43eSBrett Creeley 		kfree(vvfl_v2);
93348ccc43eSBrett Creeley 	}
9345ec8b7d1SJesse Brandeburg }
9355ec8b7d1SJesse Brandeburg 
9365ec8b7d1SJesse Brandeburg /**
9375ec8b7d1SJesse Brandeburg  * iavf_set_promiscuous
9385ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
9395ec8b7d1SJesse Brandeburg  *
9405ec8b7d1SJesse Brandeburg  * Request that the PF enable promiscuous mode for our VSI.
9415ec8b7d1SJesse Brandeburg  **/
iavf_set_promiscuous(struct iavf_adapter * adapter)9427e85cf09SBrett Creeley void iavf_set_promiscuous(struct iavf_adapter *adapter)
9435ec8b7d1SJesse Brandeburg {
9447e85cf09SBrett Creeley 	struct net_device *netdev = adapter->netdev;
9455ec8b7d1SJesse Brandeburg 	struct virtchnl_promisc_info vpi;
9467e85cf09SBrett Creeley 	unsigned int flags;
9475ec8b7d1SJesse Brandeburg 
9485ec8b7d1SJesse Brandeburg 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
9495ec8b7d1SJesse Brandeburg 		/* bail because we already have a command pending */
9505ec8b7d1SJesse Brandeburg 		dev_err(&adapter->pdev->dev, "Cannot set promiscuous mode, command %d pending\n",
9515ec8b7d1SJesse Brandeburg 			adapter->current_op);
9525ec8b7d1SJesse Brandeburg 		return;
9535ec8b7d1SJesse Brandeburg 	}
9545ec8b7d1SJesse Brandeburg 
9557e85cf09SBrett Creeley 	/* prevent changes to promiscuous flags */
9567e85cf09SBrett Creeley 	spin_lock_bh(&adapter->current_netdev_promisc_flags_lock);
9577e85cf09SBrett Creeley 
9587e85cf09SBrett Creeley 	/* sanity check to prevent duplicate AQ calls */
9597e85cf09SBrett Creeley 	if (!iavf_promiscuous_mode_changed(adapter)) {
9607e85cf09SBrett Creeley 		adapter->aq_required &= ~IAVF_FLAG_AQ_CONFIGURE_PROMISC_MODE;
9617e85cf09SBrett Creeley 		dev_dbg(&adapter->pdev->dev, "No change in promiscuous mode\n");
9627e85cf09SBrett Creeley 		/* allow changes to promiscuous flags */
9637e85cf09SBrett Creeley 		spin_unlock_bh(&adapter->current_netdev_promisc_flags_lock);
9647e85cf09SBrett Creeley 		return;
9657e85cf09SBrett Creeley 	}
9667e85cf09SBrett Creeley 
9677e85cf09SBrett Creeley 	/* there are 2 bits, but only 3 states */
9687e85cf09SBrett Creeley 	if (!(netdev->flags & IFF_PROMISC) &&
9697e85cf09SBrett Creeley 	    netdev->flags & IFF_ALLMULTI) {
9707e85cf09SBrett Creeley 		/* State 1  - only multicast promiscuous mode enabled
9717e85cf09SBrett Creeley 		 * - !IFF_PROMISC && IFF_ALLMULTI
9727e85cf09SBrett Creeley 		 */
9737e85cf09SBrett Creeley 		flags = FLAG_VF_MULTICAST_PROMISC;
9747e85cf09SBrett Creeley 		adapter->current_netdev_promisc_flags |= IFF_ALLMULTI;
9757e85cf09SBrett Creeley 		adapter->current_netdev_promisc_flags &= ~IFF_PROMISC;
9767e85cf09SBrett Creeley 		dev_info(&adapter->pdev->dev, "Entering multicast promiscuous mode\n");
9777e85cf09SBrett Creeley 	} else if (!(netdev->flags & IFF_PROMISC) &&
9787e85cf09SBrett Creeley 		   !(netdev->flags & IFF_ALLMULTI)) {
9797e85cf09SBrett Creeley 		/* State 2 - unicast/multicast promiscuous mode disabled
9807e85cf09SBrett Creeley 		 * - !IFF_PROMISC && !IFF_ALLMULTI
9817e85cf09SBrett Creeley 		 */
9827e85cf09SBrett Creeley 		flags = 0;
9837e85cf09SBrett Creeley 		adapter->current_netdev_promisc_flags &=
9847e85cf09SBrett Creeley 			~(IFF_PROMISC | IFF_ALLMULTI);
9857e85cf09SBrett Creeley 		dev_info(&adapter->pdev->dev, "Leaving promiscuous mode\n");
9867e85cf09SBrett Creeley 	} else {
9877e85cf09SBrett Creeley 		/* State 3 - unicast/multicast promiscuous mode enabled
9887e85cf09SBrett Creeley 		 * - IFF_PROMISC && IFF_ALLMULTI
9897e85cf09SBrett Creeley 		 * - IFF_PROMISC && !IFF_ALLMULTI
9907e85cf09SBrett Creeley 		 */
9917e85cf09SBrett Creeley 		flags = FLAG_VF_UNICAST_PROMISC | FLAG_VF_MULTICAST_PROMISC;
9927e85cf09SBrett Creeley 		adapter->current_netdev_promisc_flags |= IFF_PROMISC;
9937e85cf09SBrett Creeley 		if (netdev->flags & IFF_ALLMULTI)
9947e85cf09SBrett Creeley 			adapter->current_netdev_promisc_flags |= IFF_ALLMULTI;
9957e85cf09SBrett Creeley 		else
9967e85cf09SBrett Creeley 			adapter->current_netdev_promisc_flags &= ~IFF_ALLMULTI;
9977e85cf09SBrett Creeley 
9985ec8b7d1SJesse Brandeburg 		dev_info(&adapter->pdev->dev, "Entering promiscuous mode\n");
9995ec8b7d1SJesse Brandeburg 	}
10005ec8b7d1SJesse Brandeburg 
10017e85cf09SBrett Creeley 	adapter->aq_required &= ~IAVF_FLAG_AQ_CONFIGURE_PROMISC_MODE;
10025ec8b7d1SJesse Brandeburg 
10037e85cf09SBrett Creeley 	/* allow changes to promiscuous flags */
10047e85cf09SBrett Creeley 	spin_unlock_bh(&adapter->current_netdev_promisc_flags_lock);
1005f1db020bSGrzegorz Szczurek 
10065ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE;
10075ec8b7d1SJesse Brandeburg 	vpi.vsi_id = adapter->vsi_res->vsi_id;
10085ec8b7d1SJesse Brandeburg 	vpi.flags = flags;
10095ec8b7d1SJesse Brandeburg 	iavf_send_pf_msg(adapter, VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
10105ec8b7d1SJesse Brandeburg 			 (u8 *)&vpi, sizeof(vpi));
10115ec8b7d1SJesse Brandeburg }
10125ec8b7d1SJesse Brandeburg 
10135ec8b7d1SJesse Brandeburg /**
10145ec8b7d1SJesse Brandeburg  * iavf_request_stats
10155ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
10165ec8b7d1SJesse Brandeburg  *
10175ec8b7d1SJesse Brandeburg  * Request VSI statistics from PF.
10185ec8b7d1SJesse Brandeburg  **/
iavf_request_stats(struct iavf_adapter * adapter)10195ec8b7d1SJesse Brandeburg void iavf_request_stats(struct iavf_adapter *adapter)
10205ec8b7d1SJesse Brandeburg {
10215ec8b7d1SJesse Brandeburg 	struct virtchnl_queue_select vqs;
10225ec8b7d1SJesse Brandeburg 
10235ec8b7d1SJesse Brandeburg 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
10245ec8b7d1SJesse Brandeburg 		/* no error message, this isn't crucial */
10255ec8b7d1SJesse Brandeburg 		return;
10265ec8b7d1SJesse Brandeburg 	}
10273b5bdd18SJedrzej Jagielski 
10283b5bdd18SJedrzej Jagielski 	adapter->aq_required &= ~IAVF_FLAG_AQ_REQUEST_STATS;
10295ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_GET_STATS;
10305ec8b7d1SJesse Brandeburg 	vqs.vsi_id = adapter->vsi_res->vsi_id;
10315ec8b7d1SJesse Brandeburg 	/* queue maps are ignored for this message - only the vsi is used */
10325ec8b7d1SJesse Brandeburg 	if (iavf_send_pf_msg(adapter, VIRTCHNL_OP_GET_STATS, (u8 *)&vqs,
10335ec8b7d1SJesse Brandeburg 			     sizeof(vqs)))
10345ec8b7d1SJesse Brandeburg 		/* if the request failed, don't lock out others */
10355ec8b7d1SJesse Brandeburg 		adapter->current_op = VIRTCHNL_OP_UNKNOWN;
10365ec8b7d1SJesse Brandeburg }
10375ec8b7d1SJesse Brandeburg 
10385ec8b7d1SJesse Brandeburg /**
10395ec8b7d1SJesse Brandeburg  * iavf_get_hena
10405ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
10415ec8b7d1SJesse Brandeburg  *
10425ec8b7d1SJesse Brandeburg  * Request hash enable capabilities from PF
10435ec8b7d1SJesse Brandeburg  **/
iavf_get_hena(struct iavf_adapter * adapter)10445ec8b7d1SJesse Brandeburg void iavf_get_hena(struct iavf_adapter *adapter)
10455ec8b7d1SJesse Brandeburg {
10465ec8b7d1SJesse Brandeburg 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
10475ec8b7d1SJesse Brandeburg 		/* bail because we already have a command pending */
10485ec8b7d1SJesse Brandeburg 		dev_err(&adapter->pdev->dev, "Cannot get RSS hash capabilities, command %d pending\n",
10495ec8b7d1SJesse Brandeburg 			adapter->current_op);
10505ec8b7d1SJesse Brandeburg 		return;
10515ec8b7d1SJesse Brandeburg 	}
10525ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_GET_RSS_HENA_CAPS;
10535ec8b7d1SJesse Brandeburg 	adapter->aq_required &= ~IAVF_FLAG_AQ_GET_HENA;
10545ec8b7d1SJesse Brandeburg 	iavf_send_pf_msg(adapter, VIRTCHNL_OP_GET_RSS_HENA_CAPS, NULL, 0);
10555ec8b7d1SJesse Brandeburg }
10565ec8b7d1SJesse Brandeburg 
10575ec8b7d1SJesse Brandeburg /**
10585ec8b7d1SJesse Brandeburg  * iavf_set_hena
10595ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
10605ec8b7d1SJesse Brandeburg  *
10615ec8b7d1SJesse Brandeburg  * Request the PF to set our RSS hash capabilities
10625ec8b7d1SJesse Brandeburg  **/
iavf_set_hena(struct iavf_adapter * adapter)10635ec8b7d1SJesse Brandeburg void iavf_set_hena(struct iavf_adapter *adapter)
10645ec8b7d1SJesse Brandeburg {
10655ec8b7d1SJesse Brandeburg 	struct virtchnl_rss_hena vrh;
10665ec8b7d1SJesse Brandeburg 
10675ec8b7d1SJesse Brandeburg 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
10685ec8b7d1SJesse Brandeburg 		/* bail because we already have a command pending */
10695ec8b7d1SJesse Brandeburg 		dev_err(&adapter->pdev->dev, "Cannot set RSS hash enable, command %d pending\n",
10705ec8b7d1SJesse Brandeburg 			adapter->current_op);
10715ec8b7d1SJesse Brandeburg 		return;
10725ec8b7d1SJesse Brandeburg 	}
10735ec8b7d1SJesse Brandeburg 	vrh.hena = adapter->hena;
10745ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_SET_RSS_HENA;
10755ec8b7d1SJesse Brandeburg 	adapter->aq_required &= ~IAVF_FLAG_AQ_SET_HENA;
10765ec8b7d1SJesse Brandeburg 	iavf_send_pf_msg(adapter, VIRTCHNL_OP_SET_RSS_HENA, (u8 *)&vrh,
10775ec8b7d1SJesse Brandeburg 			 sizeof(vrh));
10785ec8b7d1SJesse Brandeburg }
10795ec8b7d1SJesse Brandeburg 
10805ec8b7d1SJesse Brandeburg /**
10815ec8b7d1SJesse Brandeburg  * iavf_set_rss_key
10825ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
10835ec8b7d1SJesse Brandeburg  *
10845ec8b7d1SJesse Brandeburg  * Request the PF to set our RSS hash key
10855ec8b7d1SJesse Brandeburg  **/
iavf_set_rss_key(struct iavf_adapter * adapter)10865ec8b7d1SJesse Brandeburg void iavf_set_rss_key(struct iavf_adapter *adapter)
10875ec8b7d1SJesse Brandeburg {
10885ec8b7d1SJesse Brandeburg 	struct virtchnl_rss_key *vrk;
10895ec8b7d1SJesse Brandeburg 	int len;
10905ec8b7d1SJesse Brandeburg 
10915ec8b7d1SJesse Brandeburg 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
10925ec8b7d1SJesse Brandeburg 		/* bail because we already have a command pending */
10935ec8b7d1SJesse Brandeburg 		dev_err(&adapter->pdev->dev, "Cannot set RSS key, command %d pending\n",
10945ec8b7d1SJesse Brandeburg 			adapter->current_op);
10955ec8b7d1SJesse Brandeburg 		return;
10965ec8b7d1SJesse Brandeburg 	}
1097dd2e84bbSAlexander Lobakin 	len = virtchnl_struct_size(vrk, key, adapter->rss_key_size);
10985ec8b7d1SJesse Brandeburg 	vrk = kzalloc(len, GFP_KERNEL);
10995ec8b7d1SJesse Brandeburg 	if (!vrk)
11005ec8b7d1SJesse Brandeburg 		return;
11015ec8b7d1SJesse Brandeburg 	vrk->vsi_id = adapter->vsi.id;
11025ec8b7d1SJesse Brandeburg 	vrk->key_len = adapter->rss_key_size;
11035ec8b7d1SJesse Brandeburg 	memcpy(vrk->key, adapter->rss_key, adapter->rss_key_size);
11045ec8b7d1SJesse Brandeburg 
11055ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_CONFIG_RSS_KEY;
11065ec8b7d1SJesse Brandeburg 	adapter->aq_required &= ~IAVF_FLAG_AQ_SET_RSS_KEY;
11075ec8b7d1SJesse Brandeburg 	iavf_send_pf_msg(adapter, VIRTCHNL_OP_CONFIG_RSS_KEY, (u8 *)vrk, len);
11085ec8b7d1SJesse Brandeburg 	kfree(vrk);
11095ec8b7d1SJesse Brandeburg }
11105ec8b7d1SJesse Brandeburg 
11115ec8b7d1SJesse Brandeburg /**
11125ec8b7d1SJesse Brandeburg  * iavf_set_rss_lut
11135ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
11145ec8b7d1SJesse Brandeburg  *
11155ec8b7d1SJesse Brandeburg  * Request the PF to set our RSS lookup table
11165ec8b7d1SJesse Brandeburg  **/
iavf_set_rss_lut(struct iavf_adapter * adapter)11175ec8b7d1SJesse Brandeburg void iavf_set_rss_lut(struct iavf_adapter *adapter)
11185ec8b7d1SJesse Brandeburg {
11195ec8b7d1SJesse Brandeburg 	struct virtchnl_rss_lut *vrl;
11205ec8b7d1SJesse Brandeburg 	int len;
11215ec8b7d1SJesse Brandeburg 
11225ec8b7d1SJesse Brandeburg 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
11235ec8b7d1SJesse Brandeburg 		/* bail because we already have a command pending */
11245ec8b7d1SJesse Brandeburg 		dev_err(&adapter->pdev->dev, "Cannot set RSS LUT, command %d pending\n",
11255ec8b7d1SJesse Brandeburg 			adapter->current_op);
11265ec8b7d1SJesse Brandeburg 		return;
11275ec8b7d1SJesse Brandeburg 	}
1128dd2e84bbSAlexander Lobakin 	len = virtchnl_struct_size(vrl, lut, adapter->rss_lut_size);
11295ec8b7d1SJesse Brandeburg 	vrl = kzalloc(len, GFP_KERNEL);
11305ec8b7d1SJesse Brandeburg 	if (!vrl)
11315ec8b7d1SJesse Brandeburg 		return;
11325ec8b7d1SJesse Brandeburg 	vrl->vsi_id = adapter->vsi.id;
11335ec8b7d1SJesse Brandeburg 	vrl->lut_entries = adapter->rss_lut_size;
11345ec8b7d1SJesse Brandeburg 	memcpy(vrl->lut, adapter->rss_lut, adapter->rss_lut_size);
11355ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_CONFIG_RSS_LUT;
11365ec8b7d1SJesse Brandeburg 	adapter->aq_required &= ~IAVF_FLAG_AQ_SET_RSS_LUT;
11375ec8b7d1SJesse Brandeburg 	iavf_send_pf_msg(adapter, VIRTCHNL_OP_CONFIG_RSS_LUT, (u8 *)vrl, len);
11385ec8b7d1SJesse Brandeburg 	kfree(vrl);
11395ec8b7d1SJesse Brandeburg }
11405ec8b7d1SJesse Brandeburg 
11415ec8b7d1SJesse Brandeburg /**
11425ec8b7d1SJesse Brandeburg  * iavf_enable_vlan_stripping
11435ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
11445ec8b7d1SJesse Brandeburg  *
11455ec8b7d1SJesse Brandeburg  * Request VLAN header stripping to be enabled
11465ec8b7d1SJesse Brandeburg  **/
iavf_enable_vlan_stripping(struct iavf_adapter * adapter)11475ec8b7d1SJesse Brandeburg void iavf_enable_vlan_stripping(struct iavf_adapter *adapter)
11485ec8b7d1SJesse Brandeburg {
11495ec8b7d1SJesse Brandeburg 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
11505ec8b7d1SJesse Brandeburg 		/* bail because we already have a command pending */
11515ec8b7d1SJesse Brandeburg 		dev_err(&adapter->pdev->dev, "Cannot enable stripping, command %d pending\n",
11525ec8b7d1SJesse Brandeburg 			adapter->current_op);
11535ec8b7d1SJesse Brandeburg 		return;
11545ec8b7d1SJesse Brandeburg 	}
11555ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_ENABLE_VLAN_STRIPPING;
11565ec8b7d1SJesse Brandeburg 	adapter->aq_required &= ~IAVF_FLAG_AQ_ENABLE_VLAN_STRIPPING;
11575ec8b7d1SJesse Brandeburg 	iavf_send_pf_msg(adapter, VIRTCHNL_OP_ENABLE_VLAN_STRIPPING, NULL, 0);
11585ec8b7d1SJesse Brandeburg }
11595ec8b7d1SJesse Brandeburg 
11605ec8b7d1SJesse Brandeburg /**
11615ec8b7d1SJesse Brandeburg  * iavf_disable_vlan_stripping
11625ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
11635ec8b7d1SJesse Brandeburg  *
11645ec8b7d1SJesse Brandeburg  * Request VLAN header stripping to be disabled
11655ec8b7d1SJesse Brandeburg  **/
iavf_disable_vlan_stripping(struct iavf_adapter * adapter)11665ec8b7d1SJesse Brandeburg void iavf_disable_vlan_stripping(struct iavf_adapter *adapter)
11675ec8b7d1SJesse Brandeburg {
11685ec8b7d1SJesse Brandeburg 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
11695ec8b7d1SJesse Brandeburg 		/* bail because we already have a command pending */
11705ec8b7d1SJesse Brandeburg 		dev_err(&adapter->pdev->dev, "Cannot disable stripping, command %d pending\n",
11715ec8b7d1SJesse Brandeburg 			adapter->current_op);
11725ec8b7d1SJesse Brandeburg 		return;
11735ec8b7d1SJesse Brandeburg 	}
11745ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_DISABLE_VLAN_STRIPPING;
11755ec8b7d1SJesse Brandeburg 	adapter->aq_required &= ~IAVF_FLAG_AQ_DISABLE_VLAN_STRIPPING;
11765ec8b7d1SJesse Brandeburg 	iavf_send_pf_msg(adapter, VIRTCHNL_OP_DISABLE_VLAN_STRIPPING, NULL, 0);
11775ec8b7d1SJesse Brandeburg }
11785ec8b7d1SJesse Brandeburg 
11798afadd1cSBrett Creeley /**
11808afadd1cSBrett Creeley  * iavf_tpid_to_vc_ethertype - transform from VLAN TPID to virtchnl ethertype
11818afadd1cSBrett Creeley  * @tpid: VLAN TPID (i.e. 0x8100, 0x88a8, etc.)
11828afadd1cSBrett Creeley  */
iavf_tpid_to_vc_ethertype(u16 tpid)11838afadd1cSBrett Creeley static u32 iavf_tpid_to_vc_ethertype(u16 tpid)
11848afadd1cSBrett Creeley {
11858afadd1cSBrett Creeley 	switch (tpid) {
11868afadd1cSBrett Creeley 	case ETH_P_8021Q:
11878afadd1cSBrett Creeley 		return VIRTCHNL_VLAN_ETHERTYPE_8100;
11888afadd1cSBrett Creeley 	case ETH_P_8021AD:
11898afadd1cSBrett Creeley 		return VIRTCHNL_VLAN_ETHERTYPE_88A8;
11908afadd1cSBrett Creeley 	}
11918afadd1cSBrett Creeley 
11928afadd1cSBrett Creeley 	return 0;
11938afadd1cSBrett Creeley }
11948afadd1cSBrett Creeley 
11958afadd1cSBrett Creeley /**
11968afadd1cSBrett Creeley  * iavf_set_vc_offload_ethertype - set virtchnl ethertype for offload message
11978afadd1cSBrett Creeley  * @adapter: adapter structure
11988afadd1cSBrett Creeley  * @msg: message structure used for updating offloads over virtchnl to update
11998afadd1cSBrett Creeley  * @tpid: VLAN TPID (i.e. 0x8100, 0x88a8, etc.)
12008afadd1cSBrett Creeley  * @offload_op: opcode used to determine which support structure to check
12018afadd1cSBrett Creeley  */
12028afadd1cSBrett Creeley static int
iavf_set_vc_offload_ethertype(struct iavf_adapter * adapter,struct virtchnl_vlan_setting * msg,u16 tpid,enum virtchnl_ops offload_op)12038afadd1cSBrett Creeley iavf_set_vc_offload_ethertype(struct iavf_adapter *adapter,
12048afadd1cSBrett Creeley 			      struct virtchnl_vlan_setting *msg, u16 tpid,
12058afadd1cSBrett Creeley 			      enum virtchnl_ops offload_op)
12068afadd1cSBrett Creeley {
12078afadd1cSBrett Creeley 	struct virtchnl_vlan_supported_caps *offload_support;
12088afadd1cSBrett Creeley 	u16 vc_ethertype = iavf_tpid_to_vc_ethertype(tpid);
12098afadd1cSBrett Creeley 
12108afadd1cSBrett Creeley 	/* reference the correct offload support structure */
12118afadd1cSBrett Creeley 	switch (offload_op) {
12128afadd1cSBrett Creeley 	case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2:
12138afadd1cSBrett Creeley 	case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2:
12148afadd1cSBrett Creeley 		offload_support =
12158afadd1cSBrett Creeley 			&adapter->vlan_v2_caps.offloads.stripping_support;
12168afadd1cSBrett Creeley 		break;
12178afadd1cSBrett Creeley 	case VIRTCHNL_OP_ENABLE_VLAN_INSERTION_V2:
12188afadd1cSBrett Creeley 	case VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2:
12198afadd1cSBrett Creeley 		offload_support =
12208afadd1cSBrett Creeley 			&adapter->vlan_v2_caps.offloads.insertion_support;
12218afadd1cSBrett Creeley 		break;
12228afadd1cSBrett Creeley 	default:
12238afadd1cSBrett Creeley 		dev_err(&adapter->pdev->dev, "Invalid opcode %d for setting virtchnl ethertype to enable/disable VLAN offloads\n",
12248afadd1cSBrett Creeley 			offload_op);
12258afadd1cSBrett Creeley 		return -EINVAL;
12268afadd1cSBrett Creeley 	}
12278afadd1cSBrett Creeley 
12288afadd1cSBrett Creeley 	/* make sure ethertype is supported */
12298afadd1cSBrett Creeley 	if (offload_support->outer & vc_ethertype &&
12308afadd1cSBrett Creeley 	    offload_support->outer & VIRTCHNL_VLAN_TOGGLE) {
12318afadd1cSBrett Creeley 		msg->outer_ethertype_setting = vc_ethertype;
12328afadd1cSBrett Creeley 	} else if (offload_support->inner & vc_ethertype &&
12338afadd1cSBrett Creeley 		   offload_support->inner & VIRTCHNL_VLAN_TOGGLE) {
12348afadd1cSBrett Creeley 		msg->inner_ethertype_setting = vc_ethertype;
12358afadd1cSBrett Creeley 	} else {
12368afadd1cSBrett Creeley 		dev_dbg(&adapter->pdev->dev, "opcode %d unsupported for VLAN TPID 0x%04x\n",
12378afadd1cSBrett Creeley 			offload_op, tpid);
12388afadd1cSBrett Creeley 		return -EINVAL;
12398afadd1cSBrett Creeley 	}
12408afadd1cSBrett Creeley 
12418afadd1cSBrett Creeley 	return 0;
12428afadd1cSBrett Creeley }
12438afadd1cSBrett Creeley 
12448afadd1cSBrett Creeley /**
12458afadd1cSBrett Creeley  * iavf_clear_offload_v2_aq_required - clear AQ required bit for offload request
12468afadd1cSBrett Creeley  * @adapter: adapter structure
12478afadd1cSBrett Creeley  * @tpid: VLAN TPID
12488afadd1cSBrett Creeley  * @offload_op: opcode used to determine which AQ required bit to clear
12498afadd1cSBrett Creeley  */
12508afadd1cSBrett Creeley static void
iavf_clear_offload_v2_aq_required(struct iavf_adapter * adapter,u16 tpid,enum virtchnl_ops offload_op)12518afadd1cSBrett Creeley iavf_clear_offload_v2_aq_required(struct iavf_adapter *adapter, u16 tpid,
12528afadd1cSBrett Creeley 				  enum virtchnl_ops offload_op)
12538afadd1cSBrett Creeley {
12548afadd1cSBrett Creeley 	switch (offload_op) {
12558afadd1cSBrett Creeley 	case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2:
12568afadd1cSBrett Creeley 		if (tpid == ETH_P_8021Q)
12578afadd1cSBrett Creeley 			adapter->aq_required &=
12588afadd1cSBrett Creeley 				~IAVF_FLAG_AQ_ENABLE_CTAG_VLAN_STRIPPING;
12598afadd1cSBrett Creeley 		else if (tpid == ETH_P_8021AD)
12608afadd1cSBrett Creeley 			adapter->aq_required &=
12618afadd1cSBrett Creeley 				~IAVF_FLAG_AQ_ENABLE_STAG_VLAN_STRIPPING;
12628afadd1cSBrett Creeley 		break;
12638afadd1cSBrett Creeley 	case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2:
12648afadd1cSBrett Creeley 		if (tpid == ETH_P_8021Q)
12658afadd1cSBrett Creeley 			adapter->aq_required &=
12668afadd1cSBrett Creeley 				~IAVF_FLAG_AQ_DISABLE_CTAG_VLAN_STRIPPING;
12678afadd1cSBrett Creeley 		else if (tpid == ETH_P_8021AD)
12688afadd1cSBrett Creeley 			adapter->aq_required &=
12698afadd1cSBrett Creeley 				~IAVF_FLAG_AQ_DISABLE_STAG_VLAN_STRIPPING;
12708afadd1cSBrett Creeley 		break;
12718afadd1cSBrett Creeley 	case VIRTCHNL_OP_ENABLE_VLAN_INSERTION_V2:
12728afadd1cSBrett Creeley 		if (tpid == ETH_P_8021Q)
12738afadd1cSBrett Creeley 			adapter->aq_required &=
12748afadd1cSBrett Creeley 				~IAVF_FLAG_AQ_ENABLE_CTAG_VLAN_INSERTION;
12758afadd1cSBrett Creeley 		else if (tpid == ETH_P_8021AD)
12768afadd1cSBrett Creeley 			adapter->aq_required &=
12778afadd1cSBrett Creeley 				~IAVF_FLAG_AQ_ENABLE_STAG_VLAN_INSERTION;
12788afadd1cSBrett Creeley 		break;
12798afadd1cSBrett Creeley 	case VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2:
12808afadd1cSBrett Creeley 		if (tpid == ETH_P_8021Q)
12818afadd1cSBrett Creeley 			adapter->aq_required &=
12828afadd1cSBrett Creeley 				~IAVF_FLAG_AQ_DISABLE_CTAG_VLAN_INSERTION;
12838afadd1cSBrett Creeley 		else if (tpid == ETH_P_8021AD)
12848afadd1cSBrett Creeley 			adapter->aq_required &=
12858afadd1cSBrett Creeley 				~IAVF_FLAG_AQ_DISABLE_STAG_VLAN_INSERTION;
12868afadd1cSBrett Creeley 		break;
12878afadd1cSBrett Creeley 	default:
12888afadd1cSBrett Creeley 		dev_err(&adapter->pdev->dev, "Unsupported opcode %d specified for clearing aq_required bits for VIRTCHNL_VF_OFFLOAD_VLAN_V2 offload request\n",
12898afadd1cSBrett Creeley 			offload_op);
12908afadd1cSBrett Creeley 	}
12918afadd1cSBrett Creeley }
12928afadd1cSBrett Creeley 
12938afadd1cSBrett Creeley /**
12948afadd1cSBrett Creeley  * iavf_send_vlan_offload_v2 - send offload enable/disable over virtchnl
12958afadd1cSBrett Creeley  * @adapter: adapter structure
12968afadd1cSBrett Creeley  * @tpid: VLAN TPID used for the command (i.e. 0x8100 or 0x88a8)
12978afadd1cSBrett Creeley  * @offload_op: offload_op used to make the request over virtchnl
12988afadd1cSBrett Creeley  */
12998afadd1cSBrett Creeley static void
iavf_send_vlan_offload_v2(struct iavf_adapter * adapter,u16 tpid,enum virtchnl_ops offload_op)13008afadd1cSBrett Creeley iavf_send_vlan_offload_v2(struct iavf_adapter *adapter, u16 tpid,
13018afadd1cSBrett Creeley 			  enum virtchnl_ops offload_op)
13028afadd1cSBrett Creeley {
13038afadd1cSBrett Creeley 	struct virtchnl_vlan_setting *msg;
13048afadd1cSBrett Creeley 	int len = sizeof(*msg);
13058afadd1cSBrett Creeley 
13068afadd1cSBrett Creeley 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
13078afadd1cSBrett Creeley 		/* bail because we already have a command pending */
13088afadd1cSBrett Creeley 		dev_err(&adapter->pdev->dev, "Cannot send %d, command %d pending\n",
13098afadd1cSBrett Creeley 			offload_op, adapter->current_op);
13108afadd1cSBrett Creeley 		return;
13118afadd1cSBrett Creeley 	}
13128afadd1cSBrett Creeley 
13138afadd1cSBrett Creeley 	adapter->current_op = offload_op;
13148afadd1cSBrett Creeley 
13158afadd1cSBrett Creeley 	msg = kzalloc(len, GFP_KERNEL);
13168afadd1cSBrett Creeley 	if (!msg)
13178afadd1cSBrett Creeley 		return;
13188afadd1cSBrett Creeley 
13198afadd1cSBrett Creeley 	msg->vport_id = adapter->vsi_res->vsi_id;
13208afadd1cSBrett Creeley 
13218afadd1cSBrett Creeley 	/* always clear to prevent unsupported and endless requests */
13228afadd1cSBrett Creeley 	iavf_clear_offload_v2_aq_required(adapter, tpid, offload_op);
13238afadd1cSBrett Creeley 
13248afadd1cSBrett Creeley 	/* only send valid offload requests */
13258afadd1cSBrett Creeley 	if (!iavf_set_vc_offload_ethertype(adapter, msg, tpid, offload_op))
13268afadd1cSBrett Creeley 		iavf_send_pf_msg(adapter, offload_op, (u8 *)msg, len);
13278afadd1cSBrett Creeley 	else
13288afadd1cSBrett Creeley 		adapter->current_op = VIRTCHNL_OP_UNKNOWN;
13298afadd1cSBrett Creeley 
13308afadd1cSBrett Creeley 	kfree(msg);
13318afadd1cSBrett Creeley }
13328afadd1cSBrett Creeley 
13338afadd1cSBrett Creeley /**
13348afadd1cSBrett Creeley  * iavf_enable_vlan_stripping_v2 - enable VLAN stripping
13358afadd1cSBrett Creeley  * @adapter: adapter structure
13368afadd1cSBrett Creeley  * @tpid: VLAN TPID used to enable VLAN stripping
13378afadd1cSBrett Creeley  */
iavf_enable_vlan_stripping_v2(struct iavf_adapter * adapter,u16 tpid)13388afadd1cSBrett Creeley void iavf_enable_vlan_stripping_v2(struct iavf_adapter *adapter, u16 tpid)
13398afadd1cSBrett Creeley {
13408afadd1cSBrett Creeley 	iavf_send_vlan_offload_v2(adapter, tpid,
13418afadd1cSBrett Creeley 				  VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2);
13428afadd1cSBrett Creeley }
13438afadd1cSBrett Creeley 
13448afadd1cSBrett Creeley /**
13458afadd1cSBrett Creeley  * iavf_disable_vlan_stripping_v2 - disable VLAN stripping
13468afadd1cSBrett Creeley  * @adapter: adapter structure
13478afadd1cSBrett Creeley  * @tpid: VLAN TPID used to disable VLAN stripping
13488afadd1cSBrett Creeley  */
iavf_disable_vlan_stripping_v2(struct iavf_adapter * adapter,u16 tpid)13498afadd1cSBrett Creeley void iavf_disable_vlan_stripping_v2(struct iavf_adapter *adapter, u16 tpid)
13508afadd1cSBrett Creeley {
13518afadd1cSBrett Creeley 	iavf_send_vlan_offload_v2(adapter, tpid,
13528afadd1cSBrett Creeley 				  VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2);
13538afadd1cSBrett Creeley }
13548afadd1cSBrett Creeley 
13558afadd1cSBrett Creeley /**
13568afadd1cSBrett Creeley  * iavf_enable_vlan_insertion_v2 - enable VLAN insertion
13578afadd1cSBrett Creeley  * @adapter: adapter structure
13588afadd1cSBrett Creeley  * @tpid: VLAN TPID used to enable VLAN insertion
13598afadd1cSBrett Creeley  */
iavf_enable_vlan_insertion_v2(struct iavf_adapter * adapter,u16 tpid)13608afadd1cSBrett Creeley void iavf_enable_vlan_insertion_v2(struct iavf_adapter *adapter, u16 tpid)
13618afadd1cSBrett Creeley {
13628afadd1cSBrett Creeley 	iavf_send_vlan_offload_v2(adapter, tpid,
13638afadd1cSBrett Creeley 				  VIRTCHNL_OP_ENABLE_VLAN_INSERTION_V2);
13648afadd1cSBrett Creeley }
13658afadd1cSBrett Creeley 
13668afadd1cSBrett Creeley /**
13678afadd1cSBrett Creeley  * iavf_disable_vlan_insertion_v2 - disable VLAN insertion
13688afadd1cSBrett Creeley  * @adapter: adapter structure
13698afadd1cSBrett Creeley  * @tpid: VLAN TPID used to disable VLAN insertion
13708afadd1cSBrett Creeley  */
iavf_disable_vlan_insertion_v2(struct iavf_adapter * adapter,u16 tpid)13718afadd1cSBrett Creeley void iavf_disable_vlan_insertion_v2(struct iavf_adapter *adapter, u16 tpid)
13728afadd1cSBrett Creeley {
13738afadd1cSBrett Creeley 	iavf_send_vlan_offload_v2(adapter, tpid,
13748afadd1cSBrett Creeley 				  VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2);
13758afadd1cSBrett Creeley }
13768afadd1cSBrett Creeley 
1377e0ef26fbSBrett Creeley #define IAVF_MAX_SPEED_STRLEN	13
1378e0ef26fbSBrett Creeley 
13795ec8b7d1SJesse Brandeburg /**
13805ec8b7d1SJesse Brandeburg  * iavf_print_link_message - print link up or down
13815ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
13825ec8b7d1SJesse Brandeburg  *
13835ec8b7d1SJesse Brandeburg  * Log a message telling the world of our wonderous link status
13845ec8b7d1SJesse Brandeburg  */
iavf_print_link_message(struct iavf_adapter * adapter)13855ec8b7d1SJesse Brandeburg static void iavf_print_link_message(struct iavf_adapter *adapter)
13865ec8b7d1SJesse Brandeburg {
13875ec8b7d1SJesse Brandeburg 	struct net_device *netdev = adapter->netdev;
1388e0ef26fbSBrett Creeley 	int link_speed_mbps;
1389e0ef26fbSBrett Creeley 	char *speed;
13905ec8b7d1SJesse Brandeburg 
13915ec8b7d1SJesse Brandeburg 	if (!adapter->link_up) {
13925ec8b7d1SJesse Brandeburg 		netdev_info(netdev, "NIC Link is Down\n");
13935ec8b7d1SJesse Brandeburg 		return;
13945ec8b7d1SJesse Brandeburg 	}
13955ec8b7d1SJesse Brandeburg 
13968a57965eSZheng Yongjun 	speed = kzalloc(IAVF_MAX_SPEED_STRLEN, GFP_KERNEL);
1397e0ef26fbSBrett Creeley 	if (!speed)
1398e0ef26fbSBrett Creeley 		return;
1399e0ef26fbSBrett Creeley 
1400e0ef26fbSBrett Creeley 	if (ADV_LINK_SUPPORT(adapter)) {
1401e0ef26fbSBrett Creeley 		link_speed_mbps = adapter->link_speed_mbps;
1402e0ef26fbSBrett Creeley 		goto print_link_msg;
1403e0ef26fbSBrett Creeley 	}
1404e0ef26fbSBrett Creeley 
14055ec8b7d1SJesse Brandeburg 	switch (adapter->link_speed) {
14065071bda2SAleksandr Loktionov 	case VIRTCHNL_LINK_SPEED_40GB:
1407e0ef26fbSBrett Creeley 		link_speed_mbps = SPEED_40000;
14085ec8b7d1SJesse Brandeburg 		break;
14095071bda2SAleksandr Loktionov 	case VIRTCHNL_LINK_SPEED_25GB:
1410e0ef26fbSBrett Creeley 		link_speed_mbps = SPEED_25000;
14115ec8b7d1SJesse Brandeburg 		break;
14125071bda2SAleksandr Loktionov 	case VIRTCHNL_LINK_SPEED_20GB:
1413e0ef26fbSBrett Creeley 		link_speed_mbps = SPEED_20000;
14145ec8b7d1SJesse Brandeburg 		break;
14155071bda2SAleksandr Loktionov 	case VIRTCHNL_LINK_SPEED_10GB:
1416e0ef26fbSBrett Creeley 		link_speed_mbps = SPEED_10000;
14175ec8b7d1SJesse Brandeburg 		break;
141818c012d9SBrett Creeley 	case VIRTCHNL_LINK_SPEED_5GB:
141918c012d9SBrett Creeley 		link_speed_mbps = SPEED_5000;
142018c012d9SBrett Creeley 		break;
142118c012d9SBrett Creeley 	case VIRTCHNL_LINK_SPEED_2_5GB:
142218c012d9SBrett Creeley 		link_speed_mbps = SPEED_2500;
142318c012d9SBrett Creeley 		break;
14245071bda2SAleksandr Loktionov 	case VIRTCHNL_LINK_SPEED_1GB:
1425e0ef26fbSBrett Creeley 		link_speed_mbps = SPEED_1000;
14265ec8b7d1SJesse Brandeburg 		break;
14275071bda2SAleksandr Loktionov 	case VIRTCHNL_LINK_SPEED_100MB:
1428e0ef26fbSBrett Creeley 		link_speed_mbps = SPEED_100;
14295ec8b7d1SJesse Brandeburg 		break;
14305ec8b7d1SJesse Brandeburg 	default:
1431e0ef26fbSBrett Creeley 		link_speed_mbps = SPEED_UNKNOWN;
14325ec8b7d1SJesse Brandeburg 		break;
14335ec8b7d1SJesse Brandeburg 	}
14345ec8b7d1SJesse Brandeburg 
1435e0ef26fbSBrett Creeley print_link_msg:
1436e0ef26fbSBrett Creeley 	if (link_speed_mbps > SPEED_1000) {
1437e0ef26fbSBrett Creeley 		if (link_speed_mbps == SPEED_2500)
1438e0ef26fbSBrett Creeley 			snprintf(speed, IAVF_MAX_SPEED_STRLEN, "2.5 Gbps");
1439e0ef26fbSBrett Creeley 		else
1440e0ef26fbSBrett Creeley 			/* convert to Gbps inline */
1441e0ef26fbSBrett Creeley 			snprintf(speed, IAVF_MAX_SPEED_STRLEN, "%d %s",
1442e0ef26fbSBrett Creeley 				 link_speed_mbps / 1000, "Gbps");
1443e0ef26fbSBrett Creeley 	} else if (link_speed_mbps == SPEED_UNKNOWN) {
1444e0ef26fbSBrett Creeley 		snprintf(speed, IAVF_MAX_SPEED_STRLEN, "%s", "Unknown Mbps");
1445e0ef26fbSBrett Creeley 	} else {
1446c2fbcc94SKaren Sornek 		snprintf(speed, IAVF_MAX_SPEED_STRLEN, "%d %s",
1447e0ef26fbSBrett Creeley 			 link_speed_mbps, "Mbps");
1448e0ef26fbSBrett Creeley 	}
1449e0ef26fbSBrett Creeley 
1450e0ef26fbSBrett Creeley 	netdev_info(netdev, "NIC Link is Up Speed is %s Full Duplex\n", speed);
1451e0ef26fbSBrett Creeley 	kfree(speed);
1452e0ef26fbSBrett Creeley }
1453e0ef26fbSBrett Creeley 
1454e0ef26fbSBrett Creeley /**
1455e0ef26fbSBrett Creeley  * iavf_get_vpe_link_status
1456e0ef26fbSBrett Creeley  * @adapter: adapter structure
1457e0ef26fbSBrett Creeley  * @vpe: virtchnl_pf_event structure
1458e0ef26fbSBrett Creeley  *
1459e0ef26fbSBrett Creeley  * Helper function for determining the link status
1460e0ef26fbSBrett Creeley  **/
1461e0ef26fbSBrett Creeley static bool
iavf_get_vpe_link_status(struct iavf_adapter * adapter,struct virtchnl_pf_event * vpe)1462e0ef26fbSBrett Creeley iavf_get_vpe_link_status(struct iavf_adapter *adapter,
1463e0ef26fbSBrett Creeley 			 struct virtchnl_pf_event *vpe)
1464e0ef26fbSBrett Creeley {
1465e0ef26fbSBrett Creeley 	if (ADV_LINK_SUPPORT(adapter))
1466e0ef26fbSBrett Creeley 		return vpe->event_data.link_event_adv.link_status;
1467e0ef26fbSBrett Creeley 	else
1468e0ef26fbSBrett Creeley 		return vpe->event_data.link_event.link_status;
1469e0ef26fbSBrett Creeley }
1470e0ef26fbSBrett Creeley 
1471e0ef26fbSBrett Creeley /**
1472e0ef26fbSBrett Creeley  * iavf_set_adapter_link_speed_from_vpe
1473e0ef26fbSBrett Creeley  * @adapter: adapter structure for which we are setting the link speed
1474e0ef26fbSBrett Creeley  * @vpe: virtchnl_pf_event structure that contains the link speed we are setting
1475e0ef26fbSBrett Creeley  *
1476e0ef26fbSBrett Creeley  * Helper function for setting iavf_adapter link speed
1477e0ef26fbSBrett Creeley  **/
1478e0ef26fbSBrett Creeley static void
iavf_set_adapter_link_speed_from_vpe(struct iavf_adapter * adapter,struct virtchnl_pf_event * vpe)1479e0ef26fbSBrett Creeley iavf_set_adapter_link_speed_from_vpe(struct iavf_adapter *adapter,
1480e0ef26fbSBrett Creeley 				     struct virtchnl_pf_event *vpe)
1481e0ef26fbSBrett Creeley {
1482e0ef26fbSBrett Creeley 	if (ADV_LINK_SUPPORT(adapter))
1483e0ef26fbSBrett Creeley 		adapter->link_speed_mbps =
1484e0ef26fbSBrett Creeley 			vpe->event_data.link_event_adv.link_speed;
1485e0ef26fbSBrett Creeley 	else
1486e0ef26fbSBrett Creeley 		adapter->link_speed = vpe->event_data.link_event.link_speed;
14875ec8b7d1SJesse Brandeburg }
14885ec8b7d1SJesse Brandeburg 
14895ec8b7d1SJesse Brandeburg /**
1490262de08fSJesse Brandeburg  * iavf_enable_channels
14915ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
14925ec8b7d1SJesse Brandeburg  *
14935ec8b7d1SJesse Brandeburg  * Request that the PF enable channels as specified by
14945ec8b7d1SJesse Brandeburg  * the user via tc tool.
14955ec8b7d1SJesse Brandeburg  **/
iavf_enable_channels(struct iavf_adapter * adapter)14965ec8b7d1SJesse Brandeburg void iavf_enable_channels(struct iavf_adapter *adapter)
14975ec8b7d1SJesse Brandeburg {
14985ec8b7d1SJesse Brandeburg 	struct virtchnl_tc_info *vti = NULL;
1499af07adbbSGustavo A. R. Silva 	size_t len;
15005ec8b7d1SJesse Brandeburg 	int i;
15015ec8b7d1SJesse Brandeburg 
15025ec8b7d1SJesse Brandeburg 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
15035ec8b7d1SJesse Brandeburg 		/* bail because we already have a command pending */
15045ec8b7d1SJesse Brandeburg 		dev_err(&adapter->pdev->dev, "Cannot configure mqprio, command %d pending\n",
15055ec8b7d1SJesse Brandeburg 			adapter->current_op);
15065ec8b7d1SJesse Brandeburg 		return;
15075ec8b7d1SJesse Brandeburg 	}
15085ec8b7d1SJesse Brandeburg 
1509b0654e64SAlexander Lobakin 	len = virtchnl_struct_size(vti, list, adapter->num_tc);
15105ec8b7d1SJesse Brandeburg 	vti = kzalloc(len, GFP_KERNEL);
15115ec8b7d1SJesse Brandeburg 	if (!vti)
15125ec8b7d1SJesse Brandeburg 		return;
15135ec8b7d1SJesse Brandeburg 	vti->num_tc = adapter->num_tc;
15145ec8b7d1SJesse Brandeburg 	for (i = 0; i < vti->num_tc; i++) {
15155ec8b7d1SJesse Brandeburg 		vti->list[i].count = adapter->ch_config.ch_info[i].count;
15165ec8b7d1SJesse Brandeburg 		vti->list[i].offset = adapter->ch_config.ch_info[i].offset;
15175ec8b7d1SJesse Brandeburg 		vti->list[i].pad = 0;
15185ec8b7d1SJesse Brandeburg 		vti->list[i].max_tx_rate =
15195ec8b7d1SJesse Brandeburg 				adapter->ch_config.ch_info[i].max_tx_rate;
15205ec8b7d1SJesse Brandeburg 	}
15215ec8b7d1SJesse Brandeburg 
15225ec8b7d1SJesse Brandeburg 	adapter->ch_config.state = __IAVF_TC_RUNNING;
15235ec8b7d1SJesse Brandeburg 	adapter->flags |= IAVF_FLAG_REINIT_ITR_NEEDED;
15245ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_ENABLE_CHANNELS;
15255ec8b7d1SJesse Brandeburg 	adapter->aq_required &= ~IAVF_FLAG_AQ_ENABLE_CHANNELS;
15265ec8b7d1SJesse Brandeburg 	iavf_send_pf_msg(adapter, VIRTCHNL_OP_ENABLE_CHANNELS, (u8 *)vti, len);
15275ec8b7d1SJesse Brandeburg 	kfree(vti);
15285ec8b7d1SJesse Brandeburg }
15295ec8b7d1SJesse Brandeburg 
15305ec8b7d1SJesse Brandeburg /**
1531262de08fSJesse Brandeburg  * iavf_disable_channels
15325ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
15335ec8b7d1SJesse Brandeburg  *
15345ec8b7d1SJesse Brandeburg  * Request that the PF disable channels that are configured
15355ec8b7d1SJesse Brandeburg  **/
iavf_disable_channels(struct iavf_adapter * adapter)15365ec8b7d1SJesse Brandeburg void iavf_disable_channels(struct iavf_adapter *adapter)
15375ec8b7d1SJesse Brandeburg {
15385ec8b7d1SJesse Brandeburg 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
15395ec8b7d1SJesse Brandeburg 		/* bail because we already have a command pending */
15405ec8b7d1SJesse Brandeburg 		dev_err(&adapter->pdev->dev, "Cannot configure mqprio, command %d pending\n",
15415ec8b7d1SJesse Brandeburg 			adapter->current_op);
15425ec8b7d1SJesse Brandeburg 		return;
15435ec8b7d1SJesse Brandeburg 	}
15445ec8b7d1SJesse Brandeburg 
15455ec8b7d1SJesse Brandeburg 	adapter->ch_config.state = __IAVF_TC_INVALID;
15465ec8b7d1SJesse Brandeburg 	adapter->flags |= IAVF_FLAG_REINIT_ITR_NEEDED;
15475ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_DISABLE_CHANNELS;
15485ec8b7d1SJesse Brandeburg 	adapter->aq_required &= ~IAVF_FLAG_AQ_DISABLE_CHANNELS;
15495ec8b7d1SJesse Brandeburg 	iavf_send_pf_msg(adapter, VIRTCHNL_OP_DISABLE_CHANNELS, NULL, 0);
15505ec8b7d1SJesse Brandeburg }
15515ec8b7d1SJesse Brandeburg 
15525ec8b7d1SJesse Brandeburg /**
15535ec8b7d1SJesse Brandeburg  * iavf_print_cloud_filter
15545ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
15555ec8b7d1SJesse Brandeburg  * @f: cloud filter to print
15565ec8b7d1SJesse Brandeburg  *
15575ec8b7d1SJesse Brandeburg  * Print the cloud filter
15585ec8b7d1SJesse Brandeburg  **/
iavf_print_cloud_filter(struct iavf_adapter * adapter,struct virtchnl_filter * f)15595ec8b7d1SJesse Brandeburg static void iavf_print_cloud_filter(struct iavf_adapter *adapter,
15605ec8b7d1SJesse Brandeburg 				    struct virtchnl_filter *f)
15615ec8b7d1SJesse Brandeburg {
15625ec8b7d1SJesse Brandeburg 	switch (f->flow_type) {
15635ec8b7d1SJesse Brandeburg 	case VIRTCHNL_TCP_V4_FLOW:
15645ec8b7d1SJesse Brandeburg 		dev_info(&adapter->pdev->dev, "dst_mac: %pM src_mac: %pM vlan_id: %hu dst_ip: %pI4 src_ip %pI4 dst_port %hu src_port %hu\n",
15655ec8b7d1SJesse Brandeburg 			 &f->data.tcp_spec.dst_mac,
15665ec8b7d1SJesse Brandeburg 			 &f->data.tcp_spec.src_mac,
15675ec8b7d1SJesse Brandeburg 			 ntohs(f->data.tcp_spec.vlan_id),
15685ec8b7d1SJesse Brandeburg 			 &f->data.tcp_spec.dst_ip[0],
15695ec8b7d1SJesse Brandeburg 			 &f->data.tcp_spec.src_ip[0],
15705ec8b7d1SJesse Brandeburg 			 ntohs(f->data.tcp_spec.dst_port),
15715ec8b7d1SJesse Brandeburg 			 ntohs(f->data.tcp_spec.src_port));
15725ec8b7d1SJesse Brandeburg 		break;
15735ec8b7d1SJesse Brandeburg 	case VIRTCHNL_TCP_V6_FLOW:
15745ec8b7d1SJesse Brandeburg 		dev_info(&adapter->pdev->dev, "dst_mac: %pM src_mac: %pM vlan_id: %hu dst_ip: %pI6 src_ip %pI6 dst_port %hu src_port %hu\n",
15755ec8b7d1SJesse Brandeburg 			 &f->data.tcp_spec.dst_mac,
15765ec8b7d1SJesse Brandeburg 			 &f->data.tcp_spec.src_mac,
15775ec8b7d1SJesse Brandeburg 			 ntohs(f->data.tcp_spec.vlan_id),
15785ec8b7d1SJesse Brandeburg 			 &f->data.tcp_spec.dst_ip,
15795ec8b7d1SJesse Brandeburg 			 &f->data.tcp_spec.src_ip,
15805ec8b7d1SJesse Brandeburg 			 ntohs(f->data.tcp_spec.dst_port),
15815ec8b7d1SJesse Brandeburg 			 ntohs(f->data.tcp_spec.src_port));
15825ec8b7d1SJesse Brandeburg 		break;
15835ec8b7d1SJesse Brandeburg 	}
15845ec8b7d1SJesse Brandeburg }
15855ec8b7d1SJesse Brandeburg 
15865ec8b7d1SJesse Brandeburg /**
15875ec8b7d1SJesse Brandeburg  * iavf_add_cloud_filter
15885ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
15895ec8b7d1SJesse Brandeburg  *
15905ec8b7d1SJesse Brandeburg  * Request that the PF add cloud filters as specified
15915ec8b7d1SJesse Brandeburg  * by the user via tc tool.
15925ec8b7d1SJesse Brandeburg  **/
iavf_add_cloud_filter(struct iavf_adapter * adapter)15935ec8b7d1SJesse Brandeburg void iavf_add_cloud_filter(struct iavf_adapter *adapter)
15945ec8b7d1SJesse Brandeburg {
15955ec8b7d1SJesse Brandeburg 	struct iavf_cloud_filter *cf;
15965ec8b7d1SJesse Brandeburg 	struct virtchnl_filter *f;
15975ec8b7d1SJesse Brandeburg 	int len = 0, count = 0;
15985ec8b7d1SJesse Brandeburg 
15995ec8b7d1SJesse Brandeburg 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
16005ec8b7d1SJesse Brandeburg 		/* bail because we already have a command pending */
16015ec8b7d1SJesse Brandeburg 		dev_err(&adapter->pdev->dev, "Cannot add cloud filter, command %d pending\n",
16025ec8b7d1SJesse Brandeburg 			adapter->current_op);
16035ec8b7d1SJesse Brandeburg 		return;
16045ec8b7d1SJesse Brandeburg 	}
16055ec8b7d1SJesse Brandeburg 	list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
16065ec8b7d1SJesse Brandeburg 		if (cf->add) {
16075ec8b7d1SJesse Brandeburg 			count++;
16085ec8b7d1SJesse Brandeburg 			break;
16095ec8b7d1SJesse Brandeburg 		}
16105ec8b7d1SJesse Brandeburg 	}
16115ec8b7d1SJesse Brandeburg 	if (!count) {
16125ec8b7d1SJesse Brandeburg 		adapter->aq_required &= ~IAVF_FLAG_AQ_ADD_CLOUD_FILTER;
16135ec8b7d1SJesse Brandeburg 		return;
16145ec8b7d1SJesse Brandeburg 	}
16155ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_ADD_CLOUD_FILTER;
16165ec8b7d1SJesse Brandeburg 
16175ec8b7d1SJesse Brandeburg 	len = sizeof(struct virtchnl_filter);
16185ec8b7d1SJesse Brandeburg 	f = kzalloc(len, GFP_KERNEL);
16195ec8b7d1SJesse Brandeburg 	if (!f)
16205ec8b7d1SJesse Brandeburg 		return;
16215ec8b7d1SJesse Brandeburg 
16225ec8b7d1SJesse Brandeburg 	list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
16235ec8b7d1SJesse Brandeburg 		if (cf->add) {
16245ec8b7d1SJesse Brandeburg 			memcpy(f, &cf->f, sizeof(struct virtchnl_filter));
16255ec8b7d1SJesse Brandeburg 			cf->add = false;
16265ec8b7d1SJesse Brandeburg 			cf->state = __IAVF_CF_ADD_PENDING;
16275ec8b7d1SJesse Brandeburg 			iavf_send_pf_msg(adapter, VIRTCHNL_OP_ADD_CLOUD_FILTER,
16285ec8b7d1SJesse Brandeburg 					 (u8 *)f, len);
16295ec8b7d1SJesse Brandeburg 		}
16305ec8b7d1SJesse Brandeburg 	}
16315ec8b7d1SJesse Brandeburg 	kfree(f);
16325ec8b7d1SJesse Brandeburg }
16335ec8b7d1SJesse Brandeburg 
16345ec8b7d1SJesse Brandeburg /**
16355ec8b7d1SJesse Brandeburg  * iavf_del_cloud_filter
16365ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
16375ec8b7d1SJesse Brandeburg  *
16385ec8b7d1SJesse Brandeburg  * Request that the PF delete cloud filters as specified
16395ec8b7d1SJesse Brandeburg  * by the user via tc tool.
16405ec8b7d1SJesse Brandeburg  **/
iavf_del_cloud_filter(struct iavf_adapter * adapter)16415ec8b7d1SJesse Brandeburg void iavf_del_cloud_filter(struct iavf_adapter *adapter)
16425ec8b7d1SJesse Brandeburg {
16435ec8b7d1SJesse Brandeburg 	struct iavf_cloud_filter *cf, *cftmp;
16445ec8b7d1SJesse Brandeburg 	struct virtchnl_filter *f;
16455ec8b7d1SJesse Brandeburg 	int len = 0, count = 0;
16465ec8b7d1SJesse Brandeburg 
16475ec8b7d1SJesse Brandeburg 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
16485ec8b7d1SJesse Brandeburg 		/* bail because we already have a command pending */
16495ec8b7d1SJesse Brandeburg 		dev_err(&adapter->pdev->dev, "Cannot remove cloud filter, command %d pending\n",
16505ec8b7d1SJesse Brandeburg 			adapter->current_op);
16515ec8b7d1SJesse Brandeburg 		return;
16525ec8b7d1SJesse Brandeburg 	}
16535ec8b7d1SJesse Brandeburg 	list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
16545ec8b7d1SJesse Brandeburg 		if (cf->del) {
16555ec8b7d1SJesse Brandeburg 			count++;
16565ec8b7d1SJesse Brandeburg 			break;
16575ec8b7d1SJesse Brandeburg 		}
16585ec8b7d1SJesse Brandeburg 	}
16595ec8b7d1SJesse Brandeburg 	if (!count) {
16605ec8b7d1SJesse Brandeburg 		adapter->aq_required &= ~IAVF_FLAG_AQ_DEL_CLOUD_FILTER;
16615ec8b7d1SJesse Brandeburg 		return;
16625ec8b7d1SJesse Brandeburg 	}
16635ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_DEL_CLOUD_FILTER;
16645ec8b7d1SJesse Brandeburg 
16655ec8b7d1SJesse Brandeburg 	len = sizeof(struct virtchnl_filter);
16665ec8b7d1SJesse Brandeburg 	f = kzalloc(len, GFP_KERNEL);
16675ec8b7d1SJesse Brandeburg 	if (!f)
16685ec8b7d1SJesse Brandeburg 		return;
16695ec8b7d1SJesse Brandeburg 
16705ec8b7d1SJesse Brandeburg 	list_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list, list) {
16715ec8b7d1SJesse Brandeburg 		if (cf->del) {
16725ec8b7d1SJesse Brandeburg 			memcpy(f, &cf->f, sizeof(struct virtchnl_filter));
16735ec8b7d1SJesse Brandeburg 			cf->del = false;
16745ec8b7d1SJesse Brandeburg 			cf->state = __IAVF_CF_DEL_PENDING;
16755ec8b7d1SJesse Brandeburg 			iavf_send_pf_msg(adapter, VIRTCHNL_OP_DEL_CLOUD_FILTER,
16765ec8b7d1SJesse Brandeburg 					 (u8 *)f, len);
16775ec8b7d1SJesse Brandeburg 		}
16785ec8b7d1SJesse Brandeburg 	}
16795ec8b7d1SJesse Brandeburg 	kfree(f);
16805ec8b7d1SJesse Brandeburg }
16815ec8b7d1SJesse Brandeburg 
16825ec8b7d1SJesse Brandeburg /**
16830dbfbabbSHaiyue Wang  * iavf_add_fdir_filter
16840dbfbabbSHaiyue Wang  * @adapter: the VF adapter structure
16850dbfbabbSHaiyue Wang  *
16860dbfbabbSHaiyue Wang  * Request that the PF add Flow Director filters as specified
16870dbfbabbSHaiyue Wang  * by the user via ethtool.
16880dbfbabbSHaiyue Wang  **/
iavf_add_fdir_filter(struct iavf_adapter * adapter)16890dbfbabbSHaiyue Wang void iavf_add_fdir_filter(struct iavf_adapter *adapter)
16900dbfbabbSHaiyue Wang {
16910dbfbabbSHaiyue Wang 	struct iavf_fdir_fltr *fdir;
16920dbfbabbSHaiyue Wang 	struct virtchnl_fdir_add *f;
16930dbfbabbSHaiyue Wang 	bool process_fltr = false;
16940dbfbabbSHaiyue Wang 	int len;
16950dbfbabbSHaiyue Wang 
16960dbfbabbSHaiyue Wang 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
16970dbfbabbSHaiyue Wang 		/* bail because we already have a command pending */
16980dbfbabbSHaiyue Wang 		dev_err(&adapter->pdev->dev, "Cannot add Flow Director filter, command %d pending\n",
16990dbfbabbSHaiyue Wang 			adapter->current_op);
17000dbfbabbSHaiyue Wang 		return;
17010dbfbabbSHaiyue Wang 	}
17020dbfbabbSHaiyue Wang 
17030dbfbabbSHaiyue Wang 	len = sizeof(struct virtchnl_fdir_add);
17040dbfbabbSHaiyue Wang 	f = kzalloc(len, GFP_KERNEL);
17050dbfbabbSHaiyue Wang 	if (!f)
17060dbfbabbSHaiyue Wang 		return;
17070dbfbabbSHaiyue Wang 
17080dbfbabbSHaiyue Wang 	spin_lock_bh(&adapter->fdir_fltr_lock);
17090dbfbabbSHaiyue Wang 	list_for_each_entry(fdir, &adapter->fdir_list_head, list) {
17100dbfbabbSHaiyue Wang 		if (fdir->state == IAVF_FDIR_FLTR_ADD_REQUEST) {
17110dbfbabbSHaiyue Wang 			process_fltr = true;
17120dbfbabbSHaiyue Wang 			fdir->state = IAVF_FDIR_FLTR_ADD_PENDING;
17130dbfbabbSHaiyue Wang 			memcpy(f, &fdir->vc_add_msg, len);
17140dbfbabbSHaiyue Wang 			break;
17150dbfbabbSHaiyue Wang 		}
17160dbfbabbSHaiyue Wang 	}
17170dbfbabbSHaiyue Wang 	spin_unlock_bh(&adapter->fdir_fltr_lock);
17180dbfbabbSHaiyue Wang 
17190dbfbabbSHaiyue Wang 	if (!process_fltr) {
17200dbfbabbSHaiyue Wang 		/* prevent iavf_add_fdir_filter() from being called when there
17210dbfbabbSHaiyue Wang 		 * are no filters to add
17220dbfbabbSHaiyue Wang 		 */
17230dbfbabbSHaiyue Wang 		adapter->aq_required &= ~IAVF_FLAG_AQ_ADD_FDIR_FILTER;
17240dbfbabbSHaiyue Wang 		kfree(f);
17250dbfbabbSHaiyue Wang 		return;
17260dbfbabbSHaiyue Wang 	}
17270dbfbabbSHaiyue Wang 	adapter->current_op = VIRTCHNL_OP_ADD_FDIR_FILTER;
17280dbfbabbSHaiyue Wang 	iavf_send_pf_msg(adapter, VIRTCHNL_OP_ADD_FDIR_FILTER, (u8 *)f, len);
17290dbfbabbSHaiyue Wang 	kfree(f);
17300dbfbabbSHaiyue Wang }
17310dbfbabbSHaiyue Wang 
17320dbfbabbSHaiyue Wang /**
17330dbfbabbSHaiyue Wang  * iavf_del_fdir_filter
17340dbfbabbSHaiyue Wang  * @adapter: the VF adapter structure
17350dbfbabbSHaiyue Wang  *
17360dbfbabbSHaiyue Wang  * Request that the PF delete Flow Director filters as specified
17370dbfbabbSHaiyue Wang  * by the user via ethtool.
17380dbfbabbSHaiyue Wang  **/
iavf_del_fdir_filter(struct iavf_adapter * adapter)17390dbfbabbSHaiyue Wang void iavf_del_fdir_filter(struct iavf_adapter *adapter)
17400dbfbabbSHaiyue Wang {
1741*3beb9d66SPiotr Gardocki 	struct virtchnl_fdir_del f = {};
17420dbfbabbSHaiyue Wang 	struct iavf_fdir_fltr *fdir;
17430dbfbabbSHaiyue Wang 	bool process_fltr = false;
17440dbfbabbSHaiyue Wang 	int len;
17450dbfbabbSHaiyue Wang 
17460dbfbabbSHaiyue Wang 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
17470dbfbabbSHaiyue Wang 		/* bail because we already have a command pending */
17480dbfbabbSHaiyue Wang 		dev_err(&adapter->pdev->dev, "Cannot remove Flow Director filter, command %d pending\n",
17490dbfbabbSHaiyue Wang 			adapter->current_op);
17500dbfbabbSHaiyue Wang 		return;
17510dbfbabbSHaiyue Wang 	}
17520dbfbabbSHaiyue Wang 
17530dbfbabbSHaiyue Wang 	len = sizeof(struct virtchnl_fdir_del);
17540dbfbabbSHaiyue Wang 
17550dbfbabbSHaiyue Wang 	spin_lock_bh(&adapter->fdir_fltr_lock);
17560dbfbabbSHaiyue Wang 	list_for_each_entry(fdir, &adapter->fdir_list_head, list) {
17570dbfbabbSHaiyue Wang 		if (fdir->state == IAVF_FDIR_FLTR_DEL_REQUEST) {
17580dbfbabbSHaiyue Wang 			process_fltr = true;
17590dbfbabbSHaiyue Wang 			f.vsi_id = fdir->vc_add_msg.vsi_id;
17600dbfbabbSHaiyue Wang 			f.flow_id = fdir->flow_id;
17610dbfbabbSHaiyue Wang 			fdir->state = IAVF_FDIR_FLTR_DEL_PENDING;
17620dbfbabbSHaiyue Wang 			break;
1763*3beb9d66SPiotr Gardocki 		} else if (fdir->state == IAVF_FDIR_FLTR_DIS_REQUEST) {
1764*3beb9d66SPiotr Gardocki 			process_fltr = true;
1765*3beb9d66SPiotr Gardocki 			f.vsi_id = fdir->vc_add_msg.vsi_id;
1766*3beb9d66SPiotr Gardocki 			f.flow_id = fdir->flow_id;
1767*3beb9d66SPiotr Gardocki 			fdir->state = IAVF_FDIR_FLTR_DIS_PENDING;
1768*3beb9d66SPiotr Gardocki 			break;
17690dbfbabbSHaiyue Wang 		}
17700dbfbabbSHaiyue Wang 	}
17710dbfbabbSHaiyue Wang 	spin_unlock_bh(&adapter->fdir_fltr_lock);
17720dbfbabbSHaiyue Wang 
17730dbfbabbSHaiyue Wang 	if (!process_fltr) {
17740dbfbabbSHaiyue Wang 		adapter->aq_required &= ~IAVF_FLAG_AQ_DEL_FDIR_FILTER;
17750dbfbabbSHaiyue Wang 		return;
17760dbfbabbSHaiyue Wang 	}
17770dbfbabbSHaiyue Wang 
17780dbfbabbSHaiyue Wang 	adapter->current_op = VIRTCHNL_OP_DEL_FDIR_FILTER;
17790dbfbabbSHaiyue Wang 	iavf_send_pf_msg(adapter, VIRTCHNL_OP_DEL_FDIR_FILTER, (u8 *)&f, len);
17800dbfbabbSHaiyue Wang }
17810dbfbabbSHaiyue Wang 
17820dbfbabbSHaiyue Wang /**
17830aaeb4fbSHaiyue Wang  * iavf_add_adv_rss_cfg
17840aaeb4fbSHaiyue Wang  * @adapter: the VF adapter structure
17850aaeb4fbSHaiyue Wang  *
17860aaeb4fbSHaiyue Wang  * Request that the PF add RSS configuration as specified
17870aaeb4fbSHaiyue Wang  * by the user via ethtool.
17880aaeb4fbSHaiyue Wang  **/
iavf_add_adv_rss_cfg(struct iavf_adapter * adapter)17890aaeb4fbSHaiyue Wang void iavf_add_adv_rss_cfg(struct iavf_adapter *adapter)
17900aaeb4fbSHaiyue Wang {
17910aaeb4fbSHaiyue Wang 	struct virtchnl_rss_cfg *rss_cfg;
17920aaeb4fbSHaiyue Wang 	struct iavf_adv_rss *rss;
17930aaeb4fbSHaiyue Wang 	bool process_rss = false;
17940aaeb4fbSHaiyue Wang 	int len;
17950aaeb4fbSHaiyue Wang 
17960aaeb4fbSHaiyue Wang 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
17970aaeb4fbSHaiyue Wang 		/* bail because we already have a command pending */
17980aaeb4fbSHaiyue Wang 		dev_err(&adapter->pdev->dev, "Cannot add RSS configuration, command %d pending\n",
17990aaeb4fbSHaiyue Wang 			adapter->current_op);
18000aaeb4fbSHaiyue Wang 		return;
18010aaeb4fbSHaiyue Wang 	}
18020aaeb4fbSHaiyue Wang 
18030aaeb4fbSHaiyue Wang 	len = sizeof(struct virtchnl_rss_cfg);
18040aaeb4fbSHaiyue Wang 	rss_cfg = kzalloc(len, GFP_KERNEL);
18050aaeb4fbSHaiyue Wang 	if (!rss_cfg)
18060aaeb4fbSHaiyue Wang 		return;
18070aaeb4fbSHaiyue Wang 
18080aaeb4fbSHaiyue Wang 	spin_lock_bh(&adapter->adv_rss_lock);
18090aaeb4fbSHaiyue Wang 	list_for_each_entry(rss, &adapter->adv_rss_list_head, list) {
18100aaeb4fbSHaiyue Wang 		if (rss->state == IAVF_ADV_RSS_ADD_REQUEST) {
18110aaeb4fbSHaiyue Wang 			process_rss = true;
18120aaeb4fbSHaiyue Wang 			rss->state = IAVF_ADV_RSS_ADD_PENDING;
18130aaeb4fbSHaiyue Wang 			memcpy(rss_cfg, &rss->cfg_msg, len);
18145ab91e05SHaiyue Wang 			iavf_print_adv_rss_cfg(adapter, rss,
18155ab91e05SHaiyue Wang 					       "Input set change for",
18165ab91e05SHaiyue Wang 					       "is pending");
18170aaeb4fbSHaiyue Wang 			break;
18180aaeb4fbSHaiyue Wang 		}
18190aaeb4fbSHaiyue Wang 	}
18200aaeb4fbSHaiyue Wang 	spin_unlock_bh(&adapter->adv_rss_lock);
18210aaeb4fbSHaiyue Wang 
18220aaeb4fbSHaiyue Wang 	if (process_rss) {
18230aaeb4fbSHaiyue Wang 		adapter->current_op = VIRTCHNL_OP_ADD_RSS_CFG;
18240aaeb4fbSHaiyue Wang 		iavf_send_pf_msg(adapter, VIRTCHNL_OP_ADD_RSS_CFG,
18250aaeb4fbSHaiyue Wang 				 (u8 *)rss_cfg, len);
18260aaeb4fbSHaiyue Wang 	} else {
18270aaeb4fbSHaiyue Wang 		adapter->aq_required &= ~IAVF_FLAG_AQ_ADD_ADV_RSS_CFG;
18280aaeb4fbSHaiyue Wang 	}
18290aaeb4fbSHaiyue Wang 
18300aaeb4fbSHaiyue Wang 	kfree(rss_cfg);
18310aaeb4fbSHaiyue Wang }
18320aaeb4fbSHaiyue Wang 
18330aaeb4fbSHaiyue Wang /**
18340aaeb4fbSHaiyue Wang  * iavf_del_adv_rss_cfg
18350aaeb4fbSHaiyue Wang  * @adapter: the VF adapter structure
18360aaeb4fbSHaiyue Wang  *
18370aaeb4fbSHaiyue Wang  * Request that the PF delete RSS configuration as specified
18380aaeb4fbSHaiyue Wang  * by the user via ethtool.
18390aaeb4fbSHaiyue Wang  **/
iavf_del_adv_rss_cfg(struct iavf_adapter * adapter)18400aaeb4fbSHaiyue Wang void iavf_del_adv_rss_cfg(struct iavf_adapter *adapter)
18410aaeb4fbSHaiyue Wang {
18420aaeb4fbSHaiyue Wang 	struct virtchnl_rss_cfg *rss_cfg;
18430aaeb4fbSHaiyue Wang 	struct iavf_adv_rss *rss;
18440aaeb4fbSHaiyue Wang 	bool process_rss = false;
18450aaeb4fbSHaiyue Wang 	int len;
18460aaeb4fbSHaiyue Wang 
18470aaeb4fbSHaiyue Wang 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
18480aaeb4fbSHaiyue Wang 		/* bail because we already have a command pending */
18490aaeb4fbSHaiyue Wang 		dev_err(&adapter->pdev->dev, "Cannot remove RSS configuration, command %d pending\n",
18500aaeb4fbSHaiyue Wang 			adapter->current_op);
18510aaeb4fbSHaiyue Wang 		return;
18520aaeb4fbSHaiyue Wang 	}
18530aaeb4fbSHaiyue Wang 
18540aaeb4fbSHaiyue Wang 	len = sizeof(struct virtchnl_rss_cfg);
18550aaeb4fbSHaiyue Wang 	rss_cfg = kzalloc(len, GFP_KERNEL);
18560aaeb4fbSHaiyue Wang 	if (!rss_cfg)
18570aaeb4fbSHaiyue Wang 		return;
18580aaeb4fbSHaiyue Wang 
18590aaeb4fbSHaiyue Wang 	spin_lock_bh(&adapter->adv_rss_lock);
18600aaeb4fbSHaiyue Wang 	list_for_each_entry(rss, &adapter->adv_rss_list_head, list) {
18610aaeb4fbSHaiyue Wang 		if (rss->state == IAVF_ADV_RSS_DEL_REQUEST) {
18620aaeb4fbSHaiyue Wang 			process_rss = true;
18630aaeb4fbSHaiyue Wang 			rss->state = IAVF_ADV_RSS_DEL_PENDING;
18640aaeb4fbSHaiyue Wang 			memcpy(rss_cfg, &rss->cfg_msg, len);
18650aaeb4fbSHaiyue Wang 			break;
18660aaeb4fbSHaiyue Wang 		}
18670aaeb4fbSHaiyue Wang 	}
18680aaeb4fbSHaiyue Wang 	spin_unlock_bh(&adapter->adv_rss_lock);
18690aaeb4fbSHaiyue Wang 
18700aaeb4fbSHaiyue Wang 	if (process_rss) {
18710aaeb4fbSHaiyue Wang 		adapter->current_op = VIRTCHNL_OP_DEL_RSS_CFG;
18720aaeb4fbSHaiyue Wang 		iavf_send_pf_msg(adapter, VIRTCHNL_OP_DEL_RSS_CFG,
18730aaeb4fbSHaiyue Wang 				 (u8 *)rss_cfg, len);
18740aaeb4fbSHaiyue Wang 	} else {
18750aaeb4fbSHaiyue Wang 		adapter->aq_required &= ~IAVF_FLAG_AQ_DEL_ADV_RSS_CFG;
18760aaeb4fbSHaiyue Wang 	}
18770aaeb4fbSHaiyue Wang 
18780aaeb4fbSHaiyue Wang 	kfree(rss_cfg);
18790aaeb4fbSHaiyue Wang }
18800aaeb4fbSHaiyue Wang 
18810aaeb4fbSHaiyue Wang /**
18825ec8b7d1SJesse Brandeburg  * iavf_request_reset
18835ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
18845ec8b7d1SJesse Brandeburg  *
18855ec8b7d1SJesse Brandeburg  * Request that the PF reset this VF. No response is expected.
18865ec8b7d1SJesse Brandeburg  **/
iavf_request_reset(struct iavf_adapter * adapter)1887bae569d0SMateusz Palczewski int iavf_request_reset(struct iavf_adapter *adapter)
18885ec8b7d1SJesse Brandeburg {
1889bae569d0SMateusz Palczewski 	int err;
18905ec8b7d1SJesse Brandeburg 	/* Don't check CURRENT_OP - this is always higher priority */
1891bae569d0SMateusz Palczewski 	err = iavf_send_pf_msg(adapter, VIRTCHNL_OP_RESET_VF, NULL, 0);
18925ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_UNKNOWN;
1893bae569d0SMateusz Palczewski 	return err;
18945ec8b7d1SJesse Brandeburg }
18955ec8b7d1SJesse Brandeburg 
18965ec8b7d1SJesse Brandeburg /**
18972cf29e55SMichal Maloszewski  * iavf_netdev_features_vlan_strip_set - update vlan strip status
18982cf29e55SMichal Maloszewski  * @netdev: ptr to netdev being adjusted
18992cf29e55SMichal Maloszewski  * @enable: enable or disable vlan strip
19002cf29e55SMichal Maloszewski  *
19012cf29e55SMichal Maloszewski  * Helper function to change vlan strip status in netdev->features.
19022cf29e55SMichal Maloszewski  */
iavf_netdev_features_vlan_strip_set(struct net_device * netdev,const bool enable)19032cf29e55SMichal Maloszewski static void iavf_netdev_features_vlan_strip_set(struct net_device *netdev,
19042cf29e55SMichal Maloszewski 						const bool enable)
19052cf29e55SMichal Maloszewski {
19062cf29e55SMichal Maloszewski 	if (enable)
19072cf29e55SMichal Maloszewski 		netdev->features |= NETIF_F_HW_VLAN_CTAG_RX;
19082cf29e55SMichal Maloszewski 	else
19092cf29e55SMichal Maloszewski 		netdev->features &= ~NETIF_F_HW_VLAN_CTAG_RX;
19102cf29e55SMichal Maloszewski }
19112cf29e55SMichal Maloszewski 
19122cf29e55SMichal Maloszewski /**
1913*3beb9d66SPiotr Gardocki  * iavf_activate_fdir_filters - Reactivate all FDIR filters after a reset
1914*3beb9d66SPiotr Gardocki  * @adapter: private adapter structure
1915*3beb9d66SPiotr Gardocki  *
1916*3beb9d66SPiotr Gardocki  * Called after a reset to re-add all FDIR filters and delete some of them
1917*3beb9d66SPiotr Gardocki  * if they were pending to be deleted.
1918*3beb9d66SPiotr Gardocki  */
iavf_activate_fdir_filters(struct iavf_adapter * adapter)1919*3beb9d66SPiotr Gardocki static void iavf_activate_fdir_filters(struct iavf_adapter *adapter)
1920*3beb9d66SPiotr Gardocki {
1921*3beb9d66SPiotr Gardocki 	struct iavf_fdir_fltr *f, *ftmp;
1922*3beb9d66SPiotr Gardocki 	bool add_filters = false;
1923*3beb9d66SPiotr Gardocki 
1924*3beb9d66SPiotr Gardocki 	spin_lock_bh(&adapter->fdir_fltr_lock);
1925*3beb9d66SPiotr Gardocki 	list_for_each_entry_safe(f, ftmp, &adapter->fdir_list_head, list) {
1926*3beb9d66SPiotr Gardocki 		if (f->state == IAVF_FDIR_FLTR_ADD_REQUEST ||
1927*3beb9d66SPiotr Gardocki 		    f->state == IAVF_FDIR_FLTR_ADD_PENDING ||
1928*3beb9d66SPiotr Gardocki 		    f->state == IAVF_FDIR_FLTR_ACTIVE) {
1929*3beb9d66SPiotr Gardocki 			/* All filters and requests have been removed in PF,
1930*3beb9d66SPiotr Gardocki 			 * restore them
1931*3beb9d66SPiotr Gardocki 			 */
1932*3beb9d66SPiotr Gardocki 			f->state = IAVF_FDIR_FLTR_ADD_REQUEST;
1933*3beb9d66SPiotr Gardocki 			add_filters = true;
1934*3beb9d66SPiotr Gardocki 		} else if (f->state == IAVF_FDIR_FLTR_DIS_REQUEST ||
1935*3beb9d66SPiotr Gardocki 			   f->state == IAVF_FDIR_FLTR_DIS_PENDING) {
1936*3beb9d66SPiotr Gardocki 			/* Link down state, leave filters as inactive */
1937*3beb9d66SPiotr Gardocki 			f->state = IAVF_FDIR_FLTR_INACTIVE;
1938*3beb9d66SPiotr Gardocki 		} else if (f->state == IAVF_FDIR_FLTR_DEL_REQUEST ||
1939*3beb9d66SPiotr Gardocki 			   f->state == IAVF_FDIR_FLTR_DEL_PENDING) {
1940*3beb9d66SPiotr Gardocki 			/* Delete filters that were pending to be deleted, the
1941*3beb9d66SPiotr Gardocki 			 * list on PF is already cleared after a reset
1942*3beb9d66SPiotr Gardocki 			 */
1943*3beb9d66SPiotr Gardocki 			list_del(&f->list);
1944*3beb9d66SPiotr Gardocki 			kfree(f);
1945*3beb9d66SPiotr Gardocki 			adapter->fdir_active_fltr--;
1946*3beb9d66SPiotr Gardocki 		}
1947*3beb9d66SPiotr Gardocki 	}
1948*3beb9d66SPiotr Gardocki 	spin_unlock_bh(&adapter->fdir_fltr_lock);
1949*3beb9d66SPiotr Gardocki 
1950*3beb9d66SPiotr Gardocki 	if (add_filters)
1951*3beb9d66SPiotr Gardocki 		adapter->aq_required |= IAVF_FLAG_AQ_ADD_FDIR_FILTER;
1952*3beb9d66SPiotr Gardocki }
1953*3beb9d66SPiotr Gardocki 
1954*3beb9d66SPiotr Gardocki /**
19555ec8b7d1SJesse Brandeburg  * iavf_virtchnl_completion
19565ec8b7d1SJesse Brandeburg  * @adapter: adapter structure
19575ec8b7d1SJesse Brandeburg  * @v_opcode: opcode sent by PF
19585ec8b7d1SJesse Brandeburg  * @v_retval: retval sent by PF
19595ec8b7d1SJesse Brandeburg  * @msg: message sent by PF
19605ec8b7d1SJesse Brandeburg  * @msglen: message length
19615ec8b7d1SJesse Brandeburg  *
19625ec8b7d1SJesse Brandeburg  * Asynchronous completion function for admin queue messages. Rather than busy
19635ec8b7d1SJesse Brandeburg  * wait, we fire off our requests and assume that no errors will be returned.
19645ec8b7d1SJesse Brandeburg  * This function handles the reply messages.
19655ec8b7d1SJesse Brandeburg  **/
iavf_virtchnl_completion(struct iavf_adapter * adapter,enum virtchnl_ops v_opcode,enum iavf_status v_retval,u8 * msg,u16 msglen)19665ec8b7d1SJesse Brandeburg void iavf_virtchnl_completion(struct iavf_adapter *adapter,
196780754bbcSSergey Nemov 			      enum virtchnl_ops v_opcode,
196880754bbcSSergey Nemov 			      enum iavf_status v_retval, u8 *msg, u16 msglen)
19695ec8b7d1SJesse Brandeburg {
19705ec8b7d1SJesse Brandeburg 	struct net_device *netdev = adapter->netdev;
19715ec8b7d1SJesse Brandeburg 
19725ec8b7d1SJesse Brandeburg 	if (v_opcode == VIRTCHNL_OP_EVENT) {
19735ec8b7d1SJesse Brandeburg 		struct virtchnl_pf_event *vpe =
19745ec8b7d1SJesse Brandeburg 			(struct virtchnl_pf_event *)msg;
1975e0ef26fbSBrett Creeley 		bool link_up = iavf_get_vpe_link_status(adapter, vpe);
19765ec8b7d1SJesse Brandeburg 
19775ec8b7d1SJesse Brandeburg 		switch (vpe->event) {
19785ec8b7d1SJesse Brandeburg 		case VIRTCHNL_EVENT_LINK_CHANGE:
1979e0ef26fbSBrett Creeley 			iavf_set_adapter_link_speed_from_vpe(adapter, vpe);
19805ec8b7d1SJesse Brandeburg 
19815ec8b7d1SJesse Brandeburg 			/* we've already got the right link status, bail */
19825ec8b7d1SJesse Brandeburg 			if (adapter->link_up == link_up)
19835ec8b7d1SJesse Brandeburg 				break;
19845ec8b7d1SJesse Brandeburg 
19855ec8b7d1SJesse Brandeburg 			if (link_up) {
19865ec8b7d1SJesse Brandeburg 				/* If we get link up message and start queues
19875ec8b7d1SJesse Brandeburg 				 * before our queues are configured it will
19885ec8b7d1SJesse Brandeburg 				 * trigger a TX hang. In that case, just ignore
19895ec8b7d1SJesse Brandeburg 				 * the link status message,we'll get another one
19905ec8b7d1SJesse Brandeburg 				 * after we enable queues and actually prepared
19915ec8b7d1SJesse Brandeburg 				 * to send traffic.
19925ec8b7d1SJesse Brandeburg 				 */
19935ec8b7d1SJesse Brandeburg 				if (adapter->state != __IAVF_RUNNING)
19945ec8b7d1SJesse Brandeburg 					break;
19955ec8b7d1SJesse Brandeburg 
19965ec8b7d1SJesse Brandeburg 				/* For ADq enabled VF, we reconfigure VSIs and
19975ec8b7d1SJesse Brandeburg 				 * re-allocate queues. Hence wait till all
19985ec8b7d1SJesse Brandeburg 				 * queues are enabled.
19995ec8b7d1SJesse Brandeburg 				 */
20005ec8b7d1SJesse Brandeburg 				if (adapter->flags &
20015ec8b7d1SJesse Brandeburg 				    IAVF_FLAG_QUEUES_DISABLED)
20025ec8b7d1SJesse Brandeburg 					break;
20035ec8b7d1SJesse Brandeburg 			}
20045ec8b7d1SJesse Brandeburg 
20055ec8b7d1SJesse Brandeburg 			adapter->link_up = link_up;
20065ec8b7d1SJesse Brandeburg 			if (link_up) {
20075ec8b7d1SJesse Brandeburg 				netif_tx_start_all_queues(netdev);
20085ec8b7d1SJesse Brandeburg 				netif_carrier_on(netdev);
20095ec8b7d1SJesse Brandeburg 			} else {
20105ec8b7d1SJesse Brandeburg 				netif_tx_stop_all_queues(netdev);
20115ec8b7d1SJesse Brandeburg 				netif_carrier_off(netdev);
20125ec8b7d1SJesse Brandeburg 			}
20135ec8b7d1SJesse Brandeburg 			iavf_print_link_message(adapter);
20145ec8b7d1SJesse Brandeburg 			break;
20155ec8b7d1SJesse Brandeburg 		case VIRTCHNL_EVENT_RESET_IMPENDING:
2016fbe66f57SKaren Sornek 			dev_info(&adapter->pdev->dev, "Reset indication received from the PF\n");
20175ec8b7d1SJesse Brandeburg 			if (!(adapter->flags & IAVF_FLAG_RESET_PENDING)) {
20185ec8b7d1SJesse Brandeburg 				dev_info(&adapter->pdev->dev, "Scheduling reset task\n");
2019c34743daSAhmed Zaki 				iavf_schedule_reset(adapter, IAVF_FLAG_RESET_PENDING);
20205ec8b7d1SJesse Brandeburg 			}
20215ec8b7d1SJesse Brandeburg 			break;
20225ec8b7d1SJesse Brandeburg 		default:
20235ec8b7d1SJesse Brandeburg 			dev_err(&adapter->pdev->dev, "Unknown event %d from PF\n",
20245ec8b7d1SJesse Brandeburg 				vpe->event);
20255ec8b7d1SJesse Brandeburg 			break;
20265ec8b7d1SJesse Brandeburg 		}
20275ec8b7d1SJesse Brandeburg 		return;
20285ec8b7d1SJesse Brandeburg 	}
20295ec8b7d1SJesse Brandeburg 	if (v_retval) {
20305ec8b7d1SJesse Brandeburg 		switch (v_opcode) {
20315ec8b7d1SJesse Brandeburg 		case VIRTCHNL_OP_ADD_VLAN:
20325ec8b7d1SJesse Brandeburg 			dev_err(&adapter->pdev->dev, "Failed to add VLAN filter, error %s\n",
20335ec8b7d1SJesse Brandeburg 				iavf_stat_str(&adapter->hw, v_retval));
20345ec8b7d1SJesse Brandeburg 			break;
20355ec8b7d1SJesse Brandeburg 		case VIRTCHNL_OP_ADD_ETH_ADDR:
20365ec8b7d1SJesse Brandeburg 			dev_err(&adapter->pdev->dev, "Failed to add MAC filter, error %s\n",
20375ec8b7d1SJesse Brandeburg 				iavf_stat_str(&adapter->hw, v_retval));
20388da80c9dSSylwester Dziedziuch 			iavf_mac_add_reject(adapter);
2039c5c922b3SStefan Assmann 			/* restore administratively set MAC address */
2040c5c922b3SStefan Assmann 			ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr);
204135a2443dSMateusz Palczewski 			wake_up(&adapter->vc_waitqueue);
20425ec8b7d1SJesse Brandeburg 			break;
20435ec8b7d1SJesse Brandeburg 		case VIRTCHNL_OP_DEL_VLAN:
20445ec8b7d1SJesse Brandeburg 			dev_err(&adapter->pdev->dev, "Failed to delete VLAN filter, error %s\n",
20455ec8b7d1SJesse Brandeburg 				iavf_stat_str(&adapter->hw, v_retval));
20465ec8b7d1SJesse Brandeburg 			break;
20475ec8b7d1SJesse Brandeburg 		case VIRTCHNL_OP_DEL_ETH_ADDR:
20485ec8b7d1SJesse Brandeburg 			dev_err(&adapter->pdev->dev, "Failed to delete MAC filter, error %s\n",
20495ec8b7d1SJesse Brandeburg 				iavf_stat_str(&adapter->hw, v_retval));
20505ec8b7d1SJesse Brandeburg 			break;
20515ec8b7d1SJesse Brandeburg 		case VIRTCHNL_OP_ENABLE_CHANNELS:
20525ec8b7d1SJesse Brandeburg 			dev_err(&adapter->pdev->dev, "Failed to configure queue channels, error %s\n",
20535ec8b7d1SJesse Brandeburg 				iavf_stat_str(&adapter->hw, v_retval));
20545ec8b7d1SJesse Brandeburg 			adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
20555ec8b7d1SJesse Brandeburg 			adapter->ch_config.state = __IAVF_TC_INVALID;
20565ec8b7d1SJesse Brandeburg 			netdev_reset_tc(netdev);
20575ec8b7d1SJesse Brandeburg 			netif_tx_start_all_queues(netdev);
20585ec8b7d1SJesse Brandeburg 			break;
20595ec8b7d1SJesse Brandeburg 		case VIRTCHNL_OP_DISABLE_CHANNELS:
20605ec8b7d1SJesse Brandeburg 			dev_err(&adapter->pdev->dev, "Failed to disable queue channels, error %s\n",
20615ec8b7d1SJesse Brandeburg 				iavf_stat_str(&adapter->hw, v_retval));
20625ec8b7d1SJesse Brandeburg 			adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
20635ec8b7d1SJesse Brandeburg 			adapter->ch_config.state = __IAVF_TC_RUNNING;
20645ec8b7d1SJesse Brandeburg 			netif_tx_start_all_queues(netdev);
20655ec8b7d1SJesse Brandeburg 			break;
20665ec8b7d1SJesse Brandeburg 		case VIRTCHNL_OP_ADD_CLOUD_FILTER: {
20675ec8b7d1SJesse Brandeburg 			struct iavf_cloud_filter *cf, *cftmp;
20685ec8b7d1SJesse Brandeburg 
20695ec8b7d1SJesse Brandeburg 			list_for_each_entry_safe(cf, cftmp,
20705ec8b7d1SJesse Brandeburg 						 &adapter->cloud_filter_list,
20715ec8b7d1SJesse Brandeburg 						 list) {
20725ec8b7d1SJesse Brandeburg 				if (cf->state == __IAVF_CF_ADD_PENDING) {
20735ec8b7d1SJesse Brandeburg 					cf->state = __IAVF_CF_INVALID;
20745ec8b7d1SJesse Brandeburg 					dev_info(&adapter->pdev->dev, "Failed to add cloud filter, error %s\n",
20755ec8b7d1SJesse Brandeburg 						 iavf_stat_str(&adapter->hw,
20765ec8b7d1SJesse Brandeburg 							       v_retval));
20775ec8b7d1SJesse Brandeburg 					iavf_print_cloud_filter(adapter,
20785ec8b7d1SJesse Brandeburg 								&cf->f);
20795ec8b7d1SJesse Brandeburg 					list_del(&cf->list);
20805ec8b7d1SJesse Brandeburg 					kfree(cf);
20815ec8b7d1SJesse Brandeburg 					adapter->num_cloud_filters--;
20825ec8b7d1SJesse Brandeburg 				}
20835ec8b7d1SJesse Brandeburg 			}
20845ec8b7d1SJesse Brandeburg 			}
20855ec8b7d1SJesse Brandeburg 			break;
20865ec8b7d1SJesse Brandeburg 		case VIRTCHNL_OP_DEL_CLOUD_FILTER: {
20875ec8b7d1SJesse Brandeburg 			struct iavf_cloud_filter *cf;
20885ec8b7d1SJesse Brandeburg 
20895ec8b7d1SJesse Brandeburg 			list_for_each_entry(cf, &adapter->cloud_filter_list,
20905ec8b7d1SJesse Brandeburg 					    list) {
20915ec8b7d1SJesse Brandeburg 				if (cf->state == __IAVF_CF_DEL_PENDING) {
20925ec8b7d1SJesse Brandeburg 					cf->state = __IAVF_CF_ACTIVE;
20935ec8b7d1SJesse Brandeburg 					dev_info(&adapter->pdev->dev, "Failed to del cloud filter, error %s\n",
20945ec8b7d1SJesse Brandeburg 						 iavf_stat_str(&adapter->hw,
20955ec8b7d1SJesse Brandeburg 							       v_retval));
20965ec8b7d1SJesse Brandeburg 					iavf_print_cloud_filter(adapter,
20975ec8b7d1SJesse Brandeburg 								&cf->f);
20985ec8b7d1SJesse Brandeburg 				}
20995ec8b7d1SJesse Brandeburg 			}
21005ec8b7d1SJesse Brandeburg 			}
21015ec8b7d1SJesse Brandeburg 			break;
21020dbfbabbSHaiyue Wang 		case VIRTCHNL_OP_ADD_FDIR_FILTER: {
21030dbfbabbSHaiyue Wang 			struct iavf_fdir_fltr *fdir, *fdir_tmp;
21040dbfbabbSHaiyue Wang 
21050dbfbabbSHaiyue Wang 			spin_lock_bh(&adapter->fdir_fltr_lock);
21060dbfbabbSHaiyue Wang 			list_for_each_entry_safe(fdir, fdir_tmp,
21070dbfbabbSHaiyue Wang 						 &adapter->fdir_list_head,
21080dbfbabbSHaiyue Wang 						 list) {
21090dbfbabbSHaiyue Wang 				if (fdir->state == IAVF_FDIR_FLTR_ADD_PENDING) {
21100dbfbabbSHaiyue Wang 					dev_info(&adapter->pdev->dev, "Failed to add Flow Director filter, error %s\n",
21110dbfbabbSHaiyue Wang 						 iavf_stat_str(&adapter->hw,
21120dbfbabbSHaiyue Wang 							       v_retval));
2113527691bfSHaiyue Wang 					iavf_print_fdir_fltr(adapter, fdir);
21140dbfbabbSHaiyue Wang 					if (msglen)
21150dbfbabbSHaiyue Wang 						dev_err(&adapter->pdev->dev,
21160dbfbabbSHaiyue Wang 							"%s\n", msg);
21170dbfbabbSHaiyue Wang 					list_del(&fdir->list);
21180dbfbabbSHaiyue Wang 					kfree(fdir);
21190dbfbabbSHaiyue Wang 					adapter->fdir_active_fltr--;
21200dbfbabbSHaiyue Wang 				}
21210dbfbabbSHaiyue Wang 			}
21220dbfbabbSHaiyue Wang 			spin_unlock_bh(&adapter->fdir_fltr_lock);
21230dbfbabbSHaiyue Wang 			}
21240dbfbabbSHaiyue Wang 			break;
21250dbfbabbSHaiyue Wang 		case VIRTCHNL_OP_DEL_FDIR_FILTER: {
21260dbfbabbSHaiyue Wang 			struct iavf_fdir_fltr *fdir;
21270dbfbabbSHaiyue Wang 
21280dbfbabbSHaiyue Wang 			spin_lock_bh(&adapter->fdir_fltr_lock);
21290dbfbabbSHaiyue Wang 			list_for_each_entry(fdir, &adapter->fdir_list_head,
21300dbfbabbSHaiyue Wang 					    list) {
2131*3beb9d66SPiotr Gardocki 				if (fdir->state == IAVF_FDIR_FLTR_DEL_PENDING ||
2132*3beb9d66SPiotr Gardocki 				    fdir->state == IAVF_FDIR_FLTR_DIS_PENDING) {
21330dbfbabbSHaiyue Wang 					fdir->state = IAVF_FDIR_FLTR_ACTIVE;
21340dbfbabbSHaiyue Wang 					dev_info(&adapter->pdev->dev, "Failed to del Flow Director filter, error %s\n",
21350dbfbabbSHaiyue Wang 						 iavf_stat_str(&adapter->hw,
21360dbfbabbSHaiyue Wang 							       v_retval));
2137527691bfSHaiyue Wang 					iavf_print_fdir_fltr(adapter, fdir);
21380dbfbabbSHaiyue Wang 				}
21390dbfbabbSHaiyue Wang 			}
21400dbfbabbSHaiyue Wang 			spin_unlock_bh(&adapter->fdir_fltr_lock);
21410dbfbabbSHaiyue Wang 			}
21420dbfbabbSHaiyue Wang 			break;
21430aaeb4fbSHaiyue Wang 		case VIRTCHNL_OP_ADD_RSS_CFG: {
21440aaeb4fbSHaiyue Wang 			struct iavf_adv_rss *rss, *rss_tmp;
21450aaeb4fbSHaiyue Wang 
21460aaeb4fbSHaiyue Wang 			spin_lock_bh(&adapter->adv_rss_lock);
21470aaeb4fbSHaiyue Wang 			list_for_each_entry_safe(rss, rss_tmp,
21480aaeb4fbSHaiyue Wang 						 &adapter->adv_rss_list_head,
21490aaeb4fbSHaiyue Wang 						 list) {
21500aaeb4fbSHaiyue Wang 				if (rss->state == IAVF_ADV_RSS_ADD_PENDING) {
21515ab91e05SHaiyue Wang 					iavf_print_adv_rss_cfg(adapter, rss,
21525ab91e05SHaiyue Wang 							       "Failed to change the input set for",
21535ab91e05SHaiyue Wang 							       NULL);
21540aaeb4fbSHaiyue Wang 					list_del(&rss->list);
21550aaeb4fbSHaiyue Wang 					kfree(rss);
21560aaeb4fbSHaiyue Wang 				}
21570aaeb4fbSHaiyue Wang 			}
21580aaeb4fbSHaiyue Wang 			spin_unlock_bh(&adapter->adv_rss_lock);
21590aaeb4fbSHaiyue Wang 			}
21600aaeb4fbSHaiyue Wang 			break;
21610aaeb4fbSHaiyue Wang 		case VIRTCHNL_OP_DEL_RSS_CFG: {
21620aaeb4fbSHaiyue Wang 			struct iavf_adv_rss *rss;
21630aaeb4fbSHaiyue Wang 
21640aaeb4fbSHaiyue Wang 			spin_lock_bh(&adapter->adv_rss_lock);
21650aaeb4fbSHaiyue Wang 			list_for_each_entry(rss, &adapter->adv_rss_list_head,
21660aaeb4fbSHaiyue Wang 					    list) {
21670aaeb4fbSHaiyue Wang 				if (rss->state == IAVF_ADV_RSS_DEL_PENDING) {
21680aaeb4fbSHaiyue Wang 					rss->state = IAVF_ADV_RSS_ACTIVE;
21690aaeb4fbSHaiyue Wang 					dev_err(&adapter->pdev->dev, "Failed to delete RSS configuration, error %s\n",
21700aaeb4fbSHaiyue Wang 						iavf_stat_str(&adapter->hw,
21710aaeb4fbSHaiyue Wang 							      v_retval));
21720aaeb4fbSHaiyue Wang 				}
21730aaeb4fbSHaiyue Wang 			}
21740aaeb4fbSHaiyue Wang 			spin_unlock_bh(&adapter->adv_rss_lock);
21750aaeb4fbSHaiyue Wang 			}
21760aaeb4fbSHaiyue Wang 			break;
21770dbfbabbSHaiyue Wang 		case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING:
21782cf29e55SMichal Maloszewski 			dev_warn(&adapter->pdev->dev, "Changing VLAN Stripping is not allowed when Port VLAN is configured\n");
21792cf29e55SMichal Maloszewski 			/* Vlan stripping could not be enabled by ethtool.
21802cf29e55SMichal Maloszewski 			 * Disable it in netdev->features.
21812cf29e55SMichal Maloszewski 			 */
21822cf29e55SMichal Maloszewski 			iavf_netdev_features_vlan_strip_set(netdev, false);
21832cf29e55SMichal Maloszewski 			break;
21840dbfbabbSHaiyue Wang 		case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING:
21850dbfbabbSHaiyue Wang 			dev_warn(&adapter->pdev->dev, "Changing VLAN Stripping is not allowed when Port VLAN is configured\n");
21862cf29e55SMichal Maloszewski 			/* Vlan stripping could not be disabled by ethtool.
21872cf29e55SMichal Maloszewski 			 * Enable it in netdev->features.
21882cf29e55SMichal Maloszewski 			 */
21892cf29e55SMichal Maloszewski 			iavf_netdev_features_vlan_strip_set(netdev, true);
21900dbfbabbSHaiyue Wang 			break;
2191968996c0SPrzemyslaw Patynowski 		case VIRTCHNL_OP_ADD_VLAN_V2:
2192968996c0SPrzemyslaw Patynowski 			iavf_vlan_add_reject(adapter);
2193968996c0SPrzemyslaw Patynowski 			dev_warn(&adapter->pdev->dev, "Failed to add VLAN filter, error %s\n",
2194968996c0SPrzemyslaw Patynowski 				 iavf_stat_str(&adapter->hw, v_retval));
2195968996c0SPrzemyslaw Patynowski 			break;
21965ec8b7d1SJesse Brandeburg 		default:
21975ec8b7d1SJesse Brandeburg 			dev_err(&adapter->pdev->dev, "PF returned error %d (%s) to our request %d\n",
21985ec8b7d1SJesse Brandeburg 				v_retval, iavf_stat_str(&adapter->hw, v_retval),
21995ec8b7d1SJesse Brandeburg 				v_opcode);
22005ec8b7d1SJesse Brandeburg 		}
22015ec8b7d1SJesse Brandeburg 	}
22025ec8b7d1SJesse Brandeburg 	switch (v_opcode) {
22038da80c9dSSylwester Dziedziuch 	case VIRTCHNL_OP_ADD_ETH_ADDR:
22048da80c9dSSylwester Dziedziuch 		if (!v_retval)
22058da80c9dSSylwester Dziedziuch 			iavf_mac_add_ok(adapter);
2206c5c922b3SStefan Assmann 		if (!ether_addr_equal(netdev->dev_addr, adapter->hw.mac.addr))
220735a2443dSMateusz Palczewski 			if (!ether_addr_equal(netdev->dev_addr,
220835a2443dSMateusz Palczewski 					      adapter->hw.mac.addr)) {
220935a2443dSMateusz Palczewski 				netif_addr_lock_bh(netdev);
2210f3956ebbSJakub Kicinski 				eth_hw_addr_set(netdev, adapter->hw.mac.addr);
221135a2443dSMateusz Palczewski 				netif_addr_unlock_bh(netdev);
221235a2443dSMateusz Palczewski 			}
221335a2443dSMateusz Palczewski 		wake_up(&adapter->vc_waitqueue);
2214c5c922b3SStefan Assmann 		break;
22155ec8b7d1SJesse Brandeburg 	case VIRTCHNL_OP_GET_STATS: {
221656184e01SJesse Brandeburg 		struct iavf_eth_stats *stats =
221756184e01SJesse Brandeburg 			(struct iavf_eth_stats *)msg;
22185ec8b7d1SJesse Brandeburg 		netdev->stats.rx_packets = stats->rx_unicast +
22195ec8b7d1SJesse Brandeburg 					   stats->rx_multicast +
22205ec8b7d1SJesse Brandeburg 					   stats->rx_broadcast;
22215ec8b7d1SJesse Brandeburg 		netdev->stats.tx_packets = stats->tx_unicast +
22225ec8b7d1SJesse Brandeburg 					   stats->tx_multicast +
22235ec8b7d1SJesse Brandeburg 					   stats->tx_broadcast;
22245ec8b7d1SJesse Brandeburg 		netdev->stats.rx_bytes = stats->rx_bytes;
22255ec8b7d1SJesse Brandeburg 		netdev->stats.tx_bytes = stats->tx_bytes;
22265ec8b7d1SJesse Brandeburg 		netdev->stats.tx_errors = stats->tx_errors;
22275ec8b7d1SJesse Brandeburg 		netdev->stats.rx_dropped = stats->rx_discards;
22285ec8b7d1SJesse Brandeburg 		netdev->stats.tx_dropped = stats->tx_discards;
22295ec8b7d1SJesse Brandeburg 		adapter->current_stats = *stats;
22305ec8b7d1SJesse Brandeburg 		}
22315ec8b7d1SJesse Brandeburg 		break;
22325ec8b7d1SJesse Brandeburg 	case VIRTCHNL_OP_GET_VF_RESOURCES: {
22335e7f59faSAlexander Lobakin 		u16 len = IAVF_VIRTCHNL_VF_RESOURCE_SIZE;
22345e7f59faSAlexander Lobakin 
22355ec8b7d1SJesse Brandeburg 		memcpy(adapter->vf_res, msg, min(msglen, len));
22365ec8b7d1SJesse Brandeburg 		iavf_validate_num_queues(adapter);
22375ec8b7d1SJesse Brandeburg 		iavf_vf_parse_hw_config(&adapter->hw, adapter->vf_res);
22385ec8b7d1SJesse Brandeburg 		if (is_zero_ether_addr(adapter->hw.mac.addr)) {
22395ec8b7d1SJesse Brandeburg 			/* restore current mac address */
22405ec8b7d1SJesse Brandeburg 			ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr);
22415ec8b7d1SJesse Brandeburg 		} else {
224235a2443dSMateusz Palczewski 			netif_addr_lock_bh(netdev);
22435ec8b7d1SJesse Brandeburg 			/* refresh current mac address if changed */
22445ec8b7d1SJesse Brandeburg 			ether_addr_copy(netdev->perm_addr,
22455ec8b7d1SJesse Brandeburg 					adapter->hw.mac.addr);
224635a2443dSMateusz Palczewski 			netif_addr_unlock_bh(netdev);
22475ec8b7d1SJesse Brandeburg 		}
22489e052291SStefan Assmann 		spin_lock_bh(&adapter->mac_vlan_list_lock);
22499e052291SStefan Assmann 		iavf_add_filter(adapter, adapter->hw.mac.addr);
22505951a2b9SBrett Creeley 
22515951a2b9SBrett Creeley 		if (VLAN_ALLOWED(adapter)) {
22525951a2b9SBrett Creeley 			if (!list_empty(&adapter->vlan_filter_list)) {
22535951a2b9SBrett Creeley 				struct iavf_vlan_filter *vlf;
22545951a2b9SBrett Creeley 
22555951a2b9SBrett Creeley 				/* re-add all VLAN filters over virtchnl */
22565951a2b9SBrett Creeley 				list_for_each_entry(vlf,
22575951a2b9SBrett Creeley 						    &adapter->vlan_filter_list,
22585951a2b9SBrett Creeley 						    list)
22590c0da0e9SAhmed Zaki 					vlf->state = IAVF_VLAN_ADD;
22605951a2b9SBrett Creeley 
22615951a2b9SBrett Creeley 				adapter->aq_required |=
22625951a2b9SBrett Creeley 					IAVF_FLAG_AQ_ADD_VLAN_FILTER;
22635951a2b9SBrett Creeley 			}
22645951a2b9SBrett Creeley 		}
22655951a2b9SBrett Creeley 
22669e052291SStefan Assmann 		spin_unlock_bh(&adapter->mac_vlan_list_lock);
2267209f2f9cSBrett Creeley 
2268*3beb9d66SPiotr Gardocki 		iavf_activate_fdir_filters(adapter);
2269*3beb9d66SPiotr Gardocki 
2270209f2f9cSBrett Creeley 		iavf_parse_vf_resource_msg(adapter);
2271209f2f9cSBrett Creeley 
2272209f2f9cSBrett Creeley 		/* negotiated VIRTCHNL_VF_OFFLOAD_VLAN_V2, so wait for the
2273209f2f9cSBrett Creeley 		 * response to VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS to finish
2274209f2f9cSBrett Creeley 		 * configuration
2275209f2f9cSBrett Creeley 		 */
2276209f2f9cSBrett Creeley 		if (VLAN_V2_ALLOWED(adapter))
2277209f2f9cSBrett Creeley 			break;
2278209f2f9cSBrett Creeley 		/* fallthrough and finish config if VIRTCHNL_VF_OFFLOAD_VLAN_V2
2279209f2f9cSBrett Creeley 		 * wasn't successfully negotiated with the PF
2280209f2f9cSBrett Creeley 		 */
2281209f2f9cSBrett Creeley 		}
2282209f2f9cSBrett Creeley 		fallthrough;
2283209f2f9cSBrett Creeley 	case VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS: {
228435a2443dSMateusz Palczewski 		struct iavf_mac_filter *f;
228535a2443dSMateusz Palczewski 		bool was_mac_changed;
228635a2443dSMateusz Palczewski 		u64 aq_required = 0;
228735a2443dSMateusz Palczewski 
2288209f2f9cSBrett Creeley 		if (v_opcode == VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS)
2289209f2f9cSBrett Creeley 			memcpy(&adapter->vlan_v2_caps, msg,
2290209f2f9cSBrett Creeley 			       min_t(u16, msglen,
2291209f2f9cSBrett Creeley 				     sizeof(adapter->vlan_v2_caps)));
2292209f2f9cSBrett Creeley 
22935ec8b7d1SJesse Brandeburg 		iavf_process_config(adapter);
22940579fafdSSlawomir Laba 		adapter->flags |= IAVF_FLAG_SETUP_NETDEV_FEATURES;
2295d1639a17SAhmed Zaki 		iavf_schedule_finish_config(adapter);
22967598f4b4SMarcin Szycik 
22977598f4b4SMarcin Szycik 		iavf_set_queue_vlan_tag_loc(adapter);
22987598f4b4SMarcin Szycik 
229935a2443dSMateusz Palczewski 		was_mac_changed = !ether_addr_equal(netdev->dev_addr,
230035a2443dSMateusz Palczewski 						    adapter->hw.mac.addr);
230135a2443dSMateusz Palczewski 
230235a2443dSMateusz Palczewski 		spin_lock_bh(&adapter->mac_vlan_list_lock);
230335a2443dSMateusz Palczewski 
230435a2443dSMateusz Palczewski 		/* re-add all MAC filters */
230535a2443dSMateusz Palczewski 		list_for_each_entry(f, &adapter->mac_filter_list, list) {
230635a2443dSMateusz Palczewski 			if (was_mac_changed &&
230735a2443dSMateusz Palczewski 			    ether_addr_equal(netdev->dev_addr, f->macaddr))
230835a2443dSMateusz Palczewski 				ether_addr_copy(f->macaddr,
230935a2443dSMateusz Palczewski 						adapter->hw.mac.addr);
231035a2443dSMateusz Palczewski 
231135a2443dSMateusz Palczewski 			f->is_new_mac = true;
231235a2443dSMateusz Palczewski 			f->add = true;
231335a2443dSMateusz Palczewski 			f->add_handled = false;
231435a2443dSMateusz Palczewski 			f->remove = false;
231535a2443dSMateusz Palczewski 		}
231635a2443dSMateusz Palczewski 
231735a2443dSMateusz Palczewski 		/* re-add all VLAN filters */
231835a2443dSMateusz Palczewski 		if (VLAN_FILTERING_ALLOWED(adapter)) {
231935a2443dSMateusz Palczewski 			struct iavf_vlan_filter *vlf;
232035a2443dSMateusz Palczewski 
232135a2443dSMateusz Palczewski 			if (!list_empty(&adapter->vlan_filter_list)) {
232235a2443dSMateusz Palczewski 				list_for_each_entry(vlf,
232335a2443dSMateusz Palczewski 						    &adapter->vlan_filter_list,
232435a2443dSMateusz Palczewski 						    list)
23250c0da0e9SAhmed Zaki 					vlf->state = IAVF_VLAN_ADD;
232635a2443dSMateusz Palczewski 
232735a2443dSMateusz Palczewski 				aq_required |= IAVF_FLAG_AQ_ADD_VLAN_FILTER;
232835a2443dSMateusz Palczewski 			}
232935a2443dSMateusz Palczewski 		}
233035a2443dSMateusz Palczewski 
233135a2443dSMateusz Palczewski 		spin_unlock_bh(&adapter->mac_vlan_list_lock);
233235a2443dSMateusz Palczewski 
233335a2443dSMateusz Palczewski 		netif_addr_lock_bh(netdev);
233435a2443dSMateusz Palczewski 		eth_hw_addr_set(netdev, adapter->hw.mac.addr);
233535a2443dSMateusz Palczewski 		netif_addr_unlock_bh(netdev);
233635a2443dSMateusz Palczewski 
233735a2443dSMateusz Palczewski 		adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER |
233835a2443dSMateusz Palczewski 			aq_required;
23395ec8b7d1SJesse Brandeburg 		}
23405ec8b7d1SJesse Brandeburg 		break;
23415ec8b7d1SJesse Brandeburg 	case VIRTCHNL_OP_ENABLE_QUEUES:
23425ec8b7d1SJesse Brandeburg 		/* enable transmits */
23435ec8b7d1SJesse Brandeburg 		iavf_irq_enable(adapter, true);
2344c2ed2403SMarcin Szycik 		wake_up(&adapter->reset_waitqueue);
23455ec8b7d1SJesse Brandeburg 		adapter->flags &= ~IAVF_FLAG_QUEUES_DISABLED;
23465ec8b7d1SJesse Brandeburg 		break;
23475ec8b7d1SJesse Brandeburg 	case VIRTCHNL_OP_DISABLE_QUEUES:
23485ec8b7d1SJesse Brandeburg 		iavf_free_all_tx_resources(adapter);
23495ec8b7d1SJesse Brandeburg 		iavf_free_all_rx_resources(adapter);
23505ec8b7d1SJesse Brandeburg 		if (adapter->state == __IAVF_DOWN_PENDING) {
235145eebd62SMateusz Palczewski 			iavf_change_state(adapter, __IAVF_DOWN);
23525ec8b7d1SJesse Brandeburg 			wake_up(&adapter->down_waitqueue);
23535ec8b7d1SJesse Brandeburg 		}
23545ec8b7d1SJesse Brandeburg 		break;
23555ec8b7d1SJesse Brandeburg 	case VIRTCHNL_OP_VERSION:
23565ec8b7d1SJesse Brandeburg 	case VIRTCHNL_OP_CONFIG_IRQ_MAP:
23575ec8b7d1SJesse Brandeburg 		/* Don't display an error if we get these out of sequence.
23585ec8b7d1SJesse Brandeburg 		 * If the firmware needed to get kicked, we'll get these and
23595ec8b7d1SJesse Brandeburg 		 * it's no problem.
23605ec8b7d1SJesse Brandeburg 		 */
23615ec8b7d1SJesse Brandeburg 		if (v_opcode != adapter->current_op)
23625ec8b7d1SJesse Brandeburg 			return;
23635ec8b7d1SJesse Brandeburg 		break;
23642723f3b5SJesse Brandeburg 	case VIRTCHNL_OP_RDMA:
23655ec8b7d1SJesse Brandeburg 		/* Gobble zero-length replies from the PF. They indicate that
23665ec8b7d1SJesse Brandeburg 		 * a previous message was received OK, and the client doesn't
23675ec8b7d1SJesse Brandeburg 		 * care about that.
23685ec8b7d1SJesse Brandeburg 		 */
23695ec8b7d1SJesse Brandeburg 		if (msglen && CLIENT_ENABLED(adapter))
23705ec8b7d1SJesse Brandeburg 			iavf_notify_client_message(&adapter->vsi, msg, msglen);
23715ec8b7d1SJesse Brandeburg 		break;
23725ec8b7d1SJesse Brandeburg 
23732723f3b5SJesse Brandeburg 	case VIRTCHNL_OP_CONFIG_RDMA_IRQ_MAP:
23745ec8b7d1SJesse Brandeburg 		adapter->client_pending &=
23752723f3b5SJesse Brandeburg 				~(BIT(VIRTCHNL_OP_CONFIG_RDMA_IRQ_MAP));
23765ec8b7d1SJesse Brandeburg 		break;
23775ec8b7d1SJesse Brandeburg 	case VIRTCHNL_OP_GET_RSS_HENA_CAPS: {
23785ec8b7d1SJesse Brandeburg 		struct virtchnl_rss_hena *vrh = (struct virtchnl_rss_hena *)msg;
23795ec8b7d1SJesse Brandeburg 
23805ec8b7d1SJesse Brandeburg 		if (msglen == sizeof(*vrh))
23815ec8b7d1SJesse Brandeburg 			adapter->hena = vrh->hena;
23825ec8b7d1SJesse Brandeburg 		else
23835ec8b7d1SJesse Brandeburg 			dev_warn(&adapter->pdev->dev,
23845ec8b7d1SJesse Brandeburg 				 "Invalid message %d from PF\n", v_opcode);
23855ec8b7d1SJesse Brandeburg 		}
23865ec8b7d1SJesse Brandeburg 		break;
23875ec8b7d1SJesse Brandeburg 	case VIRTCHNL_OP_REQUEST_QUEUES: {
23885ec8b7d1SJesse Brandeburg 		struct virtchnl_vf_res_request *vfres =
23895ec8b7d1SJesse Brandeburg 			(struct virtchnl_vf_res_request *)msg;
23905ec8b7d1SJesse Brandeburg 
23915ec8b7d1SJesse Brandeburg 		if (vfres->num_queue_pairs != adapter->num_req_queues) {
23925ec8b7d1SJesse Brandeburg 			dev_info(&adapter->pdev->dev,
23935ec8b7d1SJesse Brandeburg 				 "Requested %d queues, PF can support %d\n",
23945ec8b7d1SJesse Brandeburg 				 adapter->num_req_queues,
23955ec8b7d1SJesse Brandeburg 				 vfres->num_queue_pairs);
23965ec8b7d1SJesse Brandeburg 			adapter->num_req_queues = 0;
23975ec8b7d1SJesse Brandeburg 			adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
23985ec8b7d1SJesse Brandeburg 		}
23995ec8b7d1SJesse Brandeburg 		}
24005ec8b7d1SJesse Brandeburg 		break;
24015ec8b7d1SJesse Brandeburg 	case VIRTCHNL_OP_ADD_CLOUD_FILTER: {
24025ec8b7d1SJesse Brandeburg 		struct iavf_cloud_filter *cf;
24035ec8b7d1SJesse Brandeburg 
24045ec8b7d1SJesse Brandeburg 		list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
24055ec8b7d1SJesse Brandeburg 			if (cf->state == __IAVF_CF_ADD_PENDING)
24065ec8b7d1SJesse Brandeburg 				cf->state = __IAVF_CF_ACTIVE;
24075ec8b7d1SJesse Brandeburg 		}
24085ec8b7d1SJesse Brandeburg 		}
24095ec8b7d1SJesse Brandeburg 		break;
24105ec8b7d1SJesse Brandeburg 	case VIRTCHNL_OP_DEL_CLOUD_FILTER: {
24115ec8b7d1SJesse Brandeburg 		struct iavf_cloud_filter *cf, *cftmp;
24125ec8b7d1SJesse Brandeburg 
24135ec8b7d1SJesse Brandeburg 		list_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list,
24145ec8b7d1SJesse Brandeburg 					 list) {
24155ec8b7d1SJesse Brandeburg 			if (cf->state == __IAVF_CF_DEL_PENDING) {
24165ec8b7d1SJesse Brandeburg 				cf->state = __IAVF_CF_INVALID;
24175ec8b7d1SJesse Brandeburg 				list_del(&cf->list);
24185ec8b7d1SJesse Brandeburg 				kfree(cf);
24195ec8b7d1SJesse Brandeburg 				adapter->num_cloud_filters--;
24205ec8b7d1SJesse Brandeburg 			}
24215ec8b7d1SJesse Brandeburg 		}
24225ec8b7d1SJesse Brandeburg 		}
24235ec8b7d1SJesse Brandeburg 		break;
24240dbfbabbSHaiyue Wang 	case VIRTCHNL_OP_ADD_FDIR_FILTER: {
24250dbfbabbSHaiyue Wang 		struct virtchnl_fdir_add *add_fltr = (struct virtchnl_fdir_add *)msg;
24260dbfbabbSHaiyue Wang 		struct iavf_fdir_fltr *fdir, *fdir_tmp;
24270dbfbabbSHaiyue Wang 
24280dbfbabbSHaiyue Wang 		spin_lock_bh(&adapter->fdir_fltr_lock);
24290dbfbabbSHaiyue Wang 		list_for_each_entry_safe(fdir, fdir_tmp,
24300dbfbabbSHaiyue Wang 					 &adapter->fdir_list_head,
24310dbfbabbSHaiyue Wang 					 list) {
24320dbfbabbSHaiyue Wang 			if (fdir->state == IAVF_FDIR_FLTR_ADD_PENDING) {
24330dbfbabbSHaiyue Wang 				if (add_fltr->status == VIRTCHNL_FDIR_SUCCESS) {
2434527691bfSHaiyue Wang 					dev_info(&adapter->pdev->dev, "Flow Director filter with location %u is added\n",
2435527691bfSHaiyue Wang 						 fdir->loc);
24360dbfbabbSHaiyue Wang 					fdir->state = IAVF_FDIR_FLTR_ACTIVE;
24370dbfbabbSHaiyue Wang 					fdir->flow_id = add_fltr->flow_id;
24380dbfbabbSHaiyue Wang 				} else {
24390dbfbabbSHaiyue Wang 					dev_info(&adapter->pdev->dev, "Failed to add Flow Director filter with status: %d\n",
24400dbfbabbSHaiyue Wang 						 add_fltr->status);
2441527691bfSHaiyue Wang 					iavf_print_fdir_fltr(adapter, fdir);
24420dbfbabbSHaiyue Wang 					list_del(&fdir->list);
24430dbfbabbSHaiyue Wang 					kfree(fdir);
24440dbfbabbSHaiyue Wang 					adapter->fdir_active_fltr--;
24450dbfbabbSHaiyue Wang 				}
24460dbfbabbSHaiyue Wang 			}
24470dbfbabbSHaiyue Wang 		}
24480dbfbabbSHaiyue Wang 		spin_unlock_bh(&adapter->fdir_fltr_lock);
24490dbfbabbSHaiyue Wang 		}
24500dbfbabbSHaiyue Wang 		break;
24510dbfbabbSHaiyue Wang 	case VIRTCHNL_OP_DEL_FDIR_FILTER: {
24520dbfbabbSHaiyue Wang 		struct virtchnl_fdir_del *del_fltr = (struct virtchnl_fdir_del *)msg;
24530dbfbabbSHaiyue Wang 		struct iavf_fdir_fltr *fdir, *fdir_tmp;
24540dbfbabbSHaiyue Wang 
24550dbfbabbSHaiyue Wang 		spin_lock_bh(&adapter->fdir_fltr_lock);
24560dbfbabbSHaiyue Wang 		list_for_each_entry_safe(fdir, fdir_tmp, &adapter->fdir_list_head,
24570dbfbabbSHaiyue Wang 					 list) {
24580dbfbabbSHaiyue Wang 			if (fdir->state == IAVF_FDIR_FLTR_DEL_PENDING) {
2459*3beb9d66SPiotr Gardocki 				if (del_fltr->status == VIRTCHNL_FDIR_SUCCESS ||
2460*3beb9d66SPiotr Gardocki 				    del_fltr->status ==
2461*3beb9d66SPiotr Gardocki 				    VIRTCHNL_FDIR_FAILURE_RULE_NONEXIST) {
2462527691bfSHaiyue Wang 					dev_info(&adapter->pdev->dev, "Flow Director filter with location %u is deleted\n",
2463527691bfSHaiyue Wang 						 fdir->loc);
24640dbfbabbSHaiyue Wang 					list_del(&fdir->list);
24650dbfbabbSHaiyue Wang 					kfree(fdir);
24660dbfbabbSHaiyue Wang 					adapter->fdir_active_fltr--;
24670dbfbabbSHaiyue Wang 				} else {
24680dbfbabbSHaiyue Wang 					fdir->state = IAVF_FDIR_FLTR_ACTIVE;
24690dbfbabbSHaiyue Wang 					dev_info(&adapter->pdev->dev, "Failed to delete Flow Director filter with status: %d\n",
24700dbfbabbSHaiyue Wang 						 del_fltr->status);
2471527691bfSHaiyue Wang 					iavf_print_fdir_fltr(adapter, fdir);
24720dbfbabbSHaiyue Wang 				}
2473*3beb9d66SPiotr Gardocki 			} else if (fdir->state == IAVF_FDIR_FLTR_DIS_PENDING) {
2474*3beb9d66SPiotr Gardocki 				if (del_fltr->status == VIRTCHNL_FDIR_SUCCESS ||
2475*3beb9d66SPiotr Gardocki 				    del_fltr->status ==
2476*3beb9d66SPiotr Gardocki 				    VIRTCHNL_FDIR_FAILURE_RULE_NONEXIST) {
2477*3beb9d66SPiotr Gardocki 					fdir->state = IAVF_FDIR_FLTR_INACTIVE;
2478*3beb9d66SPiotr Gardocki 				} else {
2479*3beb9d66SPiotr Gardocki 					fdir->state = IAVF_FDIR_FLTR_ACTIVE;
2480*3beb9d66SPiotr Gardocki 					dev_info(&adapter->pdev->dev, "Failed to disable Flow Director filter with status: %d\n",
2481*3beb9d66SPiotr Gardocki 						 del_fltr->status);
2482*3beb9d66SPiotr Gardocki 					iavf_print_fdir_fltr(adapter, fdir);
2483*3beb9d66SPiotr Gardocki 				}
24840dbfbabbSHaiyue Wang 			}
24850dbfbabbSHaiyue Wang 		}
24860dbfbabbSHaiyue Wang 		spin_unlock_bh(&adapter->fdir_fltr_lock);
24870dbfbabbSHaiyue Wang 		}
24880dbfbabbSHaiyue Wang 		break;
24890aaeb4fbSHaiyue Wang 	case VIRTCHNL_OP_ADD_RSS_CFG: {
24900aaeb4fbSHaiyue Wang 		struct iavf_adv_rss *rss;
24910aaeb4fbSHaiyue Wang 
24920aaeb4fbSHaiyue Wang 		spin_lock_bh(&adapter->adv_rss_lock);
24935ab91e05SHaiyue Wang 		list_for_each_entry(rss, &adapter->adv_rss_list_head, list) {
24945ab91e05SHaiyue Wang 			if (rss->state == IAVF_ADV_RSS_ADD_PENDING) {
24955ab91e05SHaiyue Wang 				iavf_print_adv_rss_cfg(adapter, rss,
24965ab91e05SHaiyue Wang 						       "Input set change for",
24975ab91e05SHaiyue Wang 						       "successful");
24980aaeb4fbSHaiyue Wang 				rss->state = IAVF_ADV_RSS_ACTIVE;
24995ab91e05SHaiyue Wang 			}
25005ab91e05SHaiyue Wang 		}
25010aaeb4fbSHaiyue Wang 		spin_unlock_bh(&adapter->adv_rss_lock);
25020aaeb4fbSHaiyue Wang 		}
25030aaeb4fbSHaiyue Wang 		break;
25040aaeb4fbSHaiyue Wang 	case VIRTCHNL_OP_DEL_RSS_CFG: {
25050aaeb4fbSHaiyue Wang 		struct iavf_adv_rss *rss, *rss_tmp;
25060aaeb4fbSHaiyue Wang 
25070aaeb4fbSHaiyue Wang 		spin_lock_bh(&adapter->adv_rss_lock);
25080aaeb4fbSHaiyue Wang 		list_for_each_entry_safe(rss, rss_tmp,
25090aaeb4fbSHaiyue Wang 					 &adapter->adv_rss_list_head, list) {
25100aaeb4fbSHaiyue Wang 			if (rss->state == IAVF_ADV_RSS_DEL_PENDING) {
25110aaeb4fbSHaiyue Wang 				list_del(&rss->list);
25120aaeb4fbSHaiyue Wang 				kfree(rss);
25130aaeb4fbSHaiyue Wang 			}
25140aaeb4fbSHaiyue Wang 		}
25150aaeb4fbSHaiyue Wang 		spin_unlock_bh(&adapter->adv_rss_lock);
25160aaeb4fbSHaiyue Wang 		}
25170aaeb4fbSHaiyue Wang 		break;
2518968996c0SPrzemyslaw Patynowski 	case VIRTCHNL_OP_ADD_VLAN_V2: {
2519968996c0SPrzemyslaw Patynowski 		struct iavf_vlan_filter *f;
2520968996c0SPrzemyslaw Patynowski 
2521968996c0SPrzemyslaw Patynowski 		spin_lock_bh(&adapter->mac_vlan_list_lock);
2522968996c0SPrzemyslaw Patynowski 		list_for_each_entry(f, &adapter->vlan_filter_list, list) {
25239c85b7faSAhmed Zaki 			if (f->state == IAVF_VLAN_IS_NEW)
25240c0da0e9SAhmed Zaki 				f->state = IAVF_VLAN_ACTIVE;
2525968996c0SPrzemyslaw Patynowski 		}
2526968996c0SPrzemyslaw Patynowski 		spin_unlock_bh(&adapter->mac_vlan_list_lock);
2527968996c0SPrzemyslaw Patynowski 		}
2528968996c0SPrzemyslaw Patynowski 		break;
25292cf29e55SMichal Maloszewski 	case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING:
25302cf29e55SMichal Maloszewski 		/* PF enabled vlan strip on this VF.
25312cf29e55SMichal Maloszewski 		 * Update netdev->features if needed to be in sync with ethtool.
25322cf29e55SMichal Maloszewski 		 */
25332cf29e55SMichal Maloszewski 		if (!v_retval)
25342cf29e55SMichal Maloszewski 			iavf_netdev_features_vlan_strip_set(netdev, true);
25352cf29e55SMichal Maloszewski 		break;
25362cf29e55SMichal Maloszewski 	case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING:
25372cf29e55SMichal Maloszewski 		/* PF disabled vlan strip on this VF.
25382cf29e55SMichal Maloszewski 		 * Update netdev->features if needed to be in sync with ethtool.
25392cf29e55SMichal Maloszewski 		 */
25402cf29e55SMichal Maloszewski 		if (!v_retval)
25412cf29e55SMichal Maloszewski 			iavf_netdev_features_vlan_strip_set(netdev, false);
25422cf29e55SMichal Maloszewski 		break;
25435ec8b7d1SJesse Brandeburg 	default:
25445ec8b7d1SJesse Brandeburg 		if (adapter->current_op && (v_opcode != adapter->current_op))
25455ec8b7d1SJesse Brandeburg 			dev_warn(&adapter->pdev->dev, "Expected response %d from PF, received %d\n",
25465ec8b7d1SJesse Brandeburg 				 adapter->current_op, v_opcode);
25475ec8b7d1SJesse Brandeburg 		break;
25485ec8b7d1SJesse Brandeburg 	} /* switch v_opcode */
25495ec8b7d1SJesse Brandeburg 	adapter->current_op = VIRTCHNL_OP_UNKNOWN;
25505ec8b7d1SJesse Brandeburg }
2551