forked from mirrors/linux
		
	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: Jacob Keller <jacob.e.keller@intel.com> Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com> Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel) Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
This commit is contained in:
		
							parent
							
								
									18aaa82bd3
								
							
						
					
					
						commit
						5f6df173f9
					
				
					 3 changed files with 23 additions and 21 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
 * @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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
	bool cmd_completed = false;
 | 
			
		||||
	struct ice_sq_cd *details;
 | 
			
		||||
	unsigned long timeout;
 | 
			
		||||
	int status = 0;
 | 
			
		||||
	u16 retval = 0;
 | 
			
		||||
	u32 val = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
	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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,7 +43,7 @@ enum ice_ctl_q {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
/* 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_MSEC	100   /* Check every 100msec */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@
 | 
			
		|||
#include <linux/ethtool.h>
 | 
			
		||||
#include <linux/etherdevice.h>
 | 
			
		||||
#include <linux/if_ether.h>
 | 
			
		||||
#include <linux/iopoll.h>
 | 
			
		||||
#include <linux/pci_ids.h>
 | 
			
		||||
#ifndef CONFIG_64BIT
 | 
			
		||||
#include <linux/io-64-nonatomic-lo-hi.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -23,6 +24,9 @@
 | 
			
		|||
#define wr64(a, reg, value)	writeq((value), ((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_M(m, s)		((m ## U) << (s))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue