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

Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue

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
...@@ -1619,7 +1619,6 @@ ice_sq_send_cmd_retry(struct ice_hw *hw, struct ice_ctl_q_info *cq, ...@@ -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; struct ice_aq_desc desc_cpy;
bool is_cmd_for_retry; bool is_cmd_for_retry;
u8 *buf_cpy = NULL;
u8 idx = 0; u8 idx = 0;
u16 opcode; u16 opcode;
int status; int status;
...@@ -1629,11 +1628,8 @@ ice_sq_send_cmd_retry(struct ice_hw *hw, struct ice_ctl_q_info *cq, ...@@ -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)); memset(&desc_cpy, 0, sizeof(desc_cpy));
if (is_cmd_for_retry) { if (is_cmd_for_retry) {
if (buf) { /* All retryable cmds are direct, without buf. */
buf_cpy = kzalloc(buf_size, GFP_KERNEL); WARN_ON(buf);
if (!buf_cpy)
return -ENOMEM;
}
memcpy(&desc_cpy, desc, sizeof(desc_cpy)); 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, ...@@ -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) hw->adminq.sq_last_status != ICE_AQ_RC_EBUSY)
break; break;
if (buf_cpy)
memcpy(buf, buf_cpy, buf_size);
memcpy(desc, &desc_cpy, sizeof(desc_cpy)); 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); } while (++idx < ICE_SQ_SEND_MAX_EXECUTE);
kfree(buf_cpy);
return status; return status;
} }
...@@ -1992,19 +1983,19 @@ ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res, ...@@ -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) void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res)
{ {
u32 total_delay = 0; unsigned long timeout;
int status; int status;
status = ice_aq_release_res(hw, res, 0, NULL);
/* there are some rare cases when trying to release the resource /* there are some rare cases when trying to release the resource
* results in an admin queue timeout, so handle them correctly * results in an admin queue timeout, so handle them correctly
*/ */
while ((status == -EIO) && (total_delay < hw->adminq.sq_cmd_timeout)) { timeout = jiffies + 10 * ICE_CTL_Q_SQ_CMD_TIMEOUT;
mdelay(1); do {
status = ice_aq_release_res(hw, res, 0, NULL); status = ice_aq_release_res(hw, res, 0, NULL);
total_delay++; if (status != -EIO)
} break;
usleep_range(1000, 2000);
} while (time_before(jiffies, timeout));
} }
/** /**
......
...@@ -637,9 +637,6 @@ static int ice_init_ctrlq(struct ice_hw *hw, enum ice_ctl_q q_type) ...@@ -637,9 +637,6 @@ static int ice_init_ctrlq(struct ice_hw *hw, enum ice_ctl_q q_type)
return -EIO; return -EIO;
} }
/* setup SQ command write back timeout */
cq->sq_cmd_timeout = ICE_CTL_Q_SQ_CMD_TIMEOUT;
/* allocate the ATQ */ /* allocate the ATQ */
ret_code = ice_init_sq(hw, cq); ret_code = ice_init_sq(hw, cq);
if (ret_code) if (ret_code)
...@@ -967,7 +964,7 @@ ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq, ...@@ -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; 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;
u32 total_delay = 0; unsigned long timeout;
int status = 0; int status = 0;
u16 retval = 0; u16 retval = 0;
u32 val = 0; u32 val = 0;
...@@ -1060,13 +1057,14 @@ ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq, ...@@ -1060,13 +1057,14 @@ ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq,
cq->sq.next_to_use = 0; cq->sq.next_to_use = 0;
wr32(hw, cq->sq.tail, cq->sq.next_to_use); wr32(hw, cq->sq.tail, cq->sq.next_to_use);
timeout = jiffies + ICE_CTL_Q_SQ_CMD_TIMEOUT;
do { do {
if (ice_sq_done(hw, cq)) if (ice_sq_done(hw, cq))
break; break;
udelay(ICE_CTL_Q_SQ_CMD_USEC); usleep_range(ICE_CTL_Q_SQ_CMD_USEC,
total_delay++; ICE_CTL_Q_SQ_CMD_USEC * 3 / 2);
} while (total_delay < cq->sq_cmd_timeout); } while (time_before(jiffies, timeout));
/* if ready, copy the desc back to temp */ /* if ready, copy the desc back to temp */
if (ice_sq_done(hw, cq)) { if (ice_sq_done(hw, cq)) {
......
...@@ -34,7 +34,7 @@ enum ice_ctl_q { ...@@ -34,7 +34,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 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_SQ_CMD_USEC 100 /* Check every 100usec */
#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 */
...@@ -87,7 +87,6 @@ struct ice_ctl_q_info { ...@@ -87,7 +87,6 @@ struct ice_ctl_q_info {
enum ice_ctl_q qtype; enum ice_ctl_q qtype;
struct ice_ctl_q_ring rq; /* receive queue */ struct ice_ctl_q_ring rq; /* receive queue */
struct ice_ctl_q_ring sq; /* send 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_rq_entries; /* receive queue depth */
u16 num_sq_entries; /* send queue depth */ u16 num_sq_entries; /* send queue depth */
u16 rq_buf_size; /* receive queue buffer size */ u16 rq_buf_size; /* receive queue buffer size */
......
...@@ -117,6 +117,7 @@ static void ice_gnss_read(struct kthread_work *work) ...@@ -117,6 +117,7 @@ static void ice_gnss_read(struct kthread_work *work)
{ {
struct gnss_serial *gnss = container_of(work, struct gnss_serial, struct gnss_serial *gnss = container_of(work, struct gnss_serial,
read_work.work); read_work.work);
unsigned long delay = ICE_GNSS_POLL_DATA_DELAY_TIME;
unsigned int i, bytes_read, data_len, count; unsigned int i, bytes_read, data_len, count;
struct ice_aqc_link_topo_addr link_topo; struct ice_aqc_link_topo_addr link_topo;
struct ice_pf *pf; struct ice_pf *pf;
...@@ -136,11 +137,6 @@ static void ice_gnss_read(struct kthread_work *work) ...@@ -136,11 +137,6 @@ static void ice_gnss_read(struct kthread_work *work)
return; return;
hw = &pf->hw; 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)); memset(&link_topo, 0, sizeof(struct ice_aqc_link_topo_addr));
link_topo.topo_params.index = ICE_E810T_GNSS_I2C_BUS; link_topo.topo_params.index = ICE_E810T_GNSS_I2C_BUS;
...@@ -151,25 +147,24 @@ static void ice_gnss_read(struct kthread_work *work) ...@@ -151,25 +147,24 @@ static void ice_gnss_read(struct kthread_work *work)
i2c_params = ICE_GNSS_UBX_DATA_LEN_WIDTH | i2c_params = ICE_GNSS_UBX_DATA_LEN_WIDTH |
ICE_AQC_I2C_USE_REPEATED_START; ICE_AQC_I2C_USE_REPEATED_START;
/* Read data length in a loop, when it's not 0 the data is ready */ err = ice_aq_read_i2c(hw, link_topo, ICE_GNSS_UBX_I2C_BUS_ADDR,
for (i = 0; i < ICE_MAX_UBX_READ_TRIES; i++) { cpu_to_le16(ICE_GNSS_UBX_DATA_LEN_H),
err = ice_aq_read_i2c(hw, link_topo, ICE_GNSS_UBX_I2C_BUS_ADDR, i2c_params, (u8 *)&data_len_b, NULL);
cpu_to_le16(ICE_GNSS_UBX_DATA_LEN_H), if (err)
i2c_params, (u8 *)&data_len_b, NULL); goto requeue;
if (err)
goto exit_buf;
data_len = be16_to_cpu(data_len_b); data_len = be16_to_cpu(data_len_b);
if (data_len != 0 && data_len != U16_MAX) if (data_len == 0 || data_len == U16_MAX)
break; 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); 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; err = -ENOMEM;
goto exit_buf; goto requeue;
} }
/* Read received data */ /* Read received data */
...@@ -183,7 +178,7 @@ static void ice_gnss_read(struct kthread_work *work) ...@@ -183,7 +178,7 @@ static void ice_gnss_read(struct kthread_work *work)
cpu_to_le16(ICE_GNSS_UBX_EMPTY_DATA), cpu_to_le16(ICE_GNSS_UBX_EMPTY_DATA),
bytes_read, &buf[i], NULL); bytes_read, &buf[i], NULL);
if (err) if (err)
goto exit_buf; goto free_buf;
} }
count = gnss_insert_raw(pf->gnss_dev, buf, i); count = gnss_insert_raw(pf->gnss_dev, buf, i);
...@@ -191,10 +186,11 @@ static void ice_gnss_read(struct kthread_work *work) ...@@ -191,10 +186,11 @@ static void ice_gnss_read(struct kthread_work *work)
dev_warn(ice_pf_to_dev(pf), dev_warn(ice_pf_to_dev(pf),
"gnss_insert_raw ret=%d size=%d\n", "gnss_insert_raw ret=%d size=%d\n",
count, i); count, i);
exit_buf: delay = ICE_GNSS_TIMER_DELAY_TIME;
free_buf:
free_page((unsigned long)buf); free_page((unsigned long)buf);
kthread_queue_delayed_work(gnss->kworker, &gnss->read_work, requeue:
ICE_GNSS_TIMER_DELAY_TIME); kthread_queue_delayed_work(gnss->kworker, &gnss->read_work, delay);
exit: exit:
if (err) if (err)
dev_dbg(ice_pf_to_dev(pf), "GNSS failed to read err=%d\n", err); dev_dbg(ice_pf_to_dev(pf), "GNSS failed to read err=%d\n", err);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#define _ICE_GNSS_H_ #define _ICE_GNSS_H_
#define ICE_E810T_GNSS_I2C_BUS 0x2 #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_TIMER_DELAY_TIME (HZ / 10) /* 0.1 second per message */
#define ICE_GNSS_TTY_WRITE_BUF 250 #define ICE_GNSS_TTY_WRITE_BUF 250
#define ICE_MAX_I2C_DATA_SIZE FIELD_MAX(ICE_AQC_I2C_DATA_SIZE_M) #define ICE_MAX_I2C_DATA_SIZE FIELD_MAX(ICE_AQC_I2C_DATA_SIZE_M)
...@@ -20,8 +21,6 @@ ...@@ -20,8 +21,6 @@
* passed as I2C addr parameter. * passed as I2C addr parameter.
*/ */
#define ICE_GNSS_UBX_WRITE_BYTES (ICE_MAX_I2C_WRITE_BYTES + 1) #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 gnss_write_buf {
struct list_head queue; struct list_head queue;
......
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