Commit 862dd2a9 authored by Vladimir Oltean's avatar Vladimir Oltean Committed by Mark Brown

spi: Don't look at TX buffer for PTP system timestamping

The API for PTP system timestamping (associating a SPI transaction with
the system time at which it was transferred) is flawed: it assumes that
the xfer->tx_buf pointer will always be present.

This is, of course, not always the case.

So introduce a "progress" variable that denotes how many word have been
transferred.

Fix the Freescale DSPI driver, the only user of the API so far, in the
same patch.

Fixes: b42faeee ("spi: Add a PTP system timestamp to the transfer structure")
Fixes: d6b71dfa ("spi: spi-fsl-dspi: Implement the PTP system timestamping for TCFQ mode")
Signed-off-by: default avatarVladimir Oltean <olteanv@gmail.com>
Link: https://lore.kernel.org/r/20191227012417.1057-1-olteanv@gmail.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 9cd34efb
...@@ -185,6 +185,7 @@ struct fsl_dspi { ...@@ -185,6 +185,7 @@ struct fsl_dspi {
struct spi_transfer *cur_transfer; struct spi_transfer *cur_transfer;
struct spi_message *cur_msg; struct spi_message *cur_msg;
struct chip_data *cur_chip; struct chip_data *cur_chip;
size_t progress;
size_t len; size_t len;
const void *tx; const void *tx;
void *rx; void *rx;
...@@ -658,7 +659,7 @@ static int dspi_rxtx(struct fsl_dspi *dspi) ...@@ -658,7 +659,7 @@ static int dspi_rxtx(struct fsl_dspi *dspi)
u32 spi_tcr; u32 spi_tcr;
spi_take_timestamp_post(dspi->ctlr, dspi->cur_transfer, spi_take_timestamp_post(dspi->ctlr, dspi->cur_transfer,
dspi->tx - dspi->bytes_per_word, !dspi->irq); dspi->progress, !dspi->irq);
/* Get transfer counter (in number of SPI transfers). It was /* Get transfer counter (in number of SPI transfers). It was
* reset to 0 when transfer(s) were started. * reset to 0 when transfer(s) were started.
...@@ -667,6 +668,7 @@ static int dspi_rxtx(struct fsl_dspi *dspi) ...@@ -667,6 +668,7 @@ static int dspi_rxtx(struct fsl_dspi *dspi)
spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr); spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr);
/* Update total number of bytes that were transferred */ /* Update total number of bytes that were transferred */
msg->actual_length += spi_tcnt * dspi->bytes_per_word; msg->actual_length += spi_tcnt * dspi->bytes_per_word;
dspi->progress += spi_tcnt;
trans_mode = dspi->devtype_data->trans_mode; trans_mode = dspi->devtype_data->trans_mode;
if (trans_mode == DSPI_EOQ_MODE) if (trans_mode == DSPI_EOQ_MODE)
...@@ -679,7 +681,7 @@ static int dspi_rxtx(struct fsl_dspi *dspi) ...@@ -679,7 +681,7 @@ static int dspi_rxtx(struct fsl_dspi *dspi)
return 0; return 0;
spi_take_timestamp_pre(dspi->ctlr, dspi->cur_transfer, spi_take_timestamp_pre(dspi->ctlr, dspi->cur_transfer,
dspi->tx, !dspi->irq); dspi->progress, !dspi->irq);
if (trans_mode == DSPI_EOQ_MODE) if (trans_mode == DSPI_EOQ_MODE)
dspi_eoq_write(dspi); dspi_eoq_write(dspi);
...@@ -768,6 +770,7 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr, ...@@ -768,6 +770,7 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
dspi->rx = transfer->rx_buf; dspi->rx = transfer->rx_buf;
dspi->rx_end = dspi->rx + transfer->len; dspi->rx_end = dspi->rx + transfer->len;
dspi->len = transfer->len; dspi->len = transfer->len;
dspi->progress = 0;
/* Validated transfer specific frame size (defaults applied) */ /* Validated transfer specific frame size (defaults applied) */
dspi->bits_per_word = transfer->bits_per_word; dspi->bits_per_word = transfer->bits_per_word;
if (transfer->bits_per_word <= 8) if (transfer->bits_per_word <= 8)
...@@ -789,7 +792,7 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr, ...@@ -789,7 +792,7 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
SPI_CTARE_DTCP(1)); SPI_CTARE_DTCP(1));
spi_take_timestamp_pre(dspi->ctlr, dspi->cur_transfer, spi_take_timestamp_pre(dspi->ctlr, dspi->cur_transfer,
dspi->tx, !dspi->irq); dspi->progress, !dspi->irq);
trans_mode = dspi->devtype_data->trans_mode; trans_mode = dspi->devtype_data->trans_mode;
switch (trans_mode) { switch (trans_mode) {
......
...@@ -1499,8 +1499,7 @@ static void spi_pump_messages(struct kthread_work *work) ...@@ -1499,8 +1499,7 @@ static void spi_pump_messages(struct kthread_work *work)
* advances its @tx buffer pointer monotonically. * advances its @tx buffer pointer monotonically.
* @ctlr: Pointer to the spi_controller structure of the driver * @ctlr: Pointer to the spi_controller structure of the driver
* @xfer: Pointer to the transfer being timestamped * @xfer: Pointer to the transfer being timestamped
* @tx: Pointer to the current word within the xfer->tx_buf that the driver is * @progress: How many words (not bytes) have been transferred so far
* preparing to transmit right now.
* @irqs_off: If true, will disable IRQs and preemption for the duration of the * @irqs_off: If true, will disable IRQs and preemption for the duration of the
* transfer, for less jitter in time measurement. Only compatible * transfer, for less jitter in time measurement. Only compatible
* with PIO drivers. If true, must follow up with * with PIO drivers. If true, must follow up with
...@@ -1510,21 +1509,19 @@ static void spi_pump_messages(struct kthread_work *work) ...@@ -1510,21 +1509,19 @@ static void spi_pump_messages(struct kthread_work *work)
*/ */
void spi_take_timestamp_pre(struct spi_controller *ctlr, void spi_take_timestamp_pre(struct spi_controller *ctlr,
struct spi_transfer *xfer, struct spi_transfer *xfer,
const void *tx, bool irqs_off) size_t progress, bool irqs_off)
{ {
u8 bytes_per_word = DIV_ROUND_UP(xfer->bits_per_word, 8);
if (!xfer->ptp_sts) if (!xfer->ptp_sts)
return; return;
if (xfer->timestamped_pre) if (xfer->timestamped_pre)
return; return;
if (tx < (xfer->tx_buf + xfer->ptp_sts_word_pre * bytes_per_word)) if (progress < xfer->ptp_sts_word_pre)
return; return;
/* Capture the resolution of the timestamp */ /* Capture the resolution of the timestamp */
xfer->ptp_sts_word_pre = (tx - xfer->tx_buf) / bytes_per_word; xfer->ptp_sts_word_pre = progress;
xfer->timestamped_pre = true; xfer->timestamped_pre = true;
...@@ -1546,23 +1543,20 @@ EXPORT_SYMBOL_GPL(spi_take_timestamp_pre); ...@@ -1546,23 +1543,20 @@ EXPORT_SYMBOL_GPL(spi_take_timestamp_pre);
* timestamped. * timestamped.
* @ctlr: Pointer to the spi_controller structure of the driver * @ctlr: Pointer to the spi_controller structure of the driver
* @xfer: Pointer to the transfer being timestamped * @xfer: Pointer to the transfer being timestamped
* @tx: Pointer to the current word within the xfer->tx_buf that the driver has * @progress: How many words (not bytes) have been transferred so far
* just transmitted.
* @irqs_off: If true, will re-enable IRQs and preemption for the local CPU. * @irqs_off: If true, will re-enable IRQs and preemption for the local CPU.
*/ */
void spi_take_timestamp_post(struct spi_controller *ctlr, void spi_take_timestamp_post(struct spi_controller *ctlr,
struct spi_transfer *xfer, struct spi_transfer *xfer,
const void *tx, bool irqs_off) size_t progress, bool irqs_off)
{ {
u8 bytes_per_word = DIV_ROUND_UP(xfer->bits_per_word, 8);
if (!xfer->ptp_sts) if (!xfer->ptp_sts)
return; return;
if (xfer->timestamped_post) if (xfer->timestamped_post)
return; return;
if (tx < (xfer->tx_buf + xfer->ptp_sts_word_post * bytes_per_word)) if (progress < xfer->ptp_sts_word_post)
return; return;
ptp_read_system_postts(xfer->ptp_sts); ptp_read_system_postts(xfer->ptp_sts);
...@@ -1573,7 +1567,7 @@ void spi_take_timestamp_post(struct spi_controller *ctlr, ...@@ -1573,7 +1567,7 @@ void spi_take_timestamp_post(struct spi_controller *ctlr,
} }
/* Capture the resolution of the timestamp */ /* Capture the resolution of the timestamp */
xfer->ptp_sts_word_post = (tx - xfer->tx_buf) / bytes_per_word; xfer->ptp_sts_word_post = progress;
xfer->timestamped_post = true; xfer->timestamped_post = true;
} }
......
...@@ -689,10 +689,10 @@ extern void spi_finalize_current_transfer(struct spi_controller *ctlr); ...@@ -689,10 +689,10 @@ extern void spi_finalize_current_transfer(struct spi_controller *ctlr);
/* Helper calls for driver to timestamp transfer */ /* Helper calls for driver to timestamp transfer */
void spi_take_timestamp_pre(struct spi_controller *ctlr, void spi_take_timestamp_pre(struct spi_controller *ctlr,
struct spi_transfer *xfer, struct spi_transfer *xfer,
const void *tx, bool irqs_off); size_t progress, bool irqs_off);
void spi_take_timestamp_post(struct spi_controller *ctlr, void spi_take_timestamp_post(struct spi_controller *ctlr,
struct spi_transfer *xfer, struct spi_transfer *xfer,
const void *tx, bool irqs_off); size_t progress, bool irqs_off);
/* the spi driver core manages memory for the spi_controller classdev */ /* the spi driver core manages memory for the spi_controller classdev */
extern struct spi_controller *__spi_alloc_controller(struct device *host, extern struct spi_controller *__spi_alloc_controller(struct device *host,
......
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