Skip to content

Commit

Permalink
ice: Add support for control queues
Browse files Browse the repository at this point in the history
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 <anirudh.venkataramanan@intel.com>
Tested-by: Tony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
  • Loading branch information
Anirudh Venkataramanan authored and Jeff Kirsher committed Mar 26, 2018
1 parent 837f08f commit 7ec59ee
Show file tree
Hide file tree
Showing 12 changed files with 1,458 additions and 2 deletions.
4 changes: 3 additions & 1 deletion drivers/net/ethernet/intel/ice/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@

obj-$(CONFIG_ICE) += ice.o

ice-y := ice_main.o
ice-y := ice_main.o \
ice_controlq.o \
ice_common.o
1 change: 1 addition & 0 deletions drivers/net/ethernet/intel/ice/ice.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <linux/compiler.h>
#include <linux/pci.h>
#include <linux/aer.h>
#include <linux/delay.h>
#include <linux/bitmap.h>
#include "ice_devids.h"
#include "ice_type.h"
Expand Down
94 changes: 94 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018, Intel Corporation. */

#ifndef _ICE_ADMINQ_CMD_H_
#define _ICE_ADMINQ_CMD_H_

/* This header file defines the Admin Queue commands, error codes and
* descriptor format. It is shared between Firmware and Software.
*/

struct ice_aqc_generic {
__le32 param0;
__le32 param1;
__le32 addr_high;
__le32 addr_low;
};

/* Get version (direct 0x0001) */
struct ice_aqc_get_ver {
__le32 rom_ver;
__le32 fw_build;
u8 fw_branch;
u8 fw_major;
u8 fw_minor;
u8 fw_patch;
u8 api_branch;
u8 api_major;
u8 api_minor;
u8 api_patch;
};

/* Queue Shutdown (direct 0x0003) */
struct ice_aqc_q_shutdown {
#define ICE_AQC_DRIVER_UNLOADING BIT(0)
__le32 driver_unloading;
u8 reserved[12];
};

/**
* struct ice_aq_desc - Admin Queue (AQ) descriptor
* @flags: ICE_AQ_FLAG_* flags
* @opcode: AQ command opcode
* @datalen: length in bytes of indirect/external data buffer
* @retval: return value from firmware
* @cookie_h: opaque data high-half
* @cookie_l: opaque data low-half
* @params: command-specific parameters
*
* Descriptor format for commands the driver posts on the Admin Transmit Queue
* (ATQ). The firmware writes back onto the command descriptor and returns
* the result of the command. Asynchronous events that are not an immediate
* result of the command are written to the Admin Receive Queue (ARQ) using
* the same descriptor format. Descriptors are in little-endian notation with
* 32-bit words.
*/
struct ice_aq_desc {
__le16 flags;
__le16 opcode;
__le16 datalen;
__le16 retval;
__le32 cookie_high;
__le32 cookie_low;
union {
u8 raw[16];
struct ice_aqc_generic generic;
struct ice_aqc_get_ver get_ver;
struct ice_aqc_q_shutdown q_shutdown;
} params;
};

/* FW defined boundary for a large buffer, 4k >= Large buffer > 512 bytes */
#define ICE_AQ_LG_BUF 512

#define ICE_AQ_FLAG_LB_S 9
#define ICE_AQ_FLAG_BUF_S 12
#define ICE_AQ_FLAG_SI_S 13

#define ICE_AQ_FLAG_LB BIT(ICE_AQ_FLAG_LB_S) /* 0x200 */
#define ICE_AQ_FLAG_BUF BIT(ICE_AQ_FLAG_BUF_S) /* 0x1000 */
#define ICE_AQ_FLAG_SI BIT(ICE_AQ_FLAG_SI_S) /* 0x2000 */

/* error codes */
enum ice_aq_err {
ICE_AQ_RC_OK = 0, /* success */
};

/* Admin Queue command opcodes */
enum ice_adminq_opc {
/* AQ commands */
ice_aqc_opc_get_ver = 0x0001,
ice_aqc_opc_q_shutdown = 0x0003,
};

#endif /* _ICE_ADMINQ_CMD_H_ */
130 changes: 130 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_common.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2018, Intel Corporation. */

#include "ice_common.h"
#include "ice_adminq_cmd.h"

