xref: /openbmc/linux/drivers/net/ethernet/intel/i40e/i40e_adminq.c (revision 86aa961bb4619a68077ebeba21c52e9ba0eab43d)
1ae06c70bSJeff Kirsher // SPDX-License-Identifier: GPL-2.0
251dce24bSJeff Kirsher /* Copyright(c) 2013 - 2018 Intel Corporation. */
356a62fc8SJesse Brandeburg 
4*e77220eeSIvan Vecera #include <linux/delay.h>
5*e77220eeSIvan Vecera #include "i40e_alloc.h"
656a62fc8SJesse Brandeburg #include "i40e_register.h"
756a62fc8SJesse Brandeburg #include "i40e_prototype.h"
856a62fc8SJesse Brandeburg 
9af28eec9SStephen Hemminger static void i40e_resume_aq(struct i40e_hw *hw);
10af28eec9SStephen Hemminger 
1156a62fc8SJesse Brandeburg /**
1256a62fc8SJesse Brandeburg  *  i40e_adminq_init_regs - Initialize AdminQ registers
1356a62fc8SJesse Brandeburg  *  @hw: pointer to the hardware structure
1456a62fc8SJesse Brandeburg  *
1556a62fc8SJesse Brandeburg  *  This assumes the alloc_asq and alloc_arq functions have already been called
1656a62fc8SJesse Brandeburg  **/
i40e_adminq_init_regs(struct i40e_hw * hw)1756a62fc8SJesse Brandeburg static void i40e_adminq_init_regs(struct i40e_hw *hw)
1856a62fc8SJesse Brandeburg {
1956a62fc8SJesse Brandeburg 	/* set head and tail registers in our local struct */
20e7f2e4b9SAnjali Singhai Jain 	if (i40e_is_vf(hw)) {
2156a62fc8SJesse Brandeburg 		hw->aq.asq.tail = I40E_VF_ATQT1;
2256a62fc8SJesse Brandeburg 		hw->aq.asq.head = I40E_VF_ATQH1;
2317e6a845SShannon Nelson 		hw->aq.asq.len  = I40E_VF_ATQLEN1;
2487dc3464SShannon Nelson 		hw->aq.asq.bal  = I40E_VF_ATQBAL1;
2587dc3464SShannon Nelson 		hw->aq.asq.bah  = I40E_VF_ATQBAH1;
2656a62fc8SJesse Brandeburg 		hw->aq.arq.tail = I40E_VF_ARQT1;
2756a62fc8SJesse Brandeburg 		hw->aq.arq.head = I40E_VF_ARQH1;
2817e6a845SShannon Nelson 		hw->aq.arq.len  = I40E_VF_ARQLEN1;
2987dc3464SShannon Nelson 		hw->aq.arq.bal  = I40E_VF_ARQBAL1;
3087dc3464SShannon Nelson 		hw->aq.arq.bah  = I40E_VF_ARQBAH1;
3156a62fc8SJesse Brandeburg 	} else {
3256a62fc8SJesse Brandeburg 		hw->aq.asq.tail = I40E_PF_ATQT;
3356a62fc8SJesse Brandeburg 		hw->aq.asq.head = I40E_PF_ATQH;
3417e6a845SShannon Nelson 		hw->aq.asq.len  = I40E_PF_ATQLEN;
3587dc3464SShannon Nelson 		hw->aq.asq.bal  = I40E_PF_ATQBAL;
3687dc3464SShannon Nelson 		hw->aq.asq.bah  = I40E_PF_ATQBAH;
3756a62fc8SJesse Brandeburg 		hw->aq.arq.tail = I40E_PF_ARQT;
3856a62fc8SJesse Brandeburg 		hw->aq.arq.head = I40E_PF_ARQH;
3917e6a845SShannon Nelson 		hw->aq.arq.len  = I40E_PF_ARQLEN;
4087dc3464SShannon Nelson 		hw->aq.arq.bal  = I40E_PF_ARQBAL;
4187dc3464SShannon Nelson 		hw->aq.arq.bah  = I40E_PF_ARQBAH;
4256a62fc8SJesse Brandeburg 	}
4356a62fc8SJesse Brandeburg }
4456a62fc8SJesse Brandeburg 
4556a62fc8SJesse Brandeburg /**
4656a62fc8SJesse Brandeburg  *  i40e_alloc_adminq_asq_ring - Allocate Admin Queue send rings
4756a62fc8SJesse Brandeburg  *  @hw: pointer to the hardware structure
4856a62fc8SJesse Brandeburg  **/
i40e_alloc_adminq_asq_ring(struct i40e_hw * hw)495180ff13SJan Sokolowski static int i40e_alloc_adminq_asq_ring(struct i40e_hw *hw)
5056a62fc8SJesse Brandeburg {
515180ff13SJan Sokolowski 	int ret_code;
5256a62fc8SJesse Brandeburg 
5390bb776aSDavid Cassard 	ret_code = i40e_allocate_dma_mem(hw, &hw->aq.asq.desc_buf,
5456a62fc8SJesse Brandeburg 					 (hw->aq.num_asq_entries *
5556a62fc8SJesse Brandeburg 					 sizeof(struct i40e_aq_desc)),
5656a62fc8SJesse Brandeburg 					 I40E_ADMINQ_DESC_ALIGNMENT);
5756a62fc8SJesse Brandeburg 	if (ret_code)
5856a62fc8SJesse Brandeburg 		return ret_code;
5956a62fc8SJesse Brandeburg 
6090bb776aSDavid Cassard 	ret_code = i40e_allocate_virt_mem(hw, &hw->aq.asq.cmd_buf,
6156a62fc8SJesse Brandeburg 					  (hw->aq.num_asq_entries *
6256a62fc8SJesse Brandeburg 					  sizeof(struct i40e_asq_cmd_details)));
6356a62fc8SJesse Brandeburg 	if (ret_code) {
6490bb776aSDavid Cassard 		i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf);
6556a62fc8SJesse Brandeburg 		return ret_code;
6656a62fc8SJesse Brandeburg 	}
6756a62fc8SJesse Brandeburg 
6856a62fc8SJesse Brandeburg 	return ret_code;
6956a62fc8SJesse Brandeburg }
7056a62fc8SJesse Brandeburg 
7156a62fc8SJesse Brandeburg /**
7256a62fc8SJesse Brandeburg  *  i40e_alloc_adminq_arq_ring - Allocate Admin Queue receive rings
7356a62fc8SJesse Brandeburg  *  @hw: pointer to the hardware structure
7456a62fc8SJesse Brandeburg  **/
i40e_alloc_adminq_arq_ring(struct i40e_hw * hw)755180ff13SJan Sokolowski static int i40e_alloc_adminq_arq_ring(struct i40e_hw *hw)
7656a62fc8SJesse Brandeburg {
775180ff13SJan Sokolowski 	int ret_code;
7856a62fc8SJesse Brandeburg 
7990bb776aSDavid Cassard 	ret_code = i40e_allocate_dma_mem(hw, &hw->aq.arq.desc_buf,
8056a62fc8SJesse Brandeburg 					 (hw->aq.num_arq_entries *
8156a62fc8SJesse Brandeburg 					 sizeof(struct i40e_aq_desc)),
8256a62fc8SJesse Brandeburg 					 I40E_ADMINQ_DESC_ALIGNMENT);
8356a62fc8SJesse Brandeburg 
8456a62fc8SJesse Brandeburg 	return ret_code;
8556a62fc8SJesse Brandeburg }
8656a62fc8SJesse Brandeburg 
8756a62fc8SJesse Brandeburg /**
8856a62fc8SJesse Brandeburg  *  i40e_free_adminq_asq - Free Admin Queue send rings
8956a62fc8SJesse Brandeburg  *  @hw: pointer to the hardware structure
9056a62fc8SJesse Brandeburg  *
9156a62fc8SJesse Brandeburg  *  This assumes the posted send buffers have already been cleaned
9256a62fc8SJesse Brandeburg  *  and de-allocated
9356a62fc8SJesse Brandeburg  **/
i40e_free_adminq_asq(struct i40e_hw * hw)9456a62fc8SJesse Brandeburg static void i40e_free_adminq_asq(struct i40e_hw *hw)
9556a62fc8SJesse Brandeburg {
9690bb776aSDavid Cassard 	i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf);
9756a62fc8SJesse Brandeburg }
9856a62fc8SJesse Brandeburg 
9956a62fc8SJesse Brandeburg /**
10056a62fc8SJesse Brandeburg  *  i40e_free_adminq_arq - Free Admin Queue receive rings
10156a62fc8SJesse Brandeburg  *  @hw: pointer to the hardware structure
10256a62fc8SJesse Brandeburg  *
10356a62fc8SJesse Brandeburg  *  This assumes the posted receive buffers have already been cleaned
10456a62fc8SJesse Brandeburg  *  and de-allocated
10556a62fc8SJesse Brandeburg  **/
i40e_free_adminq_arq(struct i40e_hw * hw)10656a62fc8SJesse Brandeburg static void i40e_free_adminq_arq(struct i40e_hw *hw)
10756a62fc8SJesse Brandeburg {
10890bb776aSDavid Cassard 	i40e_free_dma_mem(hw, &hw->aq.arq.desc_buf);
10956a62fc8SJesse Brandeburg }
11056a62fc8SJesse Brandeburg 
11156a62fc8SJesse Brandeburg /**
11256a62fc8SJesse Brandeburg  *  i40e_alloc_arq_bufs - Allocate pre-posted buffers for the receive queue
11356a62fc8SJesse Brandeburg  *  @hw: pointer to the hardware structure
11456a62fc8SJesse Brandeburg  **/
i40e_alloc_arq_bufs(struct i40e_hw * hw)1155180ff13SJan Sokolowski static int i40e_alloc_arq_bufs(struct i40e_hw *hw)
11656a62fc8SJesse Brandeburg {
11756a62fc8SJesse Brandeburg 	struct i40e_aq_desc *desc;
11856a62fc8SJesse Brandeburg 	struct i40e_dma_mem *bi;
1195180ff13SJan Sokolowski 	int ret_code;
12056a62fc8SJesse Brandeburg 	int i;
12156a62fc8SJesse Brandeburg 
12256a62fc8SJesse Brandeburg 	/* We'll be allocating the buffer info memory first, then we can
12356a62fc8SJesse Brandeburg 	 * allocate the mapped buffers for the event processing
12456a62fc8SJesse Brandeburg 	 */
12556a62fc8SJesse Brandeburg 
12656a62fc8SJesse Brandeburg 	/* buffer_info structures do not need alignment */
12790bb776aSDavid Cassard 	ret_code = i40e_allocate_virt_mem(hw, &hw->aq.arq.dma_head,
12890bb776aSDavid Cassard 		(hw->aq.num_arq_entries * sizeof(struct i40e_dma_mem)));
12956a62fc8SJesse Brandeburg 	if (ret_code)
13056a62fc8SJesse Brandeburg 		goto alloc_arq_bufs;
13190bb776aSDavid Cassard 	hw->aq.arq.r.arq_bi = (struct i40e_dma_mem *)hw->aq.arq.dma_head.va;
13256a62fc8SJesse Brandeburg 
13356a62fc8SJesse Brandeburg 	/* allocate the mapped buffers */
13456a62fc8SJesse Brandeburg 	for (i = 0; i < hw->aq.num_arq_entries; i++) {
13556a62fc8SJesse Brandeburg 		bi = &hw->aq.arq.r.arq_bi[i];
13656a62fc8SJesse Brandeburg 		ret_code = i40e_allocate_dma_mem(hw, bi,
13756a62fc8SJesse Brandeburg 						 hw->aq.arq_buf_size,
13856a62fc8SJesse Brandeburg 						 I40E_ADMINQ_DESC_ALIGNMENT);
13956a62fc8SJesse Brandeburg 		if (ret_code)
14056a62fc8SJesse Brandeburg 			goto unwind_alloc_arq_bufs;
14156a62fc8SJesse Brandeburg 
14256a62fc8SJesse Brandeburg 		/* now configure the descriptors for use */
14356a62fc8SJesse Brandeburg 		desc = I40E_ADMINQ_DESC(hw->aq.arq, i);
14456a62fc8SJesse Brandeburg 
14556a62fc8SJesse Brandeburg 		desc->flags = cpu_to_le16(I40E_AQ_FLAG_BUF);
14656a62fc8SJesse Brandeburg 		if (hw->aq.arq_buf_size > I40E_AQ_LARGE_BUF)
14756a62fc8SJesse Brandeburg 			desc->flags |= cpu_to_le16(I40E_AQ_FLAG_LB);
14856a62fc8SJesse Brandeburg 		desc->opcode = 0;
14956a62fc8SJesse Brandeburg 		/* This is in accordance with Admin queue design, there is no
15056a62fc8SJesse Brandeburg 		 * register for buffer size configuration
15156a62fc8SJesse Brandeburg 		 */
15256a62fc8SJesse Brandeburg 		desc->datalen = cpu_to_le16((u16)bi->size);
15356a62fc8SJesse Brandeburg 		desc->retval = 0;
15456a62fc8SJesse Brandeburg 		desc->cookie_high = 0;
15556a62fc8SJesse Brandeburg 		desc->cookie_low = 0;
15656a62fc8SJesse Brandeburg 		desc->params.external.addr_high =
15756a62fc8SJesse Brandeburg 			cpu_to_le32(upper_32_bits(bi->pa));
15856a62fc8SJesse Brandeburg 		desc->params.external.addr_low =
15956a62fc8SJesse Brandeburg 			cpu_to_le32(lower_32_bits(bi->pa));
16056a62fc8SJesse Brandeburg 		desc->params.external.param0 = 0;
16156a62fc8SJesse Brandeburg 		desc->params.external.param1 = 0;
16256a62fc8SJesse Brandeburg 	}
16356a62fc8SJesse Brandeburg 
16456a62fc8SJesse Brandeburg alloc_arq_bufs:
16556a62fc8SJesse Brandeburg 	return ret_code;
16656a62fc8SJesse Brandeburg 
16756a62fc8SJesse Brandeburg unwind_alloc_arq_bufs:
16856a62fc8SJesse Brandeburg 	/* don't try to free the one that failed... */
16956a62fc8SJesse Brandeburg 	i--;
17056a62fc8SJesse Brandeburg 	for (; i >= 0; i--)
17156a62fc8SJesse Brandeburg 		i40e_free_dma_mem(hw, &hw->aq.arq.r.arq_bi[i]);
17290bb776aSDavid Cassard 	i40e_free_virt_mem(hw, &hw->aq.arq.dma_head);
17356a62fc8SJesse Brandeburg 
17456a62fc8SJesse Brandeburg 	return ret_code;
17556a62fc8SJesse Brandeburg }
17656a62fc8SJesse Brandeburg 
17756a62fc8SJesse Brandeburg /**
17856a62fc8SJesse Brandeburg  *  i40e_alloc_asq_bufs - Allocate empty buffer structs for the send queue
17956a62fc8SJesse Brandeburg  *  @hw: pointer to the hardware structure
18056a62fc8SJesse Brandeburg  **/
i40e_alloc_asq_bufs(struct i40e_hw * hw)1815180ff13SJan Sokolowski static int i40e_alloc_asq_bufs(struct i40e_hw *hw)
18256a62fc8SJesse Brandeburg {
18356a62fc8SJesse Brandeburg 	struct i40e_dma_mem *bi;
1845180ff13SJan Sokolowski 	int ret_code;
18556a62fc8SJesse Brandeburg 	int i;
18656a62fc8SJesse Brandeburg 
18756a62fc8SJesse Brandeburg 	/* No mapped memory needed yet, just the buffer info structures */
18890bb776aSDavid Cassard 	ret_code = i40e_allocate_virt_mem(hw, &hw->aq.asq.dma_head,
18990bb776aSDavid Cassard 		(hw->aq.num_asq_entries * sizeof(struct i40e_dma_mem)));
19056a62fc8SJesse Brandeburg 	if (ret_code)
19156a62fc8SJesse Brandeburg 		goto alloc_asq_bufs;
19290bb776aSDavid Cassard 	hw->aq.asq.r.asq_bi = (struct i40e_dma_mem *)hw->aq.asq.dma_head.va;
19356a62fc8SJesse Brandeburg 
19456a62fc8SJesse Brandeburg 	/* allocate the mapped buffers */
19556a62fc8SJesse Brandeburg 	for (i = 0; i < hw->aq.num_asq_entries; i++) {
19656a62fc8SJesse Brandeburg 		bi = &hw->aq.asq.r.asq_bi[i];
19756a62fc8SJesse Brandeburg 		ret_code = i40e_allocate_dma_mem(hw, bi,
19856a62fc8SJesse Brandeburg 						 hw->aq.asq_buf_size,
19956a62fc8SJesse Brandeburg 						 I40E_ADMINQ_DESC_ALIGNMENT);
20056a62fc8SJesse Brandeburg 		if (ret_code)
20156a62fc8SJesse Brandeburg 			goto unwind_alloc_asq_bufs;
20256a62fc8SJesse Brandeburg 	}
20356a62fc8SJesse Brandeburg alloc_asq_bufs:
20456a62fc8SJesse Brandeburg 	return ret_code;
20556a62fc8SJesse Brandeburg 
20656a62fc8SJesse Brandeburg unwind_alloc_asq_bufs:
20756a62fc8SJesse Brandeburg 	/* don't try to free the one that failed... */
20856a62fc8SJesse Brandeburg 	i--;
20956a62fc8SJesse Brandeburg 	for (; i >= 0; i--)
21056a62fc8SJesse Brandeburg 		i40e_free_dma_mem(hw, &hw->aq.asq.r.asq_bi[i]);
21190bb776aSDavid Cassard 	i40e_free_virt_mem(hw, &hw->aq.asq.dma_head);
21256a62fc8SJesse Brandeburg 
21356a62fc8SJesse Brandeburg 	return ret_code;
21456a62fc8SJesse Brandeburg }
21556a62fc8SJesse Brandeburg 
21656a62fc8SJesse Brandeburg /**
21756a62fc8SJesse Brandeburg  *  i40e_free_arq_bufs - Free receive queue buffer info elements
21856a62fc8SJesse Brandeburg  *  @hw: pointer to the hardware structure
21956a62fc8SJesse Brandeburg  **/
i40e_free_arq_bufs(struct i40e_hw * hw)22056a62fc8SJesse Brandeburg static void i40e_free_arq_bufs(struct i40e_hw *hw)
22156a62fc8SJesse Brandeburg {
22256a62fc8SJesse Brandeburg 	int i;
22356a62fc8SJesse Brandeburg 
22490bb776aSDavid Cassard 	/* free descriptors */
22556a62fc8SJesse Brandeburg 	for (i = 0; i < hw->aq.num_arq_entries; i++)
22656a62fc8SJesse Brandeburg 		i40e_free_dma_mem(hw, &hw->aq.arq.r.arq_bi[i]);
22756a62fc8SJesse Brandeburg 
22890bb776aSDavid Cassard 	/* free the descriptor memory */
22990bb776aSDavid Cassard 	i40e_free_dma_mem(hw, &hw->aq.arq.desc_buf);
23090bb776aSDavid Cassard 
23190bb776aSDavid Cassard 	/* free the dma header */
23290bb776aSDavid Cassard 	i40e_free_virt_mem(hw, &hw->aq.arq.dma_head);
23356a62fc8SJesse Brandeburg }
23456a62fc8SJesse Brandeburg 
23556a62fc8SJesse Brandeburg /**
23656a62fc8SJesse Brandeburg  *  i40e_free_asq_bufs - Free send queue buffer info elements
23756a62fc8SJesse Brandeburg  *  @hw: pointer to the hardware structure
23856a62fc8SJesse Brandeburg  **/
i40e_free_asq_bufs(struct i40e_hw * hw)23956a62fc8SJesse Brandeburg static void i40e_free_asq_bufs(struct i40e_hw *hw)
24056a62fc8SJesse Brandeburg {
24156a62fc8SJesse Brandeburg 	int i;
24256a62fc8SJesse Brandeburg 
24356a62fc8SJesse Brandeburg 	/* only unmap if the address is non-NULL */
24456a62fc8SJesse Brandeburg 	for (i = 0; i < hw->aq.num_asq_entries; i++)
24556a62fc8SJesse Brandeburg 		if (hw->aq.asq.r.asq_bi[i].pa)
24656a62fc8SJesse Brandeburg 			i40e_free_dma_mem(hw, &hw->aq.asq.r.asq_bi[i]);
24756a62fc8SJesse Brandeburg 
24890bb776aSDavid Cassard 	/* free the buffer info list */
24990bb776aSDavid Cassard 	i40e_free_virt_mem(hw, &hw->aq.asq.cmd_buf);
25090bb776aSDavid Cassard 
25190bb776aSDavid Cassard 	/* free the descriptor memory */
25290bb776aSDavid Cassard 	i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf);
25390bb776aSDavid Cassard 
25490bb776aSDavid Cassard 	/* free the dma header */
25590bb776aSDavid Cassard 	i40e_free_virt_mem(hw, &hw->aq.asq.dma_head);
25656a62fc8SJesse Brandeburg }
25756a62fc8SJesse Brandeburg 
25856a62fc8SJesse Brandeburg /**
25956a62fc8SJesse Brandeburg  *  i40e_config_asq_regs - configure ASQ registers
26056a62fc8SJesse Brandeburg  *  @hw: pointer to the hardware structure
26156a62fc8SJesse Brandeburg  *
26256a62fc8SJesse Brandeburg  *  Configure base address and length registers for the transmit queue
26356a62fc8SJesse Brandeburg  **/
i40e_config_asq_regs(struct i40e_hw * hw)2645180ff13SJan Sokolowski static int i40e_config_asq_regs(struct i40e_hw *hw)
26556a62fc8SJesse Brandeburg {
2665180ff13SJan Sokolowski 	int ret_code = 0;
267e03af1e1SKamil Krawczyk 	u32 reg = 0;
268e03af1e1SKamil Krawczyk 
26980a977e7SMichal Kosiarz 	/* Clear Head and Tail */
27080a977e7SMichal Kosiarz 	wr32(hw, hw->aq.asq.head, 0);
27180a977e7SMichal Kosiarz 	wr32(hw, hw->aq.asq.tail, 0);
27280a977e7SMichal Kosiarz 
27387dc3464SShannon Nelson 	/* set starting point */
27487dc3464SShannon Nelson 	wr32(hw, hw->aq.asq.len, (hw->aq.num_asq_entries |
27556a62fc8SJesse Brandeburg 				  I40E_PF_ATQLEN_ATQENABLE_MASK));
27687dc3464SShannon Nelson 	wr32(hw, hw->aq.asq.bal, lower_32_bits(hw->aq.asq.desc_buf.pa));
27787dc3464SShannon Nelson 	wr32(hw, hw->aq.asq.bah, upper_32_bits(hw->aq.asq.desc_buf.pa));
278e03af1e1SKamil Krawczyk 
279e03af1e1SKamil Krawczyk 	/* Check one register to verify that config was applied */
28087dc3464SShannon Nelson 	reg = rd32(hw, hw->aq.asq.bal);
281e03af1e1SKamil Krawczyk 	if (reg != lower_32_bits(hw->aq.asq.desc_buf.pa))
282230f3d53SJan Sokolowski 		ret_code = -EIO;
283e03af1e1SKamil Krawczyk 
284e03af1e1SKamil Krawczyk 	return ret_code;
28556a62fc8SJesse Brandeburg }
28656a62fc8SJesse Brandeburg 
28756a62fc8SJesse Brandeburg /**
28856a62fc8SJesse Brandeburg  *  i40e_config_arq_regs - ARQ register configuration
28956a62fc8SJesse Brandeburg  *  @hw: pointer to the hardware structure
29056a62fc8SJesse Brandeburg  *
29156a62fc8SJesse Brandeburg  * Configure base address and length registers for the receive (event queue)
29256a62fc8SJesse Brandeburg  **/
i40e_config_arq_regs(struct i40e_hw * hw)2935180ff13SJan Sokolowski static int i40e_config_arq_regs(struct i40e_hw *hw)
29456a62fc8SJesse Brandeburg {
2955180ff13SJan Sokolowski 	int ret_code = 0;
296e03af1e1SKamil Krawczyk 	u32 reg = 0;
297e03af1e1SKamil Krawczyk 
29880a977e7SMichal Kosiarz 	/* Clear Head and Tail */
29980a977e7SMichal Kosiarz 	wr32(hw, hw->aq.arq.head, 0);
30080a977e7SMichal Kosiarz 	wr32(hw, hw->aq.arq.tail, 0);
30180a977e7SMichal Kosiarz 
30287dc3464SShannon Nelson 	/* set starting point */
30387dc3464SShannon Nelson 	wr32(hw, hw->aq.arq.len, (hw->aq.num_arq_entries |
30456a62fc8SJesse Brandeburg 				  I40E_PF_ARQLEN_ARQENABLE_MASK));
30587dc3464SShannon Nelson 	wr32(hw, hw->aq.arq.bal, lower_32_bits(hw->aq.arq.desc_buf.pa));
30687dc3464SShannon Nelson 	wr32(hw, hw->aq.arq.bah, upper_32_bits(hw->aq.arq.desc_buf.pa));
30756a62fc8SJesse Brandeburg 
30856a62fc8SJesse Brandeburg 	/* Update tail in the HW to post pre-allocated buffers */
30956a62fc8SJesse Brandeburg 	wr32(hw, hw->aq.arq.tail, hw->aq.num_arq_entries - 1);
310e03af1e1SKamil Krawczyk 
311e03af1e1SKamil Krawczyk 	/* Check one register to verify that config was applied */
31287dc3464SShannon Nelson 	reg = rd32(hw, hw->aq.arq.bal);
313e03af1e1SKamil Krawczyk 	if (reg != lower_32_bits(hw->aq.arq.desc_buf.pa))
314230f3d53SJan Sokolowski 		ret_code = -EIO;
315e03af1e1SKamil Krawczyk 
316e03af1e1SKamil Krawczyk 	return ret_code;
31756a62fc8SJesse Brandeburg }
31856a62fc8SJesse Brandeburg 
31956a62fc8SJesse Brandeburg /**
32056a62fc8SJesse Brandeburg  *  i40e_init_asq - main initialization routine for ASQ
32156a62fc8SJesse Brandeburg  *  @hw: pointer to the hardware structure
32256a62fc8SJesse Brandeburg  *
32356a62fc8SJesse Brandeburg  *  This is the main initialization routine for the Admin Send Queue
32456a62fc8SJesse Brandeburg  *  Prior to calling this function, drivers *MUST* set the following fields
32556a62fc8SJesse Brandeburg  *  in the hw->aq structure:
32656a62fc8SJesse Brandeburg  *     - hw->aq.num_asq_entries
32756a62fc8SJesse Brandeburg  *     - hw->aq.arq_buf_size
32856a62fc8SJesse Brandeburg  *
32956a62fc8SJesse Brandeburg  *  Do *NOT* hold the lock when calling this as the memory allocation routines
33056a62fc8SJesse Brandeburg  *  called are not going to be atomic context safe
33156a62fc8SJesse Brandeburg  **/
i40e_init_asq(struct i40e_hw * hw)3325180ff13SJan Sokolowski static int i40e_init_asq(struct i40e_hw *hw)
33356a62fc8SJesse Brandeburg {
3345180ff13SJan Sokolowski 	int ret_code = 0;
33556a62fc8SJesse Brandeburg 
33656a62fc8SJesse Brandeburg 	if (hw->aq.asq.count > 0) {
33756a62fc8SJesse Brandeburg 		/* queue already initialized */
338230f3d53SJan Sokolowski 		ret_code = -EBUSY;
33956a62fc8SJesse Brandeburg 		goto init_adminq_exit;
34056a62fc8SJesse Brandeburg 	}
34156a62fc8SJesse Brandeburg 
34256a62fc8SJesse Brandeburg 	/* verify input for valid configuration */
34356a62fc8SJesse Brandeburg 	if ((hw->aq.num_asq_entries == 0) ||
34456a62fc8SJesse Brandeburg 	    (hw->aq.asq_buf_size == 0)) {
345230f3d53SJan Sokolowski 		ret_code = -EIO;
34656a62fc8SJesse Brandeburg 		goto init_adminq_exit;
34756a62fc8SJesse Brandeburg 	}
34856a62fc8SJesse Brandeburg 
34956a62fc8SJesse Brandeburg 	hw->aq.asq.next_to_use = 0;
35056a62fc8SJesse Brandeburg 	hw->aq.asq.next_to_clean = 0;
35156a62fc8SJesse Brandeburg 
35256a62fc8SJesse Brandeburg 	/* allocate the ring memory */
35356a62fc8SJesse Brandeburg 	ret_code = i40e_alloc_adminq_asq_ring(hw);
35456a62fc8SJesse Brandeburg 	if (ret_code)
35556a62fc8SJesse Brandeburg 		goto init_adminq_exit;
35656a62fc8SJesse Brandeburg 
35756a62fc8SJesse Brandeburg 	/* allocate buffers in the rings */
35856a62fc8SJesse Brandeburg 	ret_code = i40e_alloc_asq_bufs(hw);
35956a62fc8SJesse Brandeburg 	if (ret_code)
36056a62fc8SJesse Brandeburg 		goto init_adminq_free_rings;
36156a62fc8SJesse Brandeburg 
36256a62fc8SJesse Brandeburg 	/* initialize base registers */
363e03af1e1SKamil Krawczyk 	ret_code = i40e_config_asq_regs(hw);
364e03af1e1SKamil Krawczyk 	if (ret_code)
365e03af1e1SKamil Krawczyk 		goto init_adminq_free_rings;
36656a62fc8SJesse Brandeburg 
36756a62fc8SJesse Brandeburg 	/* success! */
36890d2c056SMitch Williams 	hw->aq.asq.count = hw->aq.num_asq_entries;
36956a62fc8SJesse Brandeburg 	goto init_adminq_exit;
37056a62fc8SJesse Brandeburg 
37156a62fc8SJesse Brandeburg init_adminq_free_rings:
37256a62fc8SJesse Brandeburg 	i40e_free_adminq_asq(hw);
37356a62fc8SJesse Brandeburg 
37456a62fc8SJesse Brandeburg init_adminq_exit:
37556a62fc8SJesse Brandeburg 	return ret_code;
37656a62fc8SJesse Brandeburg }
37756a62fc8SJesse Brandeburg 
37856a62fc8SJesse Brandeburg /**
37956a62fc8SJesse Brandeburg  *  i40e_init_arq - initialize ARQ
38056a62fc8SJesse Brandeburg  *  @hw: pointer to the hardware structure
38156a62fc8SJesse Brandeburg  *
38256a62fc8SJesse Brandeburg  *  The main initialization routine for the Admin Receive (Event) Queue.
38356a62fc8SJesse Brandeburg  *  Prior to calling this function, drivers *MUST* set the following fields
38456a62fc8SJesse Brandeburg  *  in the hw->aq structure:
38556a62fc8SJesse Brandeburg  *     - hw->aq.num_asq_entries
38656a62fc8SJesse Brandeburg  *     - hw->aq.arq_buf_size
38756a62fc8SJesse Brandeburg  *
38856a62fc8SJesse Brandeburg  *  Do *NOT* hold the lock when calling this as the memory allocation routines
38956a62fc8SJesse Brandeburg  *  called are not going to be atomic context safe
39056a62fc8SJesse Brandeburg  **/
i40e_init_arq(struct i40e_hw * hw)3915180ff13SJan Sokolowski static int i40e_init_arq(struct i40e_hw *hw)
39256a62fc8SJesse Brandeburg {
3935180ff13SJan Sokolowski 	int ret_code = 0;
39456a62fc8SJesse Brandeburg 
39556a62fc8SJesse Brandeburg 	if (hw->aq.arq.count > 0) {
39656a62fc8SJesse Brandeburg 		/* queue already initialized */
397230f3d53SJan Sokolowski 		ret_code = -EBUSY;
39856a62fc8SJesse Brandeburg 		goto init_adminq_exit;
39956a62fc8SJesse Brandeburg 	}
40056a62fc8SJesse Brandeburg 
40156a62fc8SJesse Brandeburg 	/* verify input for valid configuration */
40256a62fc8SJesse Brandeburg 	if ((hw->aq.num_arq_entries == 0) ||
40356a62fc8SJesse Brandeburg 	    (hw->aq.arq_buf_size == 0)) {
404230f3d53SJan Sokolowski 		ret_code = -EIO;
40556a62fc8SJesse Brandeburg 		goto init_adminq_exit;
40656a62fc8SJesse Brandeburg 	}
40756a62fc8SJesse Brandeburg 
40856a62fc8SJesse Brandeburg 	hw->aq.arq.next_to_use = 0;
40956a62fc8SJesse Brandeburg 	hw->aq.arq.next_to_clean = 0;
41056a62fc8SJesse Brandeburg 
41156a62fc8SJesse Brandeburg 	/* allocate the ring memory */
41256a62fc8SJesse Brandeburg 	ret_code = i40e_alloc_adminq_arq_ring(hw);
41356a62fc8SJesse Brandeburg 	if (ret_code)
41456a62fc8SJesse Brandeburg 		goto init_adminq_exit;
41556a62fc8SJesse Brandeburg 
41656a62fc8SJesse Brandeburg 	/* allocate buffers in the rings */
41756a62fc8SJesse Brandeburg 	ret_code = i40e_alloc_arq_bufs(hw);
41856a62fc8SJesse Brandeburg 	if (ret_code)
41956a62fc8SJesse Brandeburg 		goto init_adminq_free_rings;
42056a62fc8SJesse Brandeburg 
42156a62fc8SJesse Brandeburg 	/* initialize base registers */
422e03af1e1SKamil Krawczyk 	ret_code = i40e_config_arq_regs(hw);
423e03af1e1SKamil Krawczyk 	if (ret_code)
424e03af1e1SKamil Krawczyk 		goto init_adminq_free_rings;
42556a62fc8SJesse Brandeburg 
42656a62fc8SJesse Brandeburg 	/* success! */
42790d2c056SMitch Williams 	hw->aq.arq.count = hw->aq.num_arq_entries;
42856a62fc8SJesse Brandeburg 	goto init_adminq_exit;
42956a62fc8SJesse Brandeburg 
43056a62fc8SJesse Brandeburg init_adminq_free_rings:
43156a62fc8SJesse Brandeburg 	i40e_free_adminq_arq(hw);
43256a62fc8SJesse Brandeburg 
43356a62fc8SJesse Brandeburg init_adminq_exit:
43456a62fc8SJesse Brandeburg 	return ret_code;
43556a62fc8SJesse Brandeburg }
43656a62fc8SJesse Brandeburg 
43756a62fc8SJesse Brandeburg /**
43856a62fc8SJesse Brandeburg  *  i40e_shutdown_asq - shutdown the ASQ
43956a62fc8SJesse Brandeburg  *  @hw: pointer to the hardware structure
44056a62fc8SJesse Brandeburg  *
44156a62fc8SJesse Brandeburg  *  The main shutdown routine for the Admin Send Queue
44256a62fc8SJesse Brandeburg  **/
i40e_shutdown_asq(struct i40e_hw * hw)4435180ff13SJan Sokolowski static int i40e_shutdown_asq(struct i40e_hw *hw)
44456a62fc8SJesse Brandeburg {
4455180ff13SJan Sokolowski 	int ret_code = 0;
44656a62fc8SJesse Brandeburg 
44724408e7aSShannon Nelson 	mutex_lock(&hw->aq.asq_mutex);
44824408e7aSShannon Nelson 
44924408e7aSShannon Nelson 	if (hw->aq.asq.count == 0) {
450230f3d53SJan Sokolowski 		ret_code = -EBUSY;
45124408e7aSShannon Nelson 		goto shutdown_asq_out;
45224408e7aSShannon Nelson 	}
45356a62fc8SJesse Brandeburg 
45456a62fc8SJesse Brandeburg 	/* Stop firmware AdminQ processing */
45517e6a845SShannon Nelson 	wr32(hw, hw->aq.asq.head, 0);
45617e6a845SShannon Nelson 	wr32(hw, hw->aq.asq.tail, 0);
45717e6a845SShannon Nelson 	wr32(hw, hw->aq.asq.len, 0);
4584346940bSShannon Nelson 	wr32(hw, hw->aq.asq.bal, 0);
4594346940bSShannon Nelson 	wr32(hw, hw->aq.asq.bah, 0);
46056a62fc8SJesse Brandeburg 
46156a62fc8SJesse Brandeburg 	hw->aq.asq.count = 0; /* to indicate uninitialized queue */
46256a62fc8SJesse Brandeburg 
46356a62fc8SJesse Brandeburg 	/* free ring buffers */
46456a62fc8SJesse Brandeburg 	i40e_free_asq_bufs(hw);
46556a62fc8SJesse Brandeburg 
46624408e7aSShannon Nelson shutdown_asq_out:
46756a62fc8SJesse Brandeburg 	mutex_unlock(&hw->aq.asq_mutex);
46856a62fc8SJesse Brandeburg 	return ret_code;
46956a62fc8SJesse Brandeburg }
47056a62fc8SJesse Brandeburg 
47156a62fc8SJesse Brandeburg /**
47256a62fc8SJesse Brandeburg  *  i40e_shutdown_arq - shutdown ARQ
47356a62fc8SJesse Brandeburg  *  @hw: pointer to the hardware structure
47456a62fc8SJesse Brandeburg  *
47556a62fc8SJesse Brandeburg  *  The main shutdown routine for the Admin Receive Queue
47656a62fc8SJesse Brandeburg  **/
i40e_shutdown_arq(struct i40e_hw * hw)4775180ff13SJan Sokolowski static int i40e_shutdown_arq(struct i40e_hw *hw)
47856a62fc8SJesse Brandeburg {
4795180ff13SJan Sokolowski 	int ret_code = 0;
48056a62fc8SJesse Brandeburg 
48124408e7aSShannon Nelson 	mutex_lock(&hw->aq.arq_mutex);
48224408e7aSShannon Nelson 
48324408e7aSShannon Nelson 	if (hw->aq.arq.count == 0) {
484230f3d53SJan Sokolowski 		ret_code = -EBUSY;
48524408e7aSShannon Nelson 		goto shutdown_arq_out;
48624408e7aSShannon Nelson 	}
48756a62fc8SJesse Brandeburg 
48856a62fc8SJesse Brandeburg 	/* Stop firmware AdminQ processing */
48917e6a845SShannon Nelson 	wr32(hw, hw->aq.arq.head, 0);
49017e6a845SShannon Nelson 	wr32(hw, hw->aq.arq.tail, 0);
49117e6a845SShannon Nelson 	wr32(hw, hw->aq.arq.len, 0);
4924346940bSShannon Nelson 	wr32(hw, hw->aq.arq.bal, 0);
4934346940bSShannon Nelson 	wr32(hw, hw->aq.arq.bah, 0);
49456a62fc8SJesse Brandeburg 
49556a62fc8SJesse Brandeburg 	hw->aq.arq.count = 0; /* to indicate uninitialized queue */
49656a62fc8SJesse Brandeburg 
49756a62fc8SJesse Brandeburg 	/* free ring buffers */
49856a62fc8SJesse Brandeburg 	i40e_free_arq_bufs(hw);
49956a62fc8SJesse Brandeburg 
50024408e7aSShannon Nelson shutdown_arq_out:
50156a62fc8SJesse Brandeburg 	mutex_unlock(&hw->aq.arq_mutex);
50256a62fc8SJesse Brandeburg 	return ret_code;
50356a62fc8SJesse Brandeburg }
50456a62fc8SJesse Brandeburg 
50556a62fc8SJesse Brandeburg /**
506a3e09dedSPiotr Azarewicz  *  i40e_set_hw_flags - set HW flags
507a3e09dedSPiotr Azarewicz  *  @hw: pointer to the hardware structure
508a3e09dedSPiotr Azarewicz  **/
i40e_set_hw_flags(struct i40e_hw * hw)509a3e09dedSPiotr Azarewicz static void i40e_set_hw_flags(struct i40e_hw *hw)
510a3e09dedSPiotr Azarewicz {
511a3e09dedSPiotr Azarewicz 	struct i40e_adminq_info *aq = &hw->aq;
512a3e09dedSPiotr Azarewicz 
513a3e09dedSPiotr Azarewicz 	hw->flags = 0;
514a3e09dedSPiotr Azarewicz 
515a3e09dedSPiotr Azarewicz 	switch (hw->mac.type) {
516a3e09dedSPiotr Azarewicz 	case I40E_MAC_XL710:
517a3e09dedSPiotr Azarewicz 		if (aq->api_maj_ver > 1 ||
518a3e09dedSPiotr Azarewicz 		    (aq->api_maj_ver == 1 &&
519a3e09dedSPiotr Azarewicz 		     aq->api_min_ver >= I40E_MINOR_VER_GET_LINK_INFO_XL710)) {
520a3e09dedSPiotr Azarewicz 			hw->flags |= I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE;
521a3e09dedSPiotr Azarewicz 			hw->flags |= I40E_HW_FLAG_FW_LLDP_STOPPABLE;
522a3e09dedSPiotr Azarewicz 			/* The ability to RX (not drop) 802.1ad frames */
523a3e09dedSPiotr Azarewicz 			hw->flags |= I40E_HW_FLAG_802_1AD_CAPABLE;
524a3e09dedSPiotr Azarewicz 		}
525a3e09dedSPiotr Azarewicz 		break;
526a3e09dedSPiotr Azarewicz 	case I40E_MAC_X722:
527a3e09dedSPiotr Azarewicz 		hw->flags |= I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE |
528a3e09dedSPiotr Azarewicz 			     I40E_HW_FLAG_NVM_READ_REQUIRES_LOCK;
529a3e09dedSPiotr Azarewicz 
530a3e09dedSPiotr Azarewicz 		if (aq->api_maj_ver > 1 ||
531a3e09dedSPiotr Azarewicz 		    (aq->api_maj_ver == 1 &&
532a3e09dedSPiotr Azarewicz 		     aq->api_min_ver >= I40E_MINOR_VER_FW_LLDP_STOPPABLE_X722))
533a3e09dedSPiotr Azarewicz 			hw->flags |= I40E_HW_FLAG_FW_LLDP_STOPPABLE;
534bb37362fSAdam Ludkiewicz 
535bb37362fSAdam Ludkiewicz 		if (aq->api_maj_ver > 1 ||
536bb37362fSAdam Ludkiewicz 		    (aq->api_maj_ver == 1 &&
537bb37362fSAdam Ludkiewicz 		     aq->api_min_ver >= I40E_MINOR_VER_GET_LINK_INFO_X722))
538bb37362fSAdam Ludkiewicz 			hw->flags |= I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE;
53930cf856aSJaroslaw Gawin 
54030cf856aSJaroslaw Gawin 		if (aq->api_maj_ver > 1 ||
54130cf856aSJaroslaw Gawin 		    (aq->api_maj_ver == 1 &&
54230cf856aSJaroslaw Gawin 		     aq->api_min_ver >= I40E_MINOR_VER_FW_REQUEST_FEC_X722))
54330cf856aSJaroslaw Gawin 			hw->flags |= I40E_HW_FLAG_X722_FEC_REQUEST_CAPABLE;
54430cf856aSJaroslaw Gawin 
5455463fce6SJeff Kirsher 		fallthrough;
546a3e09dedSPiotr Azarewicz 	default:
547a3e09dedSPiotr Azarewicz 		break;
548a3e09dedSPiotr Azarewicz 	}
549a3e09dedSPiotr Azarewicz 
550a3e09dedSPiotr Azarewicz 	/* Newer versions of firmware require lock when reading the NVM */
551a3e09dedSPiotr Azarewicz 	if (aq->api_maj_ver > 1 ||
552a3e09dedSPiotr Azarewicz 	    (aq->api_maj_ver == 1 &&
553a3e09dedSPiotr Azarewicz 	     aq->api_min_ver >= 5))
554a3e09dedSPiotr Azarewicz 		hw->flags |= I40E_HW_FLAG_NVM_READ_REQUIRES_LOCK;
555a3e09dedSPiotr Azarewicz 
556a3e09dedSPiotr Azarewicz 	if (aq->api_maj_ver > 1 ||
557a3e09dedSPiotr Azarewicz 	    (aq->api_maj_ver == 1 &&
558a3e09dedSPiotr Azarewicz 	     aq->api_min_ver >= 8)) {
559a3e09dedSPiotr Azarewicz 		hw->flags |= I40E_HW_FLAG_FW_LLDP_PERSISTENT;
560a3e09dedSPiotr Azarewicz 		hw->flags |= I40E_HW_FLAG_DROP_MODE;
561a3e09dedSPiotr Azarewicz 	}
562a3e09dedSPiotr Azarewicz 
563a3e09dedSPiotr Azarewicz 	if (aq->api_maj_ver > 1 ||
564a3e09dedSPiotr Azarewicz 	    (aq->api_maj_ver == 1 &&
565a3e09dedSPiotr Azarewicz 	     aq->api_min_ver >= 9))
566a3e09dedSPiotr Azarewicz 		hw->flags |= I40E_HW_FLAG_AQ_PHY_ACCESS_EXTENDED;
567a3e09dedSPiotr Azarewicz }
568a3e09dedSPiotr Azarewicz 
569a3e09dedSPiotr Azarewicz /**
57056a62fc8SJesse Brandeburg  *  i40e_init_adminq - main initialization routine for Admin Queue
57156a62fc8SJesse Brandeburg  *  @hw: pointer to the hardware structure
57256a62fc8SJesse Brandeburg  *
57356a62fc8SJesse Brandeburg  *  Prior to calling this function, drivers *MUST* set the following fields
57456a62fc8SJesse Brandeburg  *  in the hw->aq structure:
57556a62fc8SJesse Brandeburg  *     - hw->aq.num_asq_entries
57656a62fc8SJesse Brandeburg  *     - hw->aq.num_arq_entries
57756a62fc8SJesse Brandeburg  *     - hw->aq.arq_buf_size
57856a62fc8SJesse Brandeburg  *     - hw->aq.asq_buf_size
57956a62fc8SJesse Brandeburg  **/
i40e_init_adminq(struct i40e_hw * hw)5805180ff13SJan Sokolowski int i40e_init_adminq(struct i40e_hw *hw)
58156a62fc8SJesse Brandeburg {
582ac24382dSCarolyn Wyborny 	u16 cfg_ptr, oem_hi, oem_lo;
583d4946cf5SShannon Nelson 	u16 eetrack_lo, eetrack_hi;
584d4946cf5SShannon Nelson 	int retry = 0;
5855180ff13SJan Sokolowski 	int ret_code;
58656a62fc8SJesse Brandeburg 
58756a62fc8SJesse Brandeburg 	/* verify input for valid configuration */
58856a62fc8SJesse Brandeburg 	if ((hw->aq.num_arq_entries == 0) ||
58956a62fc8SJesse Brandeburg 	    (hw->aq.num_asq_entries == 0) ||
59056a62fc8SJesse Brandeburg 	    (hw->aq.arq_buf_size == 0) ||
59156a62fc8SJesse Brandeburg 	    (hw->aq.asq_buf_size == 0)) {
592230f3d53SJan Sokolowski 		ret_code = -EIO;
59356a62fc8SJesse Brandeburg 		goto init_adminq_exit;
59456a62fc8SJesse Brandeburg 	}
59556a62fc8SJesse Brandeburg 
59656a62fc8SJesse Brandeburg 	/* Set up register offsets */
59756a62fc8SJesse Brandeburg 	i40e_adminq_init_regs(hw);
59856a62fc8SJesse Brandeburg 
59909c4e56bSKamil Krawczyk 	/* setup ASQ command write back timeout */
60009c4e56bSKamil Krawczyk 	hw->aq.asq_cmd_timeout = I40E_ASQ_CMD_TIMEOUT;
60109c4e56bSKamil Krawczyk 
60256a62fc8SJesse Brandeburg 	/* allocate the ASQ */
60356a62fc8SJesse Brandeburg 	ret_code = i40e_init_asq(hw);
60456a62fc8SJesse Brandeburg 	if (ret_code)
60556a62fc8SJesse Brandeburg 		goto init_adminq_destroy_locks;
60656a62fc8SJesse Brandeburg 
60756a62fc8SJesse Brandeburg 	/* allocate the ARQ */
60856a62fc8SJesse Brandeburg 	ret_code = i40e_init_arq(hw);
60956a62fc8SJesse Brandeburg 	if (ret_code)
61056a62fc8SJesse Brandeburg 		goto init_adminq_free_asq;
61156a62fc8SJesse Brandeburg 
612d4946cf5SShannon Nelson 	/* There are some cases where the firmware may not be quite ready
613d4946cf5SShannon Nelson 	 * for AdminQ operations, so we retry the AdminQ setup a few times
614d4946cf5SShannon Nelson 	 * if we see timeouts in this first AQ call.
615d4946cf5SShannon Nelson 	 */
616d4946cf5SShannon Nelson 	do {
61756a62fc8SJesse Brandeburg 		ret_code = i40e_aq_get_firmware_version(hw,
618d4946cf5SShannon Nelson 							&hw->aq.fw_maj_ver,
619d4946cf5SShannon Nelson 							&hw->aq.fw_min_ver,
6207edf810cSShannon Nelson 							&hw->aq.fw_build,
621d4946cf5SShannon Nelson 							&hw->aq.api_maj_ver,
622d4946cf5SShannon Nelson 							&hw->aq.api_min_ver,
62356a62fc8SJesse Brandeburg 							NULL);
624230f3d53SJan Sokolowski 		if (ret_code != -EIO)
625d4946cf5SShannon Nelson 			break;
626d4946cf5SShannon Nelson 		retry++;
627d4946cf5SShannon Nelson 		msleep(100);
628d4946cf5SShannon Nelson 		i40e_resume_aq(hw);
629d4946cf5SShannon Nelson 	} while (retry < 10);
630230f3d53SJan Sokolowski 	if (ret_code != 0)
63156a62fc8SJesse Brandeburg 		goto init_adminq_free_arq;
63256a62fc8SJesse Brandeburg 
633a3e09dedSPiotr Azarewicz 	/* Some features were introduced in different FW API version
634a3e09dedSPiotr Azarewicz 	 * for different MAC type.
635a3e09dedSPiotr Azarewicz 	 */
636a3e09dedSPiotr Azarewicz 	i40e_set_hw_flags(hw);
637a3e09dedSPiotr Azarewicz 
638981b7545SShannon Nelson 	/* get the NVM version info */
6394f651a5bSShannon Nelson 	i40e_read_nvm_word(hw, I40E_SR_NVM_DEV_STARTER_VERSION,
6404f651a5bSShannon Nelson 			   &hw->nvm.version);
64156a62fc8SJesse Brandeburg 	i40e_read_nvm_word(hw, I40E_SR_NVM_EETRACK_LO, &eetrack_lo);
64256a62fc8SJesse Brandeburg 	i40e_read_nvm_word(hw, I40E_SR_NVM_EETRACK_HI, &eetrack_hi);
64356a62fc8SJesse Brandeburg 	hw->nvm.eetrack = (eetrack_hi << 16) | eetrack_lo;
644ac24382dSCarolyn Wyborny 	i40e_read_nvm_word(hw, I40E_SR_BOOT_CONFIG_PTR, &cfg_ptr);
645ac24382dSCarolyn Wyborny 	i40e_read_nvm_word(hw, (cfg_ptr + I40E_NVM_OEM_VER_OFF),
646ac24382dSCarolyn Wyborny 			   &oem_hi);
647ac24382dSCarolyn Wyborny 	i40e_read_nvm_word(hw, (cfg_ptr + (I40E_NVM_OEM_VER_OFF + 1)),
648ac24382dSCarolyn Wyborny 			   &oem_lo);
649ac24382dSCarolyn Wyborny 	hw->nvm.oem_ver = ((u32)oem_hi << 16) | oem_lo;
65056a62fc8SJesse Brandeburg 
65100f6c2f5SMariusz Stachura 	if (hw->mac.type == I40E_MAC_XL710 &&
65200f6c2f5SMariusz Stachura 	    hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
65300f6c2f5SMariusz Stachura 	    hw->aq.api_min_ver >= I40E_MINOR_VER_GET_LINK_INFO_XL710) {
65400f6c2f5SMariusz Stachura 		hw->flags |= I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE;
655de10933eSKrzysztof Galazka 		hw->flags |= I40E_HW_FLAG_FW_LLDP_STOPPABLE;
656de10933eSKrzysztof Galazka 	}
657de10933eSKrzysztof Galazka 	if (hw->mac.type == I40E_MAC_X722 &&
658de10933eSKrzysztof Galazka 	    hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
659de10933eSKrzysztof Galazka 	    hw->aq.api_min_ver >= I40E_MINOR_VER_FW_LLDP_STOPPABLE_X722) {
660de10933eSKrzysztof Galazka 		hw->flags |= I40E_HW_FLAG_FW_LLDP_STOPPABLE;
66100f6c2f5SMariusz Stachura 	}
66200f6c2f5SMariusz Stachura 
663ab243ec9SScott Peterson 	/* The ability to RX (not drop) 802.1ad frames was added in API 1.7 */
664ab243ec9SScott Peterson 	if (hw->aq.api_maj_ver > 1 ||
665ab243ec9SScott Peterson 	    (hw->aq.api_maj_ver == 1 &&
666ab243ec9SScott Peterson 	     hw->aq.api_min_ver >= 7))
667ab243ec9SScott Peterson 		hw->flags |= I40E_HW_FLAG_802_1AD_CAPABLE;
668ab243ec9SScott Peterson 
6697e612411SShannon Nelson 	if (hw->aq.api_maj_ver > I40E_FW_API_VERSION_MAJOR) {
670230f3d53SJan Sokolowski 		ret_code = -EIO;
671981b7545SShannon Nelson 		goto init_adminq_free_arq;
672981b7545SShannon Nelson 	}
673981b7545SShannon Nelson 
674ff2ff3b4SShannon Nelson 	/* pre-emptive resource lock release */
675ff2ff3b4SShannon Nelson 	i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL);
676437f82a2SShannon Nelson 	hw->nvm_release_on_done = false;
6770f52958bSShannon Nelson 	hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
678ff2ff3b4SShannon Nelson 
67956a62fc8SJesse Brandeburg 	ret_code = 0;
68056a62fc8SJesse Brandeburg 
68156a62fc8SJesse Brandeburg 	/* success! */
68256a62fc8SJesse Brandeburg 	goto init_adminq_exit;
68356a62fc8SJesse Brandeburg 
68456a62fc8SJesse Brandeburg init_adminq_free_arq:
68556a62fc8SJesse Brandeburg 	i40e_shutdown_arq(hw);
68656a62fc8SJesse Brandeburg init_adminq_free_asq:
68756a62fc8SJesse Brandeburg 	i40e_shutdown_asq(hw);
68856a62fc8SJesse Brandeburg init_adminq_destroy_locks:
68956a62fc8SJesse Brandeburg 
69056a62fc8SJesse Brandeburg init_adminq_exit:
69156a62fc8SJesse Brandeburg 	return ret_code;
69256a62fc8SJesse Brandeburg }
69356a62fc8SJesse Brandeburg 
69456a62fc8SJesse Brandeburg /**
69556a62fc8SJesse Brandeburg  *  i40e_shutdown_adminq - shutdown routine for the Admin Queue
69656a62fc8SJesse Brandeburg  *  @hw: pointer to the hardware structure
69756a62fc8SJesse Brandeburg  **/
i40e_shutdown_adminq(struct i40e_hw * hw)6983f6023f7SJason Yan void i40e_shutdown_adminq(struct i40e_hw *hw)
69956a62fc8SJesse Brandeburg {
700e1860d8fSAnjali Singhai Jain 	if (i40e_check_asq_alive(hw))
701e1860d8fSAnjali Singhai Jain 		i40e_aq_queue_shutdown(hw, true);
702e1860d8fSAnjali Singhai Jain 
70356a62fc8SJesse Brandeburg 	i40e_shutdown_asq(hw);
70456a62fc8SJesse Brandeburg 	i40e_shutdown_arq(hw);
70556a62fc8SJesse Brandeburg 
706e4c83c20SShannon Nelson 	if (hw->nvm_buff.va)
707e4c83c20SShannon Nelson 		i40e_free_virt_mem(hw, &hw->nvm_buff);
70856a62fc8SJesse Brandeburg }
70956a62fc8SJesse Brandeburg 
71056a62fc8SJesse Brandeburg /**
71156a62fc8SJesse Brandeburg  *  i40e_clean_asq - cleans Admin send queue
71298d44381SJeff Kirsher  *  @hw: pointer to the hardware structure
71356a62fc8SJesse Brandeburg  *
71456a62fc8SJesse Brandeburg  *  returns the number of free desc
71556a62fc8SJesse Brandeburg  **/
i40e_clean_asq(struct i40e_hw * hw)71656a62fc8SJesse Brandeburg static u16 i40e_clean_asq(struct i40e_hw *hw)
71756a62fc8SJesse Brandeburg {
71856a62fc8SJesse Brandeburg 	struct i40e_adminq_ring *asq = &(hw->aq.asq);
71956a62fc8SJesse Brandeburg 	struct i40e_asq_cmd_details *details;
72056a62fc8SJesse Brandeburg 	u16 ntc = asq->next_to_clean;
72156a62fc8SJesse Brandeburg 	struct i40e_aq_desc desc_cb;
72256a62fc8SJesse Brandeburg 	struct i40e_aq_desc *desc;
72356a62fc8SJesse Brandeburg 
72456a62fc8SJesse Brandeburg 	desc = I40E_ADMINQ_DESC(*asq, ntc);
72556a62fc8SJesse Brandeburg 	details = I40E_ADMINQ_DETAILS(*asq, ntc);
72656a62fc8SJesse Brandeburg 	while (rd32(hw, hw->aq.asq.head) != ntc) {
727b83ebf50SDoug Dziggel 		i40e_debug(hw, I40E_DEBUG_AQ_COMMAND,
7286995b36cSJesse Brandeburg 			   "ntc %d head %d.\n", ntc, rd32(hw, hw->aq.asq.head));
72980a977e7SMichal Kosiarz 
73056a62fc8SJesse Brandeburg 		if (details->callback) {
73156a62fc8SJesse Brandeburg 			I40E_ADMINQ_CALLBACK cb_func =
73256a62fc8SJesse Brandeburg 					(I40E_ADMINQ_CALLBACK)details->callback;
73356a62fc8SJesse Brandeburg 			desc_cb = *desc;
73456a62fc8SJesse Brandeburg 			cb_func(hw, &desc_cb);
73556a62fc8SJesse Brandeburg 		}
736a63fa1cdSMitch Williams 		memset(desc, 0, sizeof(*desc));
737a63fa1cdSMitch Williams 		memset(details, 0, sizeof(*details));
73856a62fc8SJesse Brandeburg 		ntc++;
73956a62fc8SJesse Brandeburg 		if (ntc == asq->count)
74056a62fc8SJesse Brandeburg 			ntc = 0;
74156a62fc8SJesse Brandeburg 		desc = I40E_ADMINQ_DESC(*asq, ntc);
74256a62fc8SJesse Brandeburg 		details = I40E_ADMINQ_DETAILS(*asq, ntc);
74356a62fc8SJesse Brandeburg 	}
74456a62fc8SJesse Brandeburg 
74556a62fc8SJesse Brandeburg 	asq->next_to_clean = ntc;
74656a62fc8SJesse Brandeburg 
74756a62fc8SJesse Brandeburg 	return I40E_DESC_UNUSED(asq);
74856a62fc8SJesse Brandeburg }
74956a62fc8SJesse Brandeburg 
75056a62fc8SJesse Brandeburg /**
75156a62fc8SJesse Brandeburg  *  i40e_asq_done - check if FW has processed the Admin Send Queue
75256a62fc8SJesse Brandeburg  *  @hw: pointer to the hw struct
75356a62fc8SJesse Brandeburg  *
75456a62fc8SJesse Brandeburg  *  Returns true if the firmware has processed all descriptors on the
75556a62fc8SJesse Brandeburg  *  admin send queue. Returns false if there are still requests pending.
75656a62fc8SJesse Brandeburg  **/
i40e_asq_done(struct i40e_hw * hw)757af28eec9SStephen Hemminger static bool i40e_asq_done(struct i40e_hw *hw)
75856a62fc8SJesse Brandeburg {
75956a62fc8SJesse Brandeburg 	/* AQ designers suggest use of head for better
76056a62fc8SJesse Brandeburg 	 * timing reliability than DD bit
76156a62fc8SJesse Brandeburg 	 */
762922680b9SShannon Nelson 	return rd32(hw, hw->aq.asq.head) == hw->aq.asq.next_to_use;
76356a62fc8SJesse Brandeburg 
76456a62fc8SJesse Brandeburg }
76556a62fc8SJesse Brandeburg 
76656a62fc8SJesse Brandeburg /**
76774073848SJedrzej Jagielski  *  i40e_asq_send_command_atomic_exec - send command to Admin Queue
76856a62fc8SJesse Brandeburg  *  @hw: pointer to the hw struct
76956a62fc8SJesse Brandeburg  *  @desc: prefilled descriptor describing the command (non DMA mem)
77056a62fc8SJesse Brandeburg  *  @buff: buffer to use for indirect commands
77156a62fc8SJesse Brandeburg  *  @buff_size: size of buffer for indirect commands
772922680b9SShannon Nelson  *  @cmd_details: pointer to command details structure
773ef39584dSJedrzej Jagielski  *  @is_atomic_context: is the function called in an atomic context?
77456a62fc8SJesse Brandeburg  *
77556a62fc8SJesse Brandeburg  *  This is the main send command driver routine for the Admin Queue send
77656a62fc8SJesse Brandeburg  *  queue.  It runs the queue, cleans the queue, etc
77756a62fc8SJesse Brandeburg  **/
7785180ff13SJan Sokolowski static int
i40e_asq_send_command_atomic_exec(struct i40e_hw * hw,struct i40e_aq_desc * desc,void * buff,u16 buff_size,struct i40e_asq_cmd_details * cmd_details,bool is_atomic_context)77974073848SJedrzej Jagielski i40e_asq_send_command_atomic_exec(struct i40e_hw *hw,
78074073848SJedrzej Jagielski 				  struct i40e_aq_desc *desc,
78174073848SJedrzej Jagielski 				  void *buff, /* can be NULL */
78274073848SJedrzej Jagielski 				  u16  buff_size,
783ef39584dSJedrzej Jagielski 				  struct i40e_asq_cmd_details *cmd_details,
784ef39584dSJedrzej Jagielski 				  bool is_atomic_context)
78556a62fc8SJesse Brandeburg {
78656a62fc8SJesse Brandeburg 	struct i40e_dma_mem *dma_buff = NULL;
78756a62fc8SJesse Brandeburg 	struct i40e_asq_cmd_details *details;
78856a62fc8SJesse Brandeburg 	struct i40e_aq_desc *desc_on_ring;
78956a62fc8SJesse Brandeburg 	bool cmd_completed = false;
79056a62fc8SJesse Brandeburg 	u16  retval = 0;
7915180ff13SJan Sokolowski 	int status = 0;
79280a977e7SMichal Kosiarz 	u32  val = 0;
79380a977e7SMichal Kosiarz 
79456a62fc8SJesse Brandeburg 	if (hw->aq.asq.count == 0) {
79556a62fc8SJesse Brandeburg 		i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
79656a62fc8SJesse Brandeburg 			   "AQTX: Admin queue not initialized.\n");
797230f3d53SJan Sokolowski 		status = -EIO;
79824408e7aSShannon Nelson 		goto asq_send_command_error;
79924408e7aSShannon Nelson 	}
80024408e7aSShannon Nelson 
8019e1c26e3SShannon Nelson 	hw->aq.asq_last_status = I40E_AQ_RC_OK;
8029e1c26e3SShannon Nelson 
80324408e7aSShannon Nelson 	val = rd32(hw, hw->aq.asq.head);
80424408e7aSShannon Nelson 	if (val >= hw->aq.num_asq_entries) {
80524408e7aSShannon Nelson 		i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
80624408e7aSShannon Nelson 			   "AQTX: head overrun at %d\n", val);
807230f3d53SJan Sokolowski 		status = -ENOSPC;
80824408e7aSShannon Nelson 		goto asq_send_command_error;
80956a62fc8SJesse Brandeburg 	}
81056a62fc8SJesse Brandeburg 
81156a62fc8SJesse Brandeburg 	details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use);
81256a62fc8SJesse Brandeburg 	if (cmd_details) {
813d7595a22SJesse Brandeburg 		*details = *cmd_details;
81456a62fc8SJesse Brandeburg 
81556a62fc8SJesse Brandeburg 		/* If the cmd_details are defined copy the cookie.  The
81656a62fc8SJesse Brandeburg 		 * cpu_to_le32 is not needed here because the data is ignored
81756a62fc8SJesse Brandeburg 		 * by the FW, only used by the driver
81856a62fc8SJesse Brandeburg 		 */
81956a62fc8SJesse Brandeburg 		if (details->cookie) {
82056a62fc8SJesse Brandeburg 			desc->cookie_high =
82156a62fc8SJesse Brandeburg 				cpu_to_le32(upper_32_bits(details->cookie));
82256a62fc8SJesse Brandeburg 			desc->cookie_low =
82356a62fc8SJesse Brandeburg 				cpu_to_le32(lower_32_bits(details->cookie));
82456a62fc8SJesse Brandeburg 		}
82556a62fc8SJesse Brandeburg 	} else {
82656a62fc8SJesse Brandeburg 		memset(details, 0, sizeof(struct i40e_asq_cmd_details));
82756a62fc8SJesse Brandeburg 	}
82856a62fc8SJesse Brandeburg 
82956a62fc8SJesse Brandeburg 	/* clear requested flags and then set additional flags if defined */
83056a62fc8SJesse Brandeburg 	desc->flags &= ~cpu_to_le16(details->flags_dis);
83156a62fc8SJesse Brandeburg 	desc->flags |= cpu_to_le16(details->flags_ena);
83256a62fc8SJesse Brandeburg 
83356a62fc8SJesse Brandeburg 	if (buff_size > hw->aq.asq_buf_size) {
83456a62fc8SJesse Brandeburg 		i40e_debug(hw,
83556a62fc8SJesse Brandeburg 			   I40E_DEBUG_AQ_MESSAGE,
83656a62fc8SJesse Brandeburg 			   "AQTX: Invalid buffer size: %d.\n",
83756a62fc8SJesse Brandeburg 			   buff_size);
838230f3d53SJan Sokolowski 		status = -EINVAL;
83956a62fc8SJesse Brandeburg 		goto asq_send_command_error;
84056a62fc8SJesse Brandeburg 	}
84156a62fc8SJesse Brandeburg 
84256a62fc8SJesse Brandeburg 	if (details->postpone && !details->async) {
84356a62fc8SJesse Brandeburg 		i40e_debug(hw,
84456a62fc8SJesse Brandeburg 			   I40E_DEBUG_AQ_MESSAGE,
84556a62fc8SJesse Brandeburg 			   "AQTX: Async flag not set along with postpone flag");
846230f3d53SJan Sokolowski 		status = -EINVAL;
84756a62fc8SJesse Brandeburg 		goto asq_send_command_error;
84856a62fc8SJesse Brandeburg 	}
84956a62fc8SJesse Brandeburg 
85056a62fc8SJesse Brandeburg 	/* call clean and check queue available function to reclaim the
85156a62fc8SJesse Brandeburg 	 * descriptors that were processed by FW, the function returns the
85256a62fc8SJesse Brandeburg 	 * number of desc available
85356a62fc8SJesse Brandeburg 	 */
85456a62fc8SJesse Brandeburg 	/* the clean function called here could be called in a separate thread
85556a62fc8SJesse Brandeburg 	 * in case of asynchronous completions
85656a62fc8SJesse Brandeburg 	 */
85756a62fc8SJesse Brandeburg 	if (i40e_clean_asq(hw) == 0) {
85856a62fc8SJesse Brandeburg 		i40e_debug(hw,
85956a62fc8SJesse Brandeburg 			   I40E_DEBUG_AQ_MESSAGE,
86056a62fc8SJesse Brandeburg 			   "AQTX: Error queue is full.\n");
861230f3d53SJan Sokolowski 		status = -ENOSPC;
86256a62fc8SJesse Brandeburg 		goto asq_send_command_error;
86356a62fc8SJesse Brandeburg 	}
86456a62fc8SJesse Brandeburg 
86556a62fc8SJesse Brandeburg 	/* initialize the temp desc pointer with the right desc */
86656a62fc8SJesse Brandeburg 	desc_on_ring = I40E_ADMINQ_DESC(hw->aq.asq, hw->aq.asq.next_to_use);
86756a62fc8SJesse Brandeburg 
86856a62fc8SJesse Brandeburg 	/* if the desc is available copy the temp desc to the right place */
869d7595a22SJesse Brandeburg 	*desc_on_ring = *desc;
87056a62fc8SJesse Brandeburg 
87156a62fc8SJesse Brandeburg 	/* if buff is not NULL assume indirect command */
87256a62fc8SJesse Brandeburg 	if (buff != NULL) {
87356a62fc8SJesse Brandeburg 		dma_buff = &(hw->aq.asq.r.asq_bi[hw->aq.asq.next_to_use]);
87456a62fc8SJesse Brandeburg 		/* copy the user buff into the respective DMA buff */
87556a62fc8SJesse Brandeburg 		memcpy(dma_buff->va, buff, buff_size);
87656a62fc8SJesse Brandeburg 		desc_on_ring->datalen = cpu_to_le16(buff_size);
87756a62fc8SJesse Brandeburg 
87856a62fc8SJesse Brandeburg 		/* Update the address values in the desc with the pa value
87956a62fc8SJesse Brandeburg 		 * for respective buffer
88056a62fc8SJesse Brandeburg 		 */
88156a62fc8SJesse Brandeburg 		desc_on_ring->params.external.addr_high =
88256a62fc8SJesse Brandeburg 				cpu_to_le32(upper_32_bits(dma_buff->pa));
88356a62fc8SJesse Brandeburg 		desc_on_ring->params.external.addr_low =
88456a62fc8SJesse Brandeburg 				cpu_to_le32(lower_32_bits(dma_buff->pa));
88556a62fc8SJesse Brandeburg 	}
88656a62fc8SJesse Brandeburg 
88756a62fc8SJesse Brandeburg 	/* bump the tail */
888b83ebf50SDoug Dziggel 	i40e_debug(hw, I40E_DEBUG_AQ_COMMAND, "AQTX: desc and buffer:\n");
889f905dd62SShannon Nelson 	i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc_on_ring,
890f905dd62SShannon Nelson 		      buff, buff_size);
89156a62fc8SJesse Brandeburg 	(hw->aq.asq.next_to_use)++;
89256a62fc8SJesse Brandeburg 	if (hw->aq.asq.next_to_use == hw->aq.asq.count)
89356a62fc8SJesse Brandeburg 		hw->aq.asq.next_to_use = 0;
89456a62fc8SJesse Brandeburg 	if (!details->postpone)
89556a62fc8SJesse Brandeburg 		wr32(hw, hw->aq.asq.tail, hw->aq.asq.next_to_use);
89656a62fc8SJesse Brandeburg 
89756a62fc8SJesse Brandeburg 	/* if cmd_details are not defined or async flag is not set,
89856a62fc8SJesse Brandeburg 	 * we need to wait for desc write back
89956a62fc8SJesse Brandeburg 	 */
90056a62fc8SJesse Brandeburg 	if (!details->async && !details->postpone) {
90156a62fc8SJesse Brandeburg 		u32 total_delay = 0;
90256a62fc8SJesse Brandeburg 
90356a62fc8SJesse Brandeburg 		do {
90456a62fc8SJesse Brandeburg 			/* AQ designers suggest use of head for better
90556a62fc8SJesse Brandeburg 			 * timing reliability than DD bit
90656a62fc8SJesse Brandeburg 			 */
90756a62fc8SJesse Brandeburg 			if (i40e_asq_done(hw))
90856a62fc8SJesse Brandeburg 				break;
909ef39584dSJedrzej Jagielski 
910ef39584dSJedrzej Jagielski 			if (is_atomic_context)
9119e3f23f4SJacob Keller 				udelay(50);
912ef39584dSJedrzej Jagielski 			else
913ef39584dSJedrzej Jagielski 				usleep_range(40, 60);
914ef39584dSJedrzej Jagielski 
9159e3f23f4SJacob Keller 			total_delay += 50;
91609c4e56bSKamil Krawczyk 		} while (total_delay < hw->aq.asq_cmd_timeout);
91756a62fc8SJesse Brandeburg 	}
91856a62fc8SJesse Brandeburg 
91956a62fc8SJesse Brandeburg 	/* if ready, copy the desc back to temp */
92056a62fc8SJesse Brandeburg 	if (i40e_asq_done(hw)) {
921d7595a22SJesse Brandeburg 		*desc = *desc_on_ring;
92256a62fc8SJesse Brandeburg 		if (buff != NULL)
92356a62fc8SJesse Brandeburg 			memcpy(buff, dma_buff->va, buff_size);
92456a62fc8SJesse Brandeburg 		retval = le16_to_cpu(desc->retval);
92556a62fc8SJesse Brandeburg 		if (retval != 0) {
92656a62fc8SJesse Brandeburg 			i40e_debug(hw,
92756a62fc8SJesse Brandeburg 				   I40E_DEBUG_AQ_MESSAGE,
92856a62fc8SJesse Brandeburg 				   "AQTX: Command completed with error 0x%X.\n",
92956a62fc8SJesse Brandeburg 				   retval);
93066d90e7dSKamil Krawczyk 
93156a62fc8SJesse Brandeburg 			/* strip off FW internal code */
93256a62fc8SJesse Brandeburg 			retval &= 0xff;
93356a62fc8SJesse Brandeburg 		}
93456a62fc8SJesse Brandeburg 		cmd_completed = true;
93556a62fc8SJesse Brandeburg 		if ((enum i40e_admin_queue_err)retval == I40E_AQ_RC_OK)
93656a62fc8SJesse Brandeburg 			status = 0;
937b2b57b29SPiotr Azarewicz 		else if ((enum i40e_admin_queue_err)retval == I40E_AQ_RC_EBUSY)
938230f3d53SJan Sokolowski 			status = -EBUSY;
93956a62fc8SJesse Brandeburg 		else
940230f3d53SJan Sokolowski 			status = -EIO;
94156a62fc8SJesse Brandeburg 		hw->aq.asq_last_status = (enum i40e_admin_queue_err)retval;
94256a62fc8SJesse Brandeburg 	}
94356a62fc8SJesse Brandeburg 
944b83ebf50SDoug Dziggel 	i40e_debug(hw, I40E_DEBUG_AQ_COMMAND,
94566d90e7dSKamil Krawczyk 		   "AQTX: desc and buffer writeback:\n");
946f905dd62SShannon Nelson 	i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, buff, buff_size);
94766d90e7dSKamil Krawczyk 
94887db27a9SShannon Nelson 	/* save writeback aq if requested */
94987db27a9SShannon Nelson 	if (details->wb_desc)
95087db27a9SShannon Nelson 		*details->wb_desc = *desc_on_ring;
95187db27a9SShannon Nelson 
95256a62fc8SJesse Brandeburg 	/* update the error if time out occurred */
95356a62fc8SJesse Brandeburg 	if ((!cmd_completed) &&
95456a62fc8SJesse Brandeburg 	    (!details->async && !details->postpone)) {
955f34e308bSMichal Kosiarz 		if (rd32(hw, hw->aq.asq.len) & I40E_GL_ATQLEN_ATQCRIT_MASK) {
956f34e308bSMichal Kosiarz 			i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
957f34e308bSMichal Kosiarz 				   "AQTX: AQ Critical error.\n");
958230f3d53SJan Sokolowski 			status = -EIO;
959f34e308bSMichal Kosiarz 		} else {
960f34e308bSMichal Kosiarz 			i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
96156a62fc8SJesse Brandeburg 				   "AQTX: Writeback timeout.\n");
962230f3d53SJan Sokolowski 			status = -EIO;
96356a62fc8SJesse Brandeburg 		}
964f34e308bSMichal Kosiarz 	}
96556a62fc8SJesse Brandeburg 
96656a62fc8SJesse Brandeburg asq_send_command_error:
96774073848SJedrzej Jagielski 	return status;
96874073848SJedrzej Jagielski }
96974073848SJedrzej Jagielski 
97074073848SJedrzej Jagielski /**
97174073848SJedrzej Jagielski  *  i40e_asq_send_command_atomic - send command to Admin Queue
97274073848SJedrzej Jagielski  *  @hw: pointer to the hw struct
97374073848SJedrzej Jagielski  *  @desc: prefilled descriptor describing the command (non DMA mem)
97474073848SJedrzej Jagielski  *  @buff: buffer to use for indirect commands
97574073848SJedrzej Jagielski  *  @buff_size: size of buffer for indirect commands
97674073848SJedrzej Jagielski  *  @cmd_details: pointer to command details structure
97774073848SJedrzej Jagielski  *  @is_atomic_context: is the function called in an atomic context?
97874073848SJedrzej Jagielski  *
97974073848SJedrzej Jagielski  *  Acquires the lock and calls the main send command execution
98074073848SJedrzej Jagielski  *  routine.
98174073848SJedrzej Jagielski  **/
9825180ff13SJan Sokolowski int
i40e_asq_send_command_atomic(struct i40e_hw * hw,struct i40e_aq_desc * desc,void * buff,u16 buff_size,struct i40e_asq_cmd_details * cmd_details,bool is_atomic_context)98374073848SJedrzej Jagielski i40e_asq_send_command_atomic(struct i40e_hw *hw,
98474073848SJedrzej Jagielski 			     struct i40e_aq_desc *desc,
98574073848SJedrzej Jagielski 			     void *buff, /* can be NULL */
98674073848SJedrzej Jagielski 			     u16  buff_size,
98774073848SJedrzej Jagielski 			     struct i40e_asq_cmd_details *cmd_details,
98874073848SJedrzej Jagielski 			     bool is_atomic_context)
98974073848SJedrzej Jagielski {
9905180ff13SJan Sokolowski 	int status;
99174073848SJedrzej Jagielski 
99274073848SJedrzej Jagielski 	mutex_lock(&hw->aq.asq_mutex);
99374073848SJedrzej Jagielski 	status = i40e_asq_send_command_atomic_exec(hw, desc, buff, buff_size,
99474073848SJedrzej Jagielski 						   cmd_details,
99574073848SJedrzej Jagielski 						   is_atomic_context);
99674073848SJedrzej Jagielski 
99756a62fc8SJesse Brandeburg 	mutex_unlock(&hw->aq.asq_mutex);
99856a62fc8SJesse Brandeburg 	return status;
99956a62fc8SJesse Brandeburg }
100056a62fc8SJesse Brandeburg 
10015180ff13SJan Sokolowski int
i40e_asq_send_command(struct i40e_hw * hw,struct i40e_aq_desc * desc,void * buff,u16 buff_size,struct i40e_asq_cmd_details * cmd_details)1002ef39584dSJedrzej Jagielski i40e_asq_send_command(struct i40e_hw *hw, struct i40e_aq_desc *desc,
1003ef39584dSJedrzej Jagielski 		      void *buff, /* can be NULL */ u16  buff_size,
1004ef39584dSJedrzej Jagielski 		      struct i40e_asq_cmd_details *cmd_details)
1005ef39584dSJedrzej Jagielski {
1006ef39584dSJedrzej Jagielski 	return i40e_asq_send_command_atomic(hw, desc, buff, buff_size,
1007ef39584dSJedrzej Jagielski 					    cmd_details, false);
1008ef39584dSJedrzej Jagielski }
1009ef39584dSJedrzej Jagielski 
101056a62fc8SJesse Brandeburg /**
101174073848SJedrzej Jagielski  *  i40e_asq_send_command_atomic_v2 - send command to Admin Queue
101274073848SJedrzej Jagielski  *  @hw: pointer to the hw struct
101374073848SJedrzej Jagielski  *  @desc: prefilled descriptor describing the command (non DMA mem)
101474073848SJedrzej Jagielski  *  @buff: buffer to use for indirect commands
101574073848SJedrzej Jagielski  *  @buff_size: size of buffer for indirect commands
101674073848SJedrzej Jagielski  *  @cmd_details: pointer to command details structure
101774073848SJedrzej Jagielski  *  @is_atomic_context: is the function called in an atomic context?
101874073848SJedrzej Jagielski  *  @aq_status: pointer to Admin Queue status return value
101974073848SJedrzej Jagielski  *
102074073848SJedrzej Jagielski  *  Acquires the lock and calls the main send command execution
102174073848SJedrzej Jagielski  *  routine. Returns the last Admin Queue status in aq_status
102274073848SJedrzej Jagielski  *  to avoid race conditions in access to hw->aq.asq_last_status.
102374073848SJedrzej Jagielski  **/
10245180ff13SJan Sokolowski int
i40e_asq_send_command_atomic_v2(struct i40e_hw * hw,struct i40e_aq_desc * desc,void * buff,u16 buff_size,struct i40e_asq_cmd_details * cmd_details,bool is_atomic_context,enum i40e_admin_queue_err * aq_status)102574073848SJedrzej Jagielski i40e_asq_send_command_atomic_v2(struct i40e_hw *hw,
102674073848SJedrzej Jagielski 				struct i40e_aq_desc *desc,
102774073848SJedrzej Jagielski 				void *buff, /* can be NULL */
102874073848SJedrzej Jagielski 				u16  buff_size,
102974073848SJedrzej Jagielski 				struct i40e_asq_cmd_details *cmd_details,
103074073848SJedrzej Jagielski 				bool is_atomic_context,
103174073848SJedrzej Jagielski 				enum i40e_admin_queue_err *aq_status)
103274073848SJedrzej Jagielski {
10335180ff13SJan Sokolowski 	int status;
103474073848SJedrzej Jagielski 
103574073848SJedrzej Jagielski 	mutex_lock(&hw->aq.asq_mutex);
103674073848SJedrzej Jagielski 	status = i40e_asq_send_command_atomic_exec(hw, desc, buff,
103774073848SJedrzej Jagielski 						   buff_size,
103874073848SJedrzej Jagielski 						   cmd_details,
103974073848SJedrzej Jagielski 						   is_atomic_context);
104074073848SJedrzej Jagielski 	if (aq_status)
104174073848SJedrzej Jagielski 		*aq_status = hw->aq.asq_last_status;
104274073848SJedrzej Jagielski 	mutex_unlock(&hw->aq.asq_mutex);
104374073848SJedrzej Jagielski 	return status;
104474073848SJedrzej Jagielski }
104574073848SJedrzej Jagielski 
10465180ff13SJan Sokolowski int
i40e_asq_send_command_v2(struct i40e_hw * hw,struct i40e_aq_desc * desc,void * buff,u16 buff_size,struct i40e_asq_cmd_details * cmd_details,enum i40e_admin_queue_err * aq_status)104774073848SJedrzej Jagielski i40e_asq_send_command_v2(struct i40e_hw *hw, struct i40e_aq_desc *desc,
104874073848SJedrzej Jagielski 			 void *buff, /* can be NULL */ u16  buff_size,
104974073848SJedrzej Jagielski 			 struct i40e_asq_cmd_details *cmd_details,
105074073848SJedrzej Jagielski 			 enum i40e_admin_queue_err *aq_status)
105174073848SJedrzej Jagielski {
105274073848SJedrzej Jagielski 	return i40e_asq_send_command_atomic_v2(hw, desc, buff, buff_size,
105374073848SJedrzej Jagielski 					       cmd_details, true, aq_status);
105474073848SJedrzej Jagielski }
105574073848SJedrzej Jagielski 
105674073848SJedrzej Jagielski /**
105756a62fc8SJesse Brandeburg  *  i40e_fill_default_direct_cmd_desc - AQ descriptor helper function
105856a62fc8SJesse Brandeburg  *  @desc:     pointer to the temp descriptor (non DMA mem)
105956a62fc8SJesse Brandeburg  *  @opcode:   the opcode can be used to decide which flags to turn off or on
106056a62fc8SJesse Brandeburg  *
106156a62fc8SJesse Brandeburg  *  Fill the desc with default values
106256a62fc8SJesse Brandeburg  **/
i40e_fill_default_direct_cmd_desc(struct i40e_aq_desc * desc,u16 opcode)106356a62fc8SJesse Brandeburg void i40e_fill_default_direct_cmd_desc(struct i40e_aq_desc *desc,
106456a62fc8SJesse Brandeburg 				       u16 opcode)
106556a62fc8SJesse Brandeburg {
106656a62fc8SJesse Brandeburg 	/* zero out the desc */
106756a62fc8SJesse Brandeburg 	memset((void *)desc, 0, sizeof(struct i40e_aq_desc));
106856a62fc8SJesse Brandeburg 	desc->opcode = cpu_to_le16(opcode);
1069ab954cbaSShannon Nelson 	desc->flags = cpu_to_le16(I40E_AQ_FLAG_SI);
107056a62fc8SJesse Brandeburg }
107156a62fc8SJesse Brandeburg 
107256a62fc8SJesse Brandeburg /**
107356a62fc8SJesse Brandeburg  *  i40e_clean_arq_element
107456a62fc8SJesse Brandeburg  *  @hw: pointer to the hw struct
107556a62fc8SJesse Brandeburg  *  @e: event info from the receive descriptor, includes any buffers
107656a62fc8SJesse Brandeburg  *  @pending: number of events that could be left to process
107756a62fc8SJesse Brandeburg  *
107856a62fc8SJesse Brandeburg  *  This function cleans one Admin Receive Queue element and returns
107956a62fc8SJesse Brandeburg  *  the contents through e.  It can also return how many events are
108056a62fc8SJesse Brandeburg  *  left to process through 'pending'
108156a62fc8SJesse Brandeburg  **/
i40e_clean_arq_element(struct i40e_hw * hw,struct i40e_arq_event_info * e,u16 * pending)10825180ff13SJan Sokolowski int i40e_clean_arq_element(struct i40e_hw *hw,
108356a62fc8SJesse Brandeburg 			   struct i40e_arq_event_info *e,
108456a62fc8SJesse Brandeburg 			   u16 *pending)
108556a62fc8SJesse Brandeburg {
108656a62fc8SJesse Brandeburg 	u16 ntc = hw->aq.arq.next_to_clean;
108756a62fc8SJesse Brandeburg 	struct i40e_aq_desc *desc;
108856a62fc8SJesse Brandeburg 	struct i40e_dma_mem *bi;
10895180ff13SJan Sokolowski 	int ret_code = 0;
109056a62fc8SJesse Brandeburg 	u16 desc_idx;
109156a62fc8SJesse Brandeburg 	u16 datalen;
109256a62fc8SJesse Brandeburg 	u16 flags;
109356a62fc8SJesse Brandeburg 	u16 ntu;
109456a62fc8SJesse Brandeburg 
109573b03f98SShannon Nelson 	/* pre-clean the event info */
109673b03f98SShannon Nelson 	memset(&e->desc, 0, sizeof(e->desc));
109773b03f98SShannon Nelson 
109856a62fc8SJesse Brandeburg 	/* take the lock before we start messing with the ring */
109956a62fc8SJesse Brandeburg 	mutex_lock(&hw->aq.arq_mutex);
110056a62fc8SJesse Brandeburg 
110143ae93a9SMitch Williams 	if (hw->aq.arq.count == 0) {
110243ae93a9SMitch Williams 		i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
110343ae93a9SMitch Williams 			   "AQRX: Admin queue not initialized.\n");
1104230f3d53SJan Sokolowski 		ret_code = -EIO;
110543ae93a9SMitch Williams 		goto clean_arq_element_err;
110643ae93a9SMitch Williams 	}
110743ae93a9SMitch Williams 
110856a62fc8SJesse Brandeburg 	/* set next_to_use to head */
11095056716cSJeff Kirsher 	ntu = rd32(hw, hw->aq.arq.head) & I40E_PF_ARQH_ARQH_MASK;
111056a62fc8SJesse Brandeburg 	if (ntu == ntc) {
111156a62fc8SJesse Brandeburg 		/* nothing to do - shouldn't need to update ring's values */
1112230f3d53SJan Sokolowski 		ret_code = -EALREADY;
111356a62fc8SJesse Brandeburg 		goto clean_arq_element_out;
111456a62fc8SJesse Brandeburg 	}
111556a62fc8SJesse Brandeburg 
111656a62fc8SJesse Brandeburg 	/* now clean the next descriptor */
111756a62fc8SJesse Brandeburg 	desc = I40E_ADMINQ_DESC(hw->aq.arq, ntc);
111856a62fc8SJesse Brandeburg 	desc_idx = ntc;
111956a62fc8SJesse Brandeburg 
112081fa7c97SMaciej Sosin 	hw->aq.arq_last_status =
112181fa7c97SMaciej Sosin 		(enum i40e_admin_queue_err)le16_to_cpu(desc->retval);
112256a62fc8SJesse Brandeburg 	flags = le16_to_cpu(desc->flags);
112356a62fc8SJesse Brandeburg 	if (flags & I40E_AQ_FLAG_ERR) {
1124230f3d53SJan Sokolowski 		ret_code = -EIO;
112556a62fc8SJesse Brandeburg 		i40e_debug(hw,
112656a62fc8SJesse Brandeburg 			   I40E_DEBUG_AQ_MESSAGE,
112756a62fc8SJesse Brandeburg 			   "AQRX: Event received with error 0x%X.\n",
112856a62fc8SJesse Brandeburg 			   hw->aq.arq_last_status);
112977813d0aSKamil Krawczyk 	}
113077813d0aSKamil Krawczyk 
1131c36bd4a7SMitch Williams 	e->desc = *desc;
113256a62fc8SJesse Brandeburg 	datalen = le16_to_cpu(desc->datalen);
11331001dc37SMitch Williams 	e->msg_len = min(datalen, e->buf_len);
11341001dc37SMitch Williams 	if (e->msg_buf != NULL && (e->msg_len != 0))
113556a62fc8SJesse Brandeburg 		memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va,
11361001dc37SMitch Williams 		       e->msg_len);
113756a62fc8SJesse Brandeburg 
1138b83ebf50SDoug Dziggel 	i40e_debug(hw, I40E_DEBUG_AQ_COMMAND, "AQRX: desc and buffer:\n");
1139f905dd62SShannon Nelson 	i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, e->msg_buf,
1140f905dd62SShannon Nelson 		      hw->aq.arq_buf_size);
114166d90e7dSKamil Krawczyk 
114256a62fc8SJesse Brandeburg 	/* Restore the original datalen and buffer address in the desc,
114356a62fc8SJesse Brandeburg 	 * FW updates datalen to indicate the event message
114456a62fc8SJesse Brandeburg 	 * size
114556a62fc8SJesse Brandeburg 	 */
114656a62fc8SJesse Brandeburg 	bi = &hw->aq.arq.r.arq_bi[ntc];
114790077773SMitch Williams 	memset((void *)desc, 0, sizeof(struct i40e_aq_desc));
114890077773SMitch Williams 
114990077773SMitch Williams 	desc->flags = cpu_to_le16(I40E_AQ_FLAG_BUF);
115090077773SMitch Williams 	if (hw->aq.arq_buf_size > I40E_AQ_LARGE_BUF)
115190077773SMitch Williams 		desc->flags |= cpu_to_le16(I40E_AQ_FLAG_LB);
115256a62fc8SJesse Brandeburg 	desc->datalen = cpu_to_le16((u16)bi->size);
115356a62fc8SJesse Brandeburg 	desc->params.external.addr_high = cpu_to_le32(upper_32_bits(bi->pa));
115456a62fc8SJesse Brandeburg 	desc->params.external.addr_low = cpu_to_le32(lower_32_bits(bi->pa));
115556a62fc8SJesse Brandeburg 
115656a62fc8SJesse Brandeburg 	/* set tail = the last cleaned desc index. */
115756a62fc8SJesse Brandeburg 	wr32(hw, hw->aq.arq.tail, ntc);
115856a62fc8SJesse Brandeburg 	/* ntc is updated to tail + 1 */
115956a62fc8SJesse Brandeburg 	ntc++;
116056a62fc8SJesse Brandeburg 	if (ntc == hw->aq.num_arq_entries)
116156a62fc8SJesse Brandeburg 		ntc = 0;
116256a62fc8SJesse Brandeburg 	hw->aq.arq.next_to_clean = ntc;
116356a62fc8SJesse Brandeburg 	hw->aq.arq.next_to_use = ntu;
116456a62fc8SJesse Brandeburg 
1165e3a5d6e6SPawel Jablonski 	i40e_nvmupd_check_wait_event(hw, le16_to_cpu(e->desc.opcode), &e->desc);
116673b03f98SShannon Nelson clean_arq_element_out:
116773b03f98SShannon Nelson 	/* Set pending if needed, unlock and return */
116873b03f98SShannon Nelson 	if (pending)
116973b03f98SShannon Nelson 		*pending = (ntc > ntu ? hw->aq.arq.count : 0) + (ntu - ntc);
117073b03f98SShannon Nelson clean_arq_element_err:
117173b03f98SShannon Nelson 	mutex_unlock(&hw->aq.arq_mutex);
117273b03f98SShannon Nelson 
117356a62fc8SJesse Brandeburg 	return ret_code;
117456a62fc8SJesse Brandeburg }
117556a62fc8SJesse Brandeburg 
i40e_resume_aq(struct i40e_hw * hw)1176af28eec9SStephen Hemminger static void i40e_resume_aq(struct i40e_hw *hw)
117756a62fc8SJesse Brandeburg {
117856a62fc8SJesse Brandeburg 	/* Registers are reset after PF reset */
117956a62fc8SJesse Brandeburg 	hw->aq.asq.next_to_use = 0;
118056a62fc8SJesse Brandeburg 	hw->aq.asq.next_to_clean = 0;
118156a62fc8SJesse Brandeburg 
118256a62fc8SJesse Brandeburg 	i40e_config_asq_regs(hw);
118356a62fc8SJesse Brandeburg 
118456a62fc8SJesse Brandeburg 	hw->aq.arq.next_to_use = 0;
118556a62fc8SJesse Brandeburg 	hw->aq.arq.next_to_clean = 0;
118656a62fc8SJesse Brandeburg 
118756a62fc8SJesse Brandeburg 	i40e_config_arq_regs(hw);
118856a62fc8SJesse Brandeburg }
1189