Skip to content

Commit

Permalink
Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/tnguy/next-queue

Tony Nguyen says:

====================
Intel Wired LAN Driver Updates 2024-08-26 (ice)

This series contains updates to ice driver only.

Jake implements and uses rd32_poll_timeout to replace a jiffies loop for
calling ice_sq_done. The rd32_poll_timeout() function is designed to allow
simplifying other places in the driver where we need to read a register
until it matches a known value.

Jake, Bruce, and Przemek update ice_debug_cq() to be more robust, and more
useful for tracing control queue messages sent and received by the device
driver.

Jake rewords several commands in the ice_control.c file which previously
referred to the "Admin queue" when they were actually generic functions
usable on any control queue.

Jake removes the unused and unnecessary cmd_buf array allocation for send
queues. This logic originally was going to be useful if we ever implemented
asynchronous completion of transmit messages. This support is unlikely to
materialize, so the overhead of allocating a command buffer is unnecessary.

Sergey improves the log messages when the ice driver reports that the NVM
version on the device is not supported by the driver. Now, these messages
include both the discovered NVM version and the requested/expected NVM
version.

Aleksandr Mishin corrects overallocation of memory related to adding
scheduler nodes.

* '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue:
  ice: Adjust over allocation of memory in ice_sched_add_root_node() and ice_sched_add_node()
  ice: Report NVM version numbers on mismatch during load
  ice: remove unnecessary control queue cmd_buf arrays
  ice: reword comments referring to control queues
  ice: stop intermixing AQ commands/responses debug dumps
  ice: do not clutter debug logs with unused data
  ice: improve debug print for control queue messages
  ice: implement and use rd32_poll_timeout for ice_sq_done timeout
====================

Link: https://patch.msgid.link/20240826224655.133847-1-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Jakub Kicinski committed Aug 27, 2024
2 parents b3bc534 + 62fdaf9 commit e5899b6
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 102 deletions.
4 changes: 4 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -2632,12 +2632,16 @@ struct ice_aq_desc {
/* FW defined boundary for a large buffer, 4k >= Large buffer > 512 bytes */
#define ICE_AQ_LG_BUF 512

#define ICE_AQ_FLAG_DD_S 0
#define ICE_AQ_FLAG_CMP_S 1
#define ICE_AQ_FLAG_ERR_S 2
#define ICE_AQ_FLAG_LB_S 9
#define ICE_AQ_FLAG_RD_S 10
#define ICE_AQ_FLAG_BUF_S 12
#define ICE_AQ_FLAG_SI_S 13

#define ICE_AQ_FLAG_DD BIT(ICE_AQ_FLAG_DD_S) /* 0x1 */
#define ICE_AQ_FLAG_CMP BIT(ICE_AQ_FLAG_CMP_S) /* 0x2 */
#define ICE_AQ_FLAG_ERR BIT(ICE_AQ_FLAG_ERR_S) /* 0x4 */
#define ICE_AQ_FLAG_LB BIT(ICE_AQ_FLAG_LB_S) /* 0x200 */
#define ICE_AQ_FLAG_RD BIT(ICE_AQ_FLAG_RD_S) /* 0x400 */
Expand Down
178 changes: 94 additions & 84 deletions drivers/net/ethernet/intel/ice/ice_controlq.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,6 @@ ice_alloc_ctrlq_sq_ring(struct ice_hw *hw, struct ice_ctl_q_info *cq)
return -ENOMEM;
cq->sq.desc_buf.size = size;

cq->sq.cmd_buf = devm_kcalloc(ice_hw_to_dev(hw), cq->num_sq_entries,
sizeof(struct ice_sq_cd), GFP_KERNEL);
if (!cq->sq.cmd_buf) {
dmam_free_coherent(ice_hw_to_dev(hw), cq->sq.desc_buf.size,
cq->sq.desc_buf.va, cq->sq.desc_buf.pa);
cq->sq.desc_buf.va = NULL;
cq->sq.desc_buf.pa = 0;
cq->sq.desc_buf.size = 0;
return -ENOMEM;
}

return 0;
}

