Skip to content

Commit 7ec59ee

Browse files
refactormanJeff Kirsher
authored andcommitted
ice: Add support for control queues
A control queue is a hardware interface which is used by the driver to interact with other subsystems (like firmware, PHY, etc.). It is implemented as a producer-consumer ring. More specifically, an "admin queue" is a type of control queue used to interact with the firmware. This patch introduces data structures and functions to initialize and teardown control/admin queues. Once the admin queue is initialized, the driver uses it to get the firmware version. Signed-off-by: Anirudh Venkataramanan <[email protected]> Tested-by: Tony Brelinski <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 837f08f commit 7ec59ee

File tree

12 files changed

+1458
-2
lines changed

12 files changed

+1458
-2
lines changed

drivers/net/ethernet/intel/ice/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@
77

88
obj-$(CONFIG_ICE) += ice.o
99

10-
ice-y := ice_main.o
10+
ice-y := ice_main.o \
11+
ice_controlq.o \
12+
ice_common.o

drivers/net/ethernet/intel/ice/ice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/compiler.h>
1313
#include <linux/pci.h>
1414
#include <linux/aer.h>
15+
#include <linux/delay.h>
1516
#include <linux/bitmap.h>
1617
#include "ice_devids.h"
1718
#include "ice_type.h"
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/* Copyright (c) 2018, Intel Corporation. */
3+
4+
#ifndef _ICE_ADMINQ_CMD_H_
5+
#define _ICE_ADMINQ_CMD_H_
6+
7+
/* This header file defines the Admin Queue commands, error codes and
8+
* descriptor format. It is shared between Firmware and Software.
9+
*/
10+
11+
struct ice_aqc_generic {
12+
__le32 param0;
13+
__le32 param1;
14+
__le32 addr_high;
15+
__le32 addr_low;
16+
};
17+
18+
/* Get version (direct 0x0001) */
19+
struct ice_aqc_get_ver {
20+
__le32 rom_ver;
21+
__le32 fw_build;
22+
u8 fw_branch;
23+
u8 fw_major;
24+
u8 fw_minor;
25+
u8 fw_patch;
26+
u8 api_branch;
27+
u8 api_major;
28+
u8 api_minor;
29+
u8 api_patch;
30+
};
31+
32+
/* Queue Shutdown (direct 0x0003) */
33+
struct ice_aqc_q_shutdown {
34+
#define ICE_AQC_DRIVER_UNLOADING BIT(0)
35+
__le32 driver_unloading;
36+
u8 reserved[12];
37+
};
38+
39+
/**
40+
* struct ice_aq_desc - Admin Queue (AQ) descriptor
41+
* @flags: ICE_AQ_FLAG_* flags
42+
* @opcode: AQ command opcode
43+
* @datalen: length in bytes of indirect/external data buffer
44+
* @retval: return value from firmware
45+
* @cookie_h: opaque data high-half
46+
* @cookie_l: opaque data low-half
47+
* @params: command-specific parameters
48+
*
49+
* Descriptor format for commands the driver posts on the Admin Transmit Queue
50+
* (ATQ). The firmware writes back onto the command descriptor and returns
51+
* the result of the command. Asynchronous events that are not an immediate
52+
* result of the command are written to the Admin Receive Queue (ARQ) using
53+
* the same descriptor format. Descriptors are in little-endian notation with
54+
* 32-bit words.
55+
*/
56+
struct ice_aq_desc {
57+
__le16 flags;
58+
__le16 opcode;
59+
__le16 datalen;
60+
__le16 retval;
61+
__le32 cookie_high;
62+
__le32 cookie_low;
63+
union {
64+
u8 raw[16];
65+
struct ice_aqc_generic generic;
66+
struct ice_aqc_get_ver get_ver;
67+
struct ice_aqc_q_shutdown q_shutdown;
68+
} params;
69+
};
70+
71+
/* FW defined boundary for a large buffer, 4k >= Large buffer > 512 bytes */
72+
#define ICE_AQ_LG_BUF 512
73+
74+
#define ICE_AQ_FLAG_LB_S 9
75+
#define ICE_AQ_FLAG_BUF_S 12
76+
#define ICE_AQ_FLAG_SI_S 13
77+
78+
#define ICE_AQ_FLAG_LB BIT(ICE_AQ_FLAG_LB_S) /* 0x200 */
79+
#define ICE_AQ_FLAG_BUF BIT(ICE_AQ_FLAG_BUF_S) /* 0x1000 */
80+
#define ICE_AQ_FLAG_SI BIT(ICE_AQ_FLAG_SI_S) /* 0x2000 */
81+
82+
/* error codes */
83+
enum ice_aq_err {
84+
ICE_AQ_RC_OK = 0, /* success */
85+
};
86+
87+
/* Admin Queue command opcodes */
88+
enum ice_adminq_opc {
89+
/* AQ commands */
90+
ice_aqc_opc_get_ver = 0x0001,
91+
ice_aqc_opc_q_shutdown = 0x0003,
92+
};
93+
94+
#endif /* _ICE_ADMINQ_CMD_H_ */
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2018, Intel Corporation. */
3+
4+
#include "ice_common.h"
5+
#include "ice_adminq_cmd.h"
6+
7+
/**
8+
* ice_debug_cq
9+
* @hw: pointer to the hardware structure
10+
* @mask: debug mask
11+
* @desc: pointer to control queue descriptor
12+
* @buf: pointer to command buffer
13+
* @buf_len: max length of buf
14+
*
15+
* Dumps debug log about control command with descriptor contents.
16+
*/
17+
void ice_debug_cq(struct ice_hw *hw, u32 __maybe_unused mask, void *desc,
18+
void *buf, u16 buf_len)
19+
{
20+
struct ice_aq_desc *cq_desc = (struct ice_aq_desc *)desc;
21+
u16 len;
22+
23+
#ifndef CONFIG_DYNAMIC_DEBUG
24+
if (!(mask & hw->debug_mask))
25+
return;
26+
#endif
27+
28+
if (!desc)
29+
return;
30+
31+
len = le16_to_cpu(cq_desc->datalen);
32+
33+
ice_debug(hw, mask,
34+
"CQ CMD: opcode 0x%04X, flags 0x%04X, datalen 0x%04X, retval 0x%04X\n",
35+
le16_to_cpu(cq_desc->opcode),
36+
le16_to_cpu(cq_desc->flags),
37+
le16_to_cpu(cq_desc->datalen), le16_to_cpu(cq_desc->retval));
38+
ice_debug(hw, mask, "\tcookie (h,l) 0x%08X 0x%08X\n",
39+
le32_to_cpu(cq_desc->cookie_high),
40+
le32_to_cpu(cq_desc->cookie_low));
41+
ice_debug(hw, mask, "\tparam (0,1) 0x%08X 0x%08X\n",
42+
le32_to_cpu(cq_desc->params.generic.param0),
43+
le32_to_cpu(cq_desc->params.generic.param1));
44+
ice_debug(hw, mask, "\taddr (h,l) 0x%08X 0x%08X\n",
45+
le32_to_cpu(cq_desc->params.generic.addr_high),
46+
le32_to_cpu(cq_desc->params.generic.addr_low));
47+
if (buf && cq_desc->datalen != 0) {
48+
ice_debug(hw, mask, "Buffer:\n");
49+
if (buf_len < len)
50+
len = buf_len;
51+
52+
ice_debug_array(hw, mask, 16, 1, (u8 *)buf, len);
53+
}
54+
}
55+
56+
/* FW Admin Queue command wrappers */
57+
58+
/**
59+
* ice_aq_send_cmd - send FW Admin Queue command to FW Admin Queue
60+
* @hw: pointer to the hw struct
61+
* @desc: descriptor describing the command
62+
* @buf: buffer to use for indirect commands (NULL for direct commands)
63+
* @buf_size: size of buffer for indirect commands (0 for direct commands)
64+
* @cd: pointer to command details structure
65+
*
66+
* Helper function to send FW Admin Queue commands to the FW Admin Queue.
67+
*/
68+
enum ice_status
69+
ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf,
70+
u16 buf_size, struct ice_sq_cd *cd)
71+
{
72+
return ice_sq_send_cmd(hw, &hw->adminq, desc, buf, buf_size, cd);
73+
}
74+
75+
/**
76+
* ice_aq_get_fw_ver
77+
* @hw: pointer to the hw struct
78+
* @cd: pointer to command details structure or NULL
79+
*
80+
* Get the firmware version (0x0001) from the admin queue commands
81+
*/
82+
enum ice_status ice_aq_get_fw_ver(struct ice_hw *hw, struct ice_sq_cd *cd)
83+
{
84+
struct ice_aqc_get_ver *resp;
85+
struct ice_aq_desc desc;
86+
enum ice_status status;
87+
88+
resp = &desc.params.get_ver;
89+
90+
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_ver);
91+
92+
status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
93+
94+
if (!status) {
95+
hw->fw_branch = resp->fw_branch;
96+
hw->fw_maj_ver = resp->fw_major;
97+
hw->fw_min_ver = resp->fw_minor;
98+
hw->fw_patch = resp->fw_patch;
99+
hw->fw_build = le32_to_cpu(resp->fw_build);
100+
hw->api_branch = resp->api_branch;
101+
hw->api_maj_ver = resp->api_major;
102+
hw->api_min_ver = resp->api_minor;
103+
hw->api_patch = resp->api_patch;
104+
}
105+
106+
return status;
107+
}
108+
109+
/**
110+
* ice_aq_q_shutdown
111+
* @hw: pointer to the hw struct
112+
* @unloading: is the driver unloading itself
113+
*
114+
* Tell the Firmware that we're shutting down the AdminQ and whether
115+
* or not the driver is unloading as well (0x0003).
116+
*/
117+
enum ice_status ice_aq_q_shutdown(struct ice_hw *hw, bool unloading)
118+
{
119+
struct ice_aqc_q_shutdown *cmd;
120+
struct ice_aq_desc desc;
121+
122+
cmd = &desc.params.q_shutdown;
123+
124+
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_q_shutdown);
125+
126+
if (unloading)
127+
cmd->driver_unloading = cpu_to_le32(ICE_AQC_DRIVER_UNLOADING);
128+
129+
return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
130+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/* Copyright (c) 2018, Intel Corporation. */
3+
4+
#ifndef _ICE_COMMON_H_
5+
#define _ICE_COMMON_H_
6+
7+
#include "ice.h"
8+
#include "ice_type.h"
9+
10+
void ice_debug_cq(struct ice_hw *hw, u32 mask, void *desc, void *buf,
11+
u16 buf_len);
12+
enum ice_status ice_init_all_ctrlq(struct ice_hw *hw);
13+
void ice_shutdown_all_ctrlq(struct ice_hw *hw);
14+
enum ice_status
15+
ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq,
16+
struct ice_aq_desc *desc, void *buf, u16 buf_size,
17+
struct ice_sq_cd *cd);
18+
bool ice_check_sq_alive(struct ice_hw *hw, struct ice_ctl_q_info *cq);
19+
enum ice_status ice_aq_q_shutdown(struct ice_hw *hw, bool unloading);
20+
void ice_fill_dflt_direct_cmd_desc(struct ice_aq_desc *desc, u16 opcode);
21+
enum ice_status
22+
ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc,
23+
void *buf, u16 buf_size, struct ice_sq_cd *cd);
24+
enum ice_status ice_aq_get_fw_ver(struct ice_hw *hw, struct ice_sq_cd *cd);
25+
#endif /* _ICE_COMMON_H_ */

0 commit comments

Comments
 (0)