/**
* ice_debug_cq
* @hw: pointer to the hardware structure
* @mask: debug mask
* @desc: pointer to control queue descriptor
* @buf: pointer to command buffer
* @buf_len: max length of buf
*
* Dumps debug log about control command with descriptor contents.
*/
void ice_debug_cq(struct ice_hw *hw, u32 __maybe_unused mask, void *desc,
void *buf, u16 buf_len)
{
struct ice_aq_desc *cq_desc = (struct ice_aq_desc *)desc;
u16 len;

#ifndef CONFIG_DYNAMIC_DEBUG
if (!(mask & hw->debug_mask))
return;
#endif

if (!desc)
return;

len = le16_to_cpu(cq_desc->datalen);

ice_debug(hw, mask,
"CQ CMD: opcode 0x%04X, flags 0x%04X, datalen 0x%04X, retval 0x%04X\n",
le16_to_cpu(cq_desc->opcode),
le16_to_cpu(cq_desc->flags),
le16_to_cpu(cq_desc->datalen), le16_to_cpu(cq_desc->retval));
ice_debug(hw, mask, "\tcookie (h,l) 0x%08X 0x%08X\n",
le32_to_cpu(cq_desc->cookie_high),
le32_to_cpu(cq_desc->cookie_low));
ice_debug(hw, mask, "\tparam (0,1) 0x%08X 0x%08X\n",
le32_to_cpu(cq_desc->params.generic.param0),
le32_to_cpu(cq_desc->params.generic.param1));
ice_debug(hw, mask, "\taddr (h,l) 0x%08X 0x%08X\n",
le32_to_cpu(cq_desc->params.generic.addr_high),
le32_to_cpu(cq_desc->params.generic.addr_low));
if (buf && cq_desc->datalen != 0) {
ice_debug(hw, mask, "Buffer:\n");
if (buf_len < len)
len = buf_len;

ice_debug_array(hw, mask, 16, 1, (u8 *)buf, len);
}
}

/* FW Admin Queue command wrappers */

/**
* ice_aq_send_cmd - send FW Admin Queue command to FW Admin Queue
* @hw: pointer to the hw struct
* @desc: descriptor describing the command
* @buf: buffer to use for indirect commands (NULL for direct commands)
* @buf_size: size of buffer for indirect commands (0 for direct commands)
* @cd: pointer to command details structure
*
* Helper function to send FW Admin Queue commands to the FW Admin Queue.
*/
enum ice_status
ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf,
u16 buf_size, struct ice_sq_cd *cd)
{
return ice_sq_send_cmd(hw, &hw->adminq, desc, buf, buf_size, cd);
}

/**
* ice_aq_get_fw_ver
* @hw: pointer to the hw struct
* @cd: pointer to command details structure or NULL
*
* Get the firmware version (0x0001) from the admin queue commands
*/
enum ice_status ice_aq_get_fw_ver(struct ice_hw *hw, struct ice_sq_cd *cd)
{
struct ice_aqc_get_ver *resp;
struct ice_aq_desc desc;
enum ice_status status;

resp = &desc.params.get_ver;

ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_ver);

status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);

if (!status) {
hw->fw_branch = resp->fw_branch;
hw->fw_maj_ver = resp->fw_major;
hw->fw_min_ver = resp->fw_minor;
hw->fw_patch = resp->fw_patch;
hw->fw_build = le32_to_cpu(resp->fw_build);
hw->api_branch = resp->api_branch;
hw->api_maj_ver = resp->api_major;
hw->api_min_ver = resp->api_minor;
hw->api_patch = resp->api_patch;
}

return status;
}

/**
* ice_aq_q_shutdown
* @hw: pointer to the hw struct
* @unloading: is the driver unloading itself
*
* Tell the Firmware that we're shutting down the AdminQ and whether
* or not the driver is unloading as well (0x0003).
*/
enum ice_status ice_aq_q_shutdown(struct ice_hw *hw, bool unloading)
{
struct ice_aqc_q_shutdown *cmd;
struct ice_aq_desc desc;

cmd = &desc.params.q_shutdown;

ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_q_shutdown);

if (unloading)
cmd->driver_unloading = cpu_to_le32(ICE_AQC_DRIVER_UNLOADING);

return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
}
25 changes: 25 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018, Intel Corporation. */

#ifndef _ICE_COMMON_H_
#define _ICE_COMMON_H_

#include "ice.h"
#include "ice_type.h"

void ice_debug_cq(struct ice_hw *hw, u32 mask, void *desc, void *buf,
u16 buf_len);
enum ice_status ice_init_all_ctrlq(struct ice_hw *hw);
void ice_shutdown_all_ctrlq(struct ice_hw *hw);
enum ice_status
ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq,
struct ice_aq_desc *desc, void *buf, u16 buf_size,
struct ice_sq_cd *cd);
bool ice_check_sq_alive(struct ice_hw *hw, struct ice_ctl_q_info *cq);
enum ice_status ice_aq_q_shutdown(struct ice_hw *hw, bool unloading);
void ice_fill_dflt_direct_cmd_desc(struct ice_aq_desc *desc, u16 opcode);
enum ice_status
ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc,
void *buf, u16 buf_size, struct ice_sq_cd *cd);
enum ice_status ice_aq_get_fw_ver(struct ice_hw *hw, struct ice_sq_cd *cd);
#endif /* _ICE_COMMON_H_ */
Loading

0 comments on commit 7ec59ee

Please sign in to comment.