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