Commit 5f6df173 authored by Jacob Keller's avatar Jacob Keller Committed by Tony Nguyen

ice: implement and use rd32_poll_timeout for ice_sq_done timeout

The ice_sq_done function is used to check the control queue head register
and determine whether or not the control queue processing is done. This
function is called in a loop checking against jiffies for a specified
timeout.

The pattern of reading a register in a loop until a condition is true or a
timeout is reached is a relatively common pattern. In fact, the kernel
provides a read_poll_timeout function implementing this behavior in
<linux/iopoll.h>

Use of read_poll_timeout is preferred over directly coding these loops.
However, using it in the ice driver is a bit more difficult because of the
rd32 wrapper. Implement a rd32_poll_timeout wrapper based on
read_poll_timeout.

Refactor ice_sq_done to use rd32_poll_timeout, replacing the loop calling
ice_sq_done in ice_sq_send_cmd. This simplifies the logic down to a single
ice_sq_done() call.

The implementation of rd32_poll_timeout uses microseconds for its timeout
value, so update the CQ timeout macros used to be specified in microseconds
units as well instead of using HZ for jiffies.
Signed-off-by: default avatarJacob Keller <jacob.e.keller@intel.com>
Reviewed-by: default avatarPrzemek Kitszel <przemyslaw.kitszel@intel.com>
Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 18aaa82b
...@@ -933,19 +933,29 @@ static void ice_debug_cq(struct ice_hw *hw, void *desc, void *buf, u16 buf_len) ...@@ -933,19 +933,29 @@ static void ice_debug_cq(struct ice_hw *hw, void *desc, void *buf, u16 buf_len)
} }
/** /**
* 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 * @hw: pointer to the HW struct
* @cq: pointer to the specific Control queue * @cq: pointer to the specific Control queue
* *
* Returns true if the firmware has processed all descriptors on the * Use read_poll_timeout to poll the control queue head, checking until it
* admin send queue. Returns false if there are still requests pending. * 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) static bool ice_sq_done(struct ice_hw *hw, struct ice_ctl_q_info *cq)
{ {
/* AQ designers suggest use of head for better u32 head;
* timing reliability than DD bit
/* 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);
} }
/** /**
...@@ -969,7 +979,6 @@ ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq, ...@@ -969,7 +979,6 @@ ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq,
struct ice_aq_desc *desc_on_ring; struct ice_aq_desc *desc_on_ring;
bool cmd_completed = false; bool cmd_completed = false;
struct ice_sq_cd *details; struct ice_sq_cd *details;
unsigned long timeout;
int status = 0; int status = 0;
u16 retval = 0; u16 retval = 0;
u32 val = 0; u32 val = 0;
...@@ -1063,20 +1072,9 @@ ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq, ...@@ -1063,20 +1072,9 @@ ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq,
wr32(hw, cq->sq.tail, cq->sq.next_to_use); wr32(hw, cq->sq.tail, cq->sq.next_to_use);
ice_flush(hw); ice_flush(hw);
/* Wait a short time before initial ice_sq_done() check, to allow /* Wait for the command to complete. If it finishes within the
* hardware time for completion. * 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)) { if (ice_sq_done(hw, cq)) {
memcpy(desc, desc_on_ring, sizeof(*desc)); memcpy(desc, desc_on_ring, sizeof(*desc));
if (buf) { if (buf) {
......
...@@ -43,7 +43,7 @@ enum ice_ctl_q { ...@@ -43,7 +43,7 @@ enum ice_ctl_q {
}; };
/* Control Queue timeout settings - max delay 1s */ /* Control Queue timeout settings - max delay 1s */
#define ICE_CTL_Q_SQ_CMD_TIMEOUT HZ /* Wait max 1s */ #define ICE_CTL_Q_SQ_CMD_TIMEOUT USEC_PER_SEC
#define ICE_CTL_Q_ADMIN_INIT_TIMEOUT 10 /* Count 10 times */ #define ICE_CTL_Q_ADMIN_INIT_TIMEOUT 10 /* Count 10 times */
#define ICE_CTL_Q_ADMIN_INIT_MSEC 100 /* Check every 100msec */ #define ICE_CTL_Q_ADMIN_INIT_MSEC 100 /* Check every 100msec */
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/iopoll.h>
#include <linux/pci_ids.h> #include <linux/pci_ids.h>
#ifndef CONFIG_64BIT #ifndef CONFIG_64BIT
#include <linux/io-64-nonatomic-lo-hi.h> #include <linux/io-64-nonatomic-lo-hi.h>
...@@ -23,6 +24,9 @@ ...@@ -23,6 +24,9 @@
#define wr64(a, reg, value) writeq((value), ((a)->hw_addr + (reg))) #define wr64(a, reg, value) writeq((value), ((a)->hw_addr + (reg)))
#define rd64(a, reg) readq((a)->hw_addr + (reg)) #define rd64(a, reg) readq((a)->hw_addr + (reg))
#define rd32_poll_timeout(a, addr, val, cond, delay_us, timeout_us) \
read_poll_timeout(rd32, val, cond, delay_us, timeout_us, false, a, addr)
#define ice_flush(a) rd32((a), GLGEN_STAT) #define ice_flush(a) rd32((a), GLGEN_STAT)
#define ICE_M(m, s) ((m ## U) << (s)) #define ICE_M(m, s) ((m ## U) << (s))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment