Commit 19c60fde authored by David S. Miller's avatar David S. Miller
Browse files


Tony Nguyen says:

====================
This series lowers the CPU usage of the ice driver when using its
provided /dev/gnss*.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 4eaeca1f b488ae52
Loading
Loading
Loading
Loading
+10 −19
Original line number Diff line number Diff line
@@ -1619,7 +1619,6 @@ ice_sq_send_cmd_retry(struct ice_hw *hw, struct ice_ctl_q_info *cq,
{
	struct ice_aq_desc desc_cpy;
	bool is_cmd_for_retry;
	u8 *buf_cpy = NULL;
	u8 idx = 0;
	u16 opcode;
	int status;
@@ -1629,11 +1628,8 @@ ice_sq_send_cmd_retry(struct ice_hw *hw, struct ice_ctl_q_info *cq,
	memset(&desc_cpy, 0, sizeof(desc_cpy));

	if (is_cmd_for_retry) {
		if (buf) {
			buf_cpy = kzalloc(buf_size, GFP_KERNEL);
			if (!buf_cpy)
				return -ENOMEM;
		}
		/* All retryable cmds are direct, without buf. */
		WARN_ON(buf);

		memcpy(&desc_cpy, desc, sizeof(desc_cpy));
	}
@@ -1645,17 +1641,12 @@ ice_sq_send_cmd_retry(struct ice_hw *hw, struct ice_ctl_q_info *cq,
		    hw->adminq.sq_last_status != ICE_AQ_RC_EBUSY)
			break;

		if (buf_cpy)
			memcpy(buf, buf_cpy, buf_size);

		memcpy(desc, &desc_cpy, sizeof(desc_cpy));

		mdelay(ICE_SQ_SEND_DELAY_TIME_MS);
		msleep(ICE_SQ_SEND_DELAY_TIME_MS);

	} while (++idx < ICE_SQ_SEND_MAX_EXECUTE);

	kfree(buf_cpy);

	return status;
}

@@ -1992,19 +1983,19 @@ ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,
 */
void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res)
{
	u32 total_delay = 0;
	unsigned long timeout;
	int status;

	status = ice_aq_release_res(hw, res, 0, NULL);

	/* there are some rare cases when trying to release the resource
	 * results in an admin queue timeout, so handle them correctly
	 */
	while ((status == -EIO) && (total_delay < hw->adminq.sq_cmd_timeout)) {
		mdelay(1);
	timeout = jiffies + 10 * ICE_CTL_Q_SQ_CMD_TIMEOUT;
	do {
		status = ice_aq_release_res(hw, res, 0, NULL);
		total_delay++;
	}
		if (status != -EIO)
			break;
		usleep_range(1000, 2000);
	} while (time_before(jiffies, timeout));
}

/**
+5 −7
Original line number Diff line number Diff line
@@ -637,9 +637,6 @@ static int ice_init_ctrlq(struct ice_hw *hw, enum ice_ctl_q q_type)
		return -EIO;
	}

	/* setup SQ command write back timeout */
	cq->sq_cmd_timeout = ICE_CTL_Q_SQ_CMD_TIMEOUT;

	/* allocate the ATQ */
	ret_code = ice_init_sq(hw, cq);
	if (ret_code)
@@ -967,7 +964,7 @@ 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;
	u32 total_delay = 0;
	unsigned long timeout;
	int status = 0;
	u16 retval = 0;
	u32 val = 0;
@@ -1060,13 +1057,14 @@ ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq,
		cq->sq.next_to_use = 0;
	wr32(hw, cq->sq.tail, cq->sq.next_to_use);

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

		udelay(ICE_CTL_Q_SQ_CMD_USEC);
		total_delay++;
	} while (total_delay < cq->sq_cmd_timeout);
		usleep_range(ICE_CTL_Q_SQ_CMD_USEC,
			     ICE_CTL_Q_SQ_CMD_USEC * 3 / 2);
	} while (time_before(jiffies, timeout));

	/* if ready, copy the desc back to temp */
	if (ice_sq_done(hw, cq)) {
+1 −2
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@ enum ice_ctl_q {
};

/* Control Queue timeout settings - max delay 1s */
#define ICE_CTL_Q_SQ_CMD_TIMEOUT	10000 /* Count 10000 times */
#define ICE_CTL_Q_SQ_CMD_TIMEOUT	HZ    /* Wait max 1s */
#define ICE_CTL_Q_SQ_CMD_USEC		100   /* Check every 100usec */
#define ICE_CTL_Q_ADMIN_INIT_TIMEOUT	10    /* Count 10 times */
#define ICE_CTL_Q_ADMIN_INIT_MSEC	100   /* Check every 100msec */
@@ -87,7 +87,6 @@ struct ice_ctl_q_info {
	enum ice_ctl_q qtype;
	struct ice_ctl_q_ring rq;	/* receive queue */
	struct ice_ctl_q_ring sq;	/* send queue */
	u32 sq_cmd_timeout;		/* send queue cmd write back timeout */
	u16 num_rq_entries;		/* receive queue depth */
	u16 num_sq_entries;		/* send queue depth */
	u16 rq_buf_size;		/* receive queue buffer size */
+19 −23
Original line number Diff line number Diff line
@@ -117,6 +117,7 @@ static void ice_gnss_read(struct kthread_work *work)
{
	struct gnss_serial *gnss = container_of(work, struct gnss_serial,
						read_work.work);
	unsigned long delay = ICE_GNSS_POLL_DATA_DELAY_TIME;
	unsigned int i, bytes_read, data_len, count;
	struct ice_aqc_link_topo_addr link_topo;
	struct ice_pf *pf;
@@ -136,11 +137,6 @@ static void ice_gnss_read(struct kthread_work *work)
		return;

	hw = &pf->hw;
	buf = (char *)get_zeroed_page(GFP_KERNEL);
	if (!buf) {
		err = -ENOMEM;
		goto exit;
	}

	memset(&link_topo, 0, sizeof(struct ice_aqc_link_topo_addr));
	link_topo.topo_params.index = ICE_E810T_GNSS_I2C_BUS;
@@ -151,25 +147,24 @@ static void ice_gnss_read(struct kthread_work *work)
	i2c_params = ICE_GNSS_UBX_DATA_LEN_WIDTH |
		     ICE_AQC_I2C_USE_REPEATED_START;

	/* Read data length in a loop, when it's not 0 the data is ready */
	for (i = 0; i < ICE_MAX_UBX_READ_TRIES; i++) {
	err = ice_aq_read_i2c(hw, link_topo, ICE_GNSS_UBX_I2C_BUS_ADDR,
			      cpu_to_le16(ICE_GNSS_UBX_DATA_LEN_H),
			      i2c_params, (u8 *)&data_len_b, NULL);
	if (err)
			goto exit_buf;
		goto requeue;

	data_len = be16_to_cpu(data_len_b);
		if (data_len != 0 && data_len != U16_MAX)
			break;
	if (data_len == 0 || data_len == U16_MAX)
		goto requeue;

		mdelay(10);
	}
	/* The u-blox has data_len bytes for us to read */

	data_len = min_t(typeof(data_len), data_len, PAGE_SIZE);
	if (!data_len) {

	buf = (char *)get_zeroed_page(GFP_KERNEL);
	if (!buf) {
		err = -ENOMEM;
		goto exit_buf;
		goto requeue;
	}

	/* Read received data */
@@ -183,7 +178,7 @@ static void ice_gnss_read(struct kthread_work *work)
				      cpu_to_le16(ICE_GNSS_UBX_EMPTY_DATA),
				      bytes_read, &buf[i], NULL);
		if (err)
			goto exit_buf;
			goto free_buf;
	}

	count = gnss_insert_raw(pf->gnss_dev, buf, i);
@@ -191,10 +186,11 @@ static void ice_gnss_read(struct kthread_work *work)
		dev_warn(ice_pf_to_dev(pf),
			 "gnss_insert_raw ret=%d size=%d\n",
			 count, i);
exit_buf:
	delay = ICE_GNSS_TIMER_DELAY_TIME;
free_buf:
	free_page((unsigned long)buf);
	kthread_queue_delayed_work(gnss->kworker, &gnss->read_work,
				   ICE_GNSS_TIMER_DELAY_TIME);
requeue:
	kthread_queue_delayed_work(gnss->kworker, &gnss->read_work, delay);
exit:
	if (err)
		dev_dbg(ice_pf_to_dev(pf), "GNSS failed to read err=%d\n", err);
+1 −2
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
#define _ICE_GNSS_H_

#define ICE_E810T_GNSS_I2C_BUS		0x2
#define ICE_GNSS_POLL_DATA_DELAY_TIME	(HZ / 50) /* poll every 20 ms */
#define ICE_GNSS_TIMER_DELAY_TIME	(HZ / 10) /* 0.1 second per message */
#define ICE_GNSS_TTY_WRITE_BUF		250
#define ICE_MAX_I2C_DATA_SIZE		FIELD_MAX(ICE_AQC_I2C_DATA_SIZE_M)
@@ -20,8 +21,6 @@
 * passed as I2C addr parameter.
 */
#define ICE_GNSS_UBX_WRITE_BYTES	(ICE_MAX_I2C_WRITE_BYTES + 1)
#define ICE_MAX_UBX_READ_TRIES		255
#define ICE_MAX_UBX_ACK_READ_TRIES	4095

struct gnss_write_buf {
	struct list_head queue;