diff options
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_gnss.c')
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_gnss.c | 114 |
1 files changed, 24 insertions, 90 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_gnss.c b/drivers/net/ethernet/intel/ice/ice_gnss.c index 8dec748bb53a4..75c9de675f202 100644 --- a/drivers/net/ethernet/intel/ice/ice_gnss.c +++ b/drivers/net/ethernet/intel/ice/ice_gnss.c @@ -16,8 +16,8 @@ * * number of bytes written - success * * negative - error code */ -static unsigned int -ice_gnss_do_write(struct ice_pf *pf, unsigned char *buf, unsigned int size) +static int +ice_gnss_do_write(struct ice_pf *pf, const unsigned char *buf, unsigned int size) { struct ice_aqc_link_topo_addr link_topo; struct ice_hw *hw = &pf->hw; @@ -72,39 +72,7 @@ err_out: dev_err(ice_pf_to_dev(pf), "GNSS failed to write, offset=%u, size=%u, err=%d\n", offset, size, err); - return offset; -} - -/** - * ice_gnss_write_pending - Write all pending data to internal GNSS - * @work: GNSS write work structure - */ -static void ice_gnss_write_pending(struct kthread_work *work) -{ - struct gnss_serial *gnss = container_of(work, struct gnss_serial, - write_work); - struct ice_pf *pf = gnss->back; - - if (!pf) - return; - - if (!test_bit(ICE_FLAG_GNSS, pf->flags)) - return; - - if (!list_empty(&gnss->queue)) { - struct gnss_write_buf *write_buf = NULL; - unsigned int bytes; - - write_buf = list_first_entry(&gnss->queue, - struct gnss_write_buf, queue); - - bytes = ice_gnss_do_write(pf, write_buf->buf, write_buf->size); - dev_dbg(ice_pf_to_dev(pf), "%u bytes written to GNSS\n", bytes); - - list_del(&write_buf->queue); - kfree(write_buf->buf); - kfree(write_buf); - } + return err; } /** @@ -117,6 +85,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; @@ -127,20 +96,10 @@ static void ice_gnss_read(struct kthread_work *work) int err = 0; pf = gnss->back; - if (!pf) { - err = -EFAULT; - goto exit; - } - - if (!test_bit(ICE_FLAG_GNSS, pf->flags)) + if (!pf || !test_bit(ICE_FLAG_GNSS, pf->flags)) 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 +110,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; + 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 requeue; - data_len = be16_to_cpu(data_len_b); - if (data_len != 0 && data_len != U16_MAX) - break; + data_len = be16_to_cpu(data_len_b); + 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 +141,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,11 +149,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); -exit: +requeue: + kthread_queue_delayed_work(gnss->kworker, &gnss->read_work, delay); if (err) dev_dbg(ice_pf_to_dev(pf), "GNSS failed to read err=%d\n", err); } @@ -224,8 +182,6 @@ static struct gnss_serial *ice_gnss_struct_init(struct ice_pf *pf) pf->gnss_serial = gnss; kthread_init_delayed_work(&gnss->read_work, ice_gnss_read); - INIT_LIST_HEAD(&gnss->queue); - kthread_init_work(&gnss->write_work, ice_gnss_write_pending); kworker = kthread_create_worker(0, "ice-gnss-%s", dev_name(dev)); if (IS_ERR(kworker)) { kfree(gnss); @@ -285,7 +241,6 @@ static void ice_gnss_close(struct gnss_device *gdev) if (!gnss) return; - kthread_cancel_work_sync(&gnss->write_work); kthread_cancel_delayed_work_sync(&gnss->read_work); } @@ -304,10 +259,7 @@ ice_gnss_write(struct gnss_device *gdev, const unsigned char *buf, size_t count) { struct ice_pf *pf = gnss_get_drvdata(gdev); - struct gnss_write_buf *write_buf; struct gnss_serial *gnss; - unsigned char *cmd_buf; - int err = count; /* We cannot write a single byte using our I2C implementation. */ if (count <= 1 || count > ICE_GNSS_TTY_WRITE_BUF) @@ -323,24 +275,7 @@ ice_gnss_write(struct gnss_device *gdev, const unsigned char *buf, if (!gnss) return -ENODEV; - cmd_buf = kcalloc(count, sizeof(*buf), GFP_KERNEL); - if (!cmd_buf) - return -ENOMEM; - - memcpy(cmd_buf, buf, count); - write_buf = kzalloc(sizeof(*write_buf), GFP_KERNEL); - if (!write_buf) { - kfree(cmd_buf); - return -ENOMEM; - } - - write_buf->buf = cmd_buf; - write_buf->size = count; - INIT_LIST_HEAD(&write_buf->queue); - list_add_tail(&write_buf->queue, &gnss->queue); - kthread_queue_work(gnss->kworker, &gnss->write_work); - - return err; + return ice_gnss_do_write(pf, buf, count); } static const struct gnss_operations ice_gnss_ops = { @@ -436,7 +371,6 @@ void ice_gnss_exit(struct ice_pf *pf) if (pf->gnss_serial) { struct gnss_serial *gnss = pf->gnss_serial; - kthread_cancel_work_sync(&gnss->write_work); kthread_cancel_delayed_work_sync(&gnss->read_work); kthread_destroy_worker(gnss->kworker); gnss->kworker = NULL; |