Expand Down Expand Up @@ -188,7 +177,7 @@ ice_alloc_rq_bufs(struct ice_hw *hw, struct ice_ctl_q_info *cq)
if (cq->rq_buf_size > ICE_AQ_LG_BUF)
desc->flags |= cpu_to_le16(ICE_AQ_FLAG_LB);
desc->opcode = 0;
/* This is in accordance with Admin queue design, there is no
/* This is in accordance with control queue design, there is no
* register for buffer size configuration
*/
desc->datalen = cpu_to_le16(bi->size);
Expand Down Expand Up @@ -338,8 +327,6 @@ do { \
(qi)->ring.r.ring##_bi[i].size = 0;\
} \
} \
/* free the buffer info list */ \
devm_kfree(ice_hw_to_dev(hw), (qi)->ring.cmd_buf); \
/* free DMA head */ \
devm_kfree(ice_hw_to_dev(hw), (qi)->ring.dma_head); \
} while (0)
Expand Down Expand Up @@ -405,11 +392,11 @@ static int ice_init_sq(struct ice_hw *hw, struct ice_ctl_q_info *cq)
}

/**
* ice_init_rq - initialize ARQ
* ice_init_rq - initialize receive side of a control queue
* @hw: pointer to the hardware structure
* @cq: pointer to the specific Control queue
*
* The main initialization routine for the Admin Receive (Event) Queue.
* The main initialization routine for Receive side of a control queue.
* Prior to calling this function, the driver *MUST* set the following fields
* in the cq->structure:
* - cq->num_rq_entries
Expand Down Expand Up @@ -465,7 +452,7 @@ static int ice_init_rq(struct ice_hw *hw, struct ice_ctl_q_info *cq)
}

/**
* ice_shutdown_sq - shutdown the Control ATQ
* ice_shutdown_sq - shutdown the transmit side of a control queue
* @hw: pointer to the hardware structure
* @cq: pointer to the specific Control queue
*
Expand All @@ -482,7 +469,7 @@ static int ice_shutdown_sq(struct ice_hw *hw, struct ice_ctl_q_info *cq)
goto shutdown_sq_out;
}

/* Stop firmware AdminQ processing */
/* Stop processing of the control queue */
wr32(hw, cq->sq.head, 0);
wr32(hw, cq->sq.tail, 0);
wr32(hw, cq->sq.len, 0);
Expand All @@ -501,7 +488,7 @@ static int ice_shutdown_sq(struct ice_hw *hw, struct ice_ctl_q_info *cq)
}

/**
* ice_aq_ver_check - Check the reported AQ API version.
* ice_aq_ver_check - Check the reported AQ API version
* @hw: pointer to the hardware structure
*
* Checks if the driver should load on a given AQ API version.
Expand All @@ -521,14 +508,20 @@ static bool ice_aq_ver_check(struct ice_hw *hw)
} else if (hw->api_maj_ver == exp_fw_api_ver_major) {
if (hw->api_min_ver > (exp_fw_api_ver_minor + 2))
dev_info(ice_hw_to_dev(hw),
"The driver for the device detected a newer version of the NVM image than expected. Please install the most recent version of the network driver.\n");
"The driver for the device detected a newer version (%u.%u) of the NVM image than expected (%u.%u). Please install the most recent version of the network driver.\n",
hw->api_maj_ver, hw->api_min_ver,
exp_fw_api_ver_major, exp_fw_api_ver_minor);
else if ((hw->api_min_ver + 2) < exp_fw_api_ver_minor)
dev_info(ice_hw_to_dev(hw),
"The driver for the device detected an older version of the NVM image than expected. Please update the NVM image.\n");
"The driver for the device detected an older version (%u.%u) of the NVM image than expected (%u.%u). Please update the NVM image.\n",
hw->api_maj_ver, hw->api_min_ver,
exp_fw_api_ver_major, exp_fw_api_ver_minor);
} else {
/* Major API version is older than expected, log a warning */
dev_info(ice_hw_to_dev(hw),
"The driver for the device detected an older version of the NVM image than expected. Please update the NVM image.\n");
"The driver for the device detected an older version (%u.%u) of the NVM image than expected (%u.%u). Please update the NVM image.\n",
hw->api_maj_ver, hw->api_min_ver,
exp_fw_api_ver_major, exp_fw_api_ver_minor);
}
return true;
}
Expand Down Expand Up @@ -855,7 +848,7 @@ void ice_destroy_all_ctrlq(struct ice_hw *hw)
}

/**
* ice_clean_sq - cleans Admin send queue (ATQ)
* ice_clean_sq - cleans send side of a control queue
* @hw: pointer to the hardware structure
* @cq: pointer to the specific Control queue
*
Expand All @@ -865,41 +858,62 @@ static u16 ice_clean_sq(struct ice_hw *hw, struct ice_ctl_q_info *cq)
{
struct ice_ctl_q_ring *sq = &cq->sq;
u16 ntc = sq->next_to_clean;
struct ice_sq_cd *details;
struct ice_aq_desc *desc;

desc = ICE_CTL_Q_DESC(*sq, ntc);
details = ICE_CTL_Q_DETAILS(*sq, ntc);

while (rd32(hw, cq->sq.head) != ntc) {
ice_debug(hw, ICE_DBG_AQ_MSG, "ntc %d head %d.\n", ntc, rd32(hw, cq->sq.head));
memset(desc, 0, sizeof(*desc));
memset(details, 0, sizeof(*details));
ntc++;
if (ntc == sq->count)
ntc = 0;
desc = ICE_CTL_Q_DESC(*sq, ntc);
details = ICE_CTL_Q_DETAILS(*sq, ntc);
}

sq->next_to_clean = ntc;

return ICE_CTL_Q_DESC_UNUSED(sq);
}

/**
* ice_ctl_q_str - Convert control queue type to string
* @qtype: the control queue type
*
* Return: A string name for the given control queue type.
*/
static const char *ice_ctl_q_str(enum ice_ctl_q qtype)
{
switch (qtype) {
case ICE_CTL_Q_UNKNOWN:
return "Unknown CQ";
case ICE_CTL_Q_ADMIN:
return "AQ";
case ICE_CTL_Q_MAILBOX:
return "MBXQ";
case ICE_CTL_Q_SB:
return "SBQ";
default:
return "Unrecognized CQ";
}
}

/**
* ice_debug_cq
* @hw: pointer to the hardware structure
* @cq: pointer to the specific Control queue
* @desc: pointer to control queue descriptor
* @buf: pointer to command buffer
* @buf_len: max length of buf
* @response: true if this is the writeback response
*
* Dumps debug log about control command with descriptor contents.
*/
static void ice_debug_cq(struct ice_hw *hw, void *desc, void *buf, u16 buf_len)
static void ice_debug_cq(struct ice_hw *hw, struct ice_ctl_q_info *cq,
void *desc, void *buf, u16 buf_len, bool response)
{
struct ice_aq_desc *cq_desc = desc;
u16 len;
u16 datalen, flags;

if (!IS_ENABLED(CONFIG_DYNAMIC_DEBUG) &&
!((ICE_DBG_AQ_DESC | ICE_DBG_AQ_DESC_BUF) & hw->debug_mask))
Expand All @@ -908,57 +922,73 @@ static void ice_debug_cq(struct ice_hw *hw, void *desc, void *buf, u16 buf_len)
if (!desc)
return;

len = le16_to_cpu(cq_desc->datalen);
datalen = le16_to_cpu(cq_desc->datalen);
flags = le16_to_cpu(cq_desc->flags);

ice_debug(hw, ICE_DBG_AQ_DESC, "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, ICE_DBG_AQ_DESC, "\tcookie (h,l) 0x%08X 0x%08X\n",
ice_debug(hw, ICE_DBG_AQ_DESC, "%s %s: opcode 0x%04X, flags 0x%04X, datalen 0x%04X, retval 0x%04X\n\tcookie (h,l) 0x%08X 0x%08X\n\tparam (0,1) 0x%08X 0x%08X\n\taddr (h,l) 0x%08X 0x%08X\n",
ice_ctl_q_str(cq->qtype), response ? "Response" : "Command",
le16_to_cpu(cq_desc->opcode), flags, datalen,
le16_to_cpu(cq_desc->retval),
le32_to_cpu(cq_desc->cookie_high),
le32_to_cpu(cq_desc->cookie_low));
ice_debug(hw, ICE_DBG_AQ_DESC, "\tparam (0,1) 0x%08X 0x%08X\n",
le32_to_cpu(cq_desc->cookie_low),
le32_to_cpu(cq_desc->params.generic.param0),
le32_to_cpu(cq_desc->params.generic.param1));
ice_debug(hw, ICE_DBG_AQ_DESC, "\taddr (h,l) 0x%08X 0x%08X\n",
le32_to_cpu(cq_desc->params.generic.param1),
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, ICE_DBG_AQ_DESC_BUF, "Buffer:\n");
if (buf_len < len)
len = buf_len;

ice_debug_array(hw, ICE_DBG_AQ_DESC_BUF, 16, 1, buf, len);
/* Dump buffer iff 1) one exists and 2) is either a response indicated
* by the DD and/or CMP flag set or a command with the RD flag set.
*/
if (buf && cq_desc->datalen &&
(flags & (ICE_AQ_FLAG_DD | ICE_AQ_FLAG_CMP | ICE_AQ_FLAG_RD))) {
char prefix[] = KBUILD_MODNAME " 0x12341234 0x12341234 ";

sprintf(prefix, KBUILD_MODNAME " 0x%08X 0x%08X ",
le32_to_cpu(cq_desc->params.generic.addr_high),
le32_to_cpu(cq_desc->params.generic.addr_low));
ice_debug_array_w_prefix(hw, ICE_DBG_AQ_DESC_BUF, prefix,
buf,
min_t(u16, buf_len, datalen));
}
}

/**
* ice_sq_done - check if FW has processed the Admin Send Queue (ATQ)
* ice_sq_done - poll until the last send on a control queue has completed
* @hw: pointer to the HW struct
* @cq: pointer to the specific Control queue
*
* Returns true if the firmware has processed all descriptors on the
* admin send queue. Returns false if there are still requests pending.
* Use read_poll_timeout to poll the control queue head, checking until it
* matches next_to_use. According to the control queue designers, this has
* better timing reliability than the DD bit.
*
* Return: true if all the descriptors on the send side of a control queue
* are finished processing, false otherwise.
*/
static bool ice_sq_done(struct ice_hw *hw, struct ice_ctl_q_info *cq)
{
/* AQ designers suggest use of head for better
* timing reliability than DD bit
u32 head;

/* Wait a short time before the initial check, to allow hardware time
* for completion.
*/
return rd32(hw, cq->sq.head) == cq->sq.next_to_use;
udelay(5);

return !rd32_poll_timeout(hw, cq->sq.head,
head, head == cq->sq.next_to_use,
20, ICE_CTL_Q_SQ_CMD_TIMEOUT);
}

/**
* ice_sq_send_cmd - send command to Control Queue (ATQ)
* ice_sq_send_cmd - send command to a control queue
* @hw: pointer to the HW struct
* @cq: pointer to the specific Control queue
* @desc: prefilled descriptor describing the command
* @buf: buffer to use for indirect commands (or NULL for direct commands)
* @buf_size: size of buffer for indirect commands (or 0 for direct commands)
* @cd: pointer to command details structure
*
* This is the main send command routine for the ATQ. It runs the queue,
* cleans the queue, etc.
* Main command for the transmit side of a control queue. It puts the command
* on the queue, bumps the tail, waits for processing of the command, captures
* command status and results, etc.
*/
int
ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq,
Expand All @@ -968,8 +998,6 @@ ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq,
struct ice_dma_mem *dma_buf = NULL;
struct ice_aq_desc *desc_on_ring;
bool cmd_completed = false;
struct ice_sq_cd *details;
unsigned long timeout;
int status = 0;
u16 retval = 0;
u32 val = 0;
Expand Down Expand Up @@ -1013,12 +1041,6 @@ ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq,
goto sq_send_command_error;
}

details = ICE_CTL_Q_DETAILS(cq->sq, cq->sq.next_to_use);
if (cd)
*details = *cd;
else
memset(details, 0, sizeof(*details));

/* Call clean and check queue available function to reclaim the
* descriptors that were processed by FW/MBX; the function returns the
* number of desc available. The clean function called here could be
Expand Down Expand Up @@ -1055,28 +1077,17 @@ ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq,
/* Debug desc and buffer */
ice_debug(hw, ICE_DBG_AQ_DESC, "ATQ: Control Send queue desc and buffer:\n");

ice_debug_cq(hw, (void *)desc_on_ring, buf, buf_size);
ice_debug_cq(hw, cq, (void *)desc_on_ring, buf, buf_size, false);

(cq->sq.next_to_use)++;
if (cq->sq.next_to_use == cq->sq.count)
cq->sq.next_to_use = 0;
wr32(hw, cq->sq.tail, cq->sq.next_to_use);
ice_flush(hw);

/* Wait a short time before initial ice_sq_done() check, to allow
* hardware time for completion.
/* Wait for the command to complete. If it finishes within the
* timeout, copy the descriptor back to temp.
*/
udelay(5);

timeout = jiffies + ICE_CTL_Q_SQ_CMD_TIMEOUT;
do {
if (ice_sq_done(hw, cq))
break;

usleep_range(100, 150);
} while (time_before(jiffies, timeout));

/* if ready, copy the desc back to temp */
if (ice_sq_done(hw, cq)) {
memcpy(desc, desc_on_ring, sizeof(*desc));
if (buf) {
Expand Down Expand Up @@ -1108,12 +1119,11 @@ ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq,

ice_debug(hw, ICE_DBG_AQ_MSG, "ATQ: desc and buffer writeback:\n");

ice_debug_cq(hw, (void *)desc, buf, buf_size);
ice_debug_cq(hw, cq, (void *)desc, buf, buf_size, true);

/* save writeback AQ if requested */
if (details->wb_desc)
memcpy(details->wb_desc, desc_on_ring,
sizeof(*details->wb_desc));
if (cd && cd->wb_desc)
memcpy(cd->wb_desc, desc_on_ring, sizeof(*cd->wb_desc));

/* update the error if time out occurred */
if (!cmd_completed) {
Expand Down Expand Up @@ -1154,9 +1164,9 @@ void ice_fill_dflt_direct_cmd_desc(struct ice_aq_desc *desc, u16 opcode)
* @e: event info from the receive descriptor, includes any buffers
* @pending: number of events that could be left to process
*
* This function cleans one Admin Receive Queue element and returns
* the contents through e. It can also return how many events are
* left to process through 'pending'.
* Clean one element from the receive side of a control queue. On return 'e'
* contains contents of the message, and 'pending' contains the number of
* events left to process.
*/
int
ice_clean_rq_elem(struct ice_hw *hw, struct ice_ctl_q_info *cq,
Expand Down Expand Up @@ -1212,7 +1222,7 @@ ice_clean_rq_elem(struct ice_hw *hw, struct ice_ctl_q_info *cq,

ice_debug(hw, ICE_DBG_AQ_DESC, "ARQ: desc and buffer:\n");

ice_debug_cq(hw, (void *)desc, e->msg_buf, cq->rq_buf_size);
ice_debug_cq(hw, cq, (void *)desc, e->msg_buf, cq->rq_buf_size, true);

/* Restore the original datalen and buffer address in the desc,
* FW updates datalen to indicate the event message size
Expand Down
Loading

0 comments on commit e5899b6

Please sign in to comment.