Skip to content

Commit 2f8fdcb

Browse files
michichanguy11
authored andcommitted
ice: do not busy-wait to read GNSS data
The ice-gnss-<dev_name> kernel thread, which reads data from the u-blox GNSS module, keep a CPU core almost 100% busy. The main reason is that it busy-waits for data to become available. A simple improvement would be to replace the "mdelay(10);" in ice_gnss_read() with sleeping. A better fix is to not do any waiting directly in the function and just requeue this delayed work as needed. The advantage is that canceling the work from ice_gnss_exit() becomes immediate, rather than taking up to ~2.5 seconds (ICE_MAX_UBX_READ_TRIES * 10 ms). This lowers the CPU usage of the ice-gnss-<dev_name> thread on my system from ~90 % to ~8 %. I am not sure if the larger 0.1 s pause after inserting data into the gnss subsystem is really necessary, but I'm keeping that as it was. Of course, ideally the driver would not have to poll at all, but I don't know if the E810 can watch for GNSS data availability over the i2c bus by itself and notify the driver. Signed-off-by: Michal Schmidt <mschmidt@redhat.com> Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com> Reviewed-by: Simon Horman <simon.horman@corigine.com> Tested-by: Sunitha Mekala <sunithax.d.mekala@intel.com> (A Contingent worker at Intel) Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
1 parent e315e7b commit 2f8fdcb

2 files changed

Lines changed: 20 additions & 25 deletions

File tree

drivers/net/ethernet/intel/ice/ice_gnss.c

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ static void ice_gnss_read(struct kthread_work *work)
117117
{
118118
struct gnss_serial *gnss = container_of(work, struct gnss_serial,
119119
read_work.work);
120+
unsigned long delay = ICE_GNSS_POLL_DATA_DELAY_TIME;
120121
unsigned int i, bytes_read, data_len, count;
121122
struct ice_aqc_link_topo_addr link_topo;
122123
struct ice_pf *pf;
@@ -136,11 +137,6 @@ static void ice_gnss_read(struct kthread_work *work)
136137
return;
137138

138139
hw = &pf->hw;
139-
buf = (char *)get_zeroed_page(GFP_KERNEL);
140-
if (!buf) {
141-
err = -ENOMEM;
142-
goto exit;
143-
}
144140

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

154-
/* Read data length in a loop, when it's not 0 the data is ready */
155-
for (i = 0; i < ICE_MAX_UBX_READ_TRIES; i++) {
156-
err = ice_aq_read_i2c(hw, link_topo, ICE_GNSS_UBX_I2C_BUS_ADDR,
157-
cpu_to_le16(ICE_GNSS_UBX_DATA_LEN_H),
158-
i2c_params, (u8 *)&data_len_b, NULL);
159-
if (err)
160-
goto exit_buf;
150+
err = ice_aq_read_i2c(hw, link_topo, ICE_GNSS_UBX_I2C_BUS_ADDR,
151+
cpu_to_le16(ICE_GNSS_UBX_DATA_LEN_H),
152+
i2c_params, (u8 *)&data_len_b, NULL);
153+
if (err)
154+
goto requeue;
161155

162-
data_len = be16_to_cpu(data_len_b);
163-
if (data_len != 0 && data_len != U16_MAX)
164-
break;
156+
data_len = be16_to_cpu(data_len_b);
157+
if (data_len == 0 || data_len == U16_MAX)
158+
goto requeue;
165159

166-
mdelay(10);
167-
}
160+
/* The u-blox has data_len bytes for us to read */
168161

169162
data_len = min_t(typeof(data_len), data_len, PAGE_SIZE);
170-
if (!data_len) {
163+
164+
buf = (char *)get_zeroed_page(GFP_KERNEL);
165+
if (!buf) {
171166
err = -ENOMEM;
172-
goto exit_buf;
167+
goto requeue;
173168
}
174169

175170
/* Read received data */
@@ -183,18 +178,19 @@ static void ice_gnss_read(struct kthread_work *work)
183178
cpu_to_le16(ICE_GNSS_UBX_EMPTY_DATA),
184179
bytes_read, &buf[i], NULL);
185180
if (err)
186-
goto exit_buf;
181+
goto free_buf;
187182
}
188183

189184
count = gnss_insert_raw(pf->gnss_dev, buf, i);
190185
if (count != i)
191186
dev_warn(ice_pf_to_dev(pf),
192187
"gnss_insert_raw ret=%d size=%d\n",
193188
count, i);
194-
exit_buf:
189+
delay = ICE_GNSS_TIMER_DELAY_TIME;
190+
free_buf:
195191
free_page((unsigned long)buf);
196-
kthread_queue_delayed_work(gnss->kworker, &gnss->read_work,
197-
ICE_GNSS_TIMER_DELAY_TIME);
192+
requeue:
193+
kthread_queue_delayed_work(gnss->kworker, &gnss->read_work, delay);
198194
exit:
199195
if (err)
200196
dev_dbg(ice_pf_to_dev(pf), "GNSS failed to read err=%d\n", err);

drivers/net/ethernet/intel/ice/ice_gnss.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#define _ICE_GNSS_H_
66

77
#define ICE_E810T_GNSS_I2C_BUS 0x2
8+
#define ICE_GNSS_POLL_DATA_DELAY_TIME (HZ / 100) /* poll every 10 ms */
89
#define ICE_GNSS_TIMER_DELAY_TIME (HZ / 10) /* 0.1 second per message */
910
#define ICE_GNSS_TTY_WRITE_BUF 250
1011
#define ICE_MAX_I2C_DATA_SIZE FIELD_MAX(ICE_AQC_I2C_DATA_SIZE_M)
@@ -20,8 +21,6 @@
2021
* passed as I2C addr parameter.
2122
*/
2223
#define ICE_GNSS_UBX_WRITE_BYTES (ICE_MAX_I2C_WRITE_BYTES + 1)
23-
#define ICE_MAX_UBX_READ_TRIES 255
24-
#define ICE_MAX_UBX_ACK_READ_TRIES 4095
2524

2625
struct gnss_write_buf {
2726
struct list_head queue;

0 commit comments

Comments
 (0)