Message ID | 1432574909-2326-1-git-send-email-kernel@martin.sperl.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Mon, May 25, 2015 at 05:28:28PM +0000, kernel@martin.sperl.org wrote:
> * bytes_histo transferred bytes/spi_transfer histogram
To repeat my previous review comments: the sysfs ABI requires one value
per file and a histogram is not a single value. To further repeat
myself either remove this or export it somewhere more appropriate like
debugfs.
On 05/25/2015 07:28 PM, kernel@martin.sperl.org wrote: > From: Martin Sperl <kernel@martin.sperl.org> > > per spi-master statistics accessible as: > /sys/class/spi_master/spi*/statistics/ > > per spi-device statistics accessible via: > /sys/class/spi_master/spi*/spi*.*/statistics/ > > The following statistics are exposed as separate "files" inside > these directories: > * messages number of spi_messages > * transfers number of spi_transfers > * bytes number of bytes transferred > * bytes_rx number of bytes transmitted > * bytes_tx number of bytes received > * bytes_histo transferred bytes/spi_transfer histogram Having those kinds of stats in world readable files has serious security implications as they can be used to implement side-channel attacks. They should probably only be available in debugfs for root. -- To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Wed, Jun 03, 2015 at 01:25:58PM +0200, Lars-Peter Clausen wrote: > Having those kinds of stats in world readable files has serious security > implications as they can be used to implement side-channel attacks. They > should probably only be available in debugfs for root. We do get to control the permissions on sysfs files, though it's a bit more unusual to make things root only (and there is the histogram).
> On 03.06.2015, at 13:53, Mark Brown <broonie@kernel.org> wrote: > >> On Wed, Jun 03, 2015 at 01:25:58PM +0200, Lars-Peter Clausen wrote: >> >> Having those kinds of stats in world readable files has serious security >> implications as they can be used to implement side-channel attacks. They >> should probably only be available in debugfs for root. > > We do get to control the permissions on sysfs files, though it's a bit > more unusual to make things root only (and there is the histogram). I left histogram as a single file because I remember having seen a file in /sys with similar semantics using multiple values (but I can not remember which one). I can remove it when I get back near my development box in a little more than a week. As for side channel attacks: the information is there already. E.g the number of Interrupts for the spi device in /proc/interrupts This could also be used as an indicator for the number of spi transfers handled, so I do not see a huge difference... If you want it as root only - we can do it, but I wonder if it is making a real difference... -- To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
> On 04.06.2015, at 18:56, Martin Sperl <kernel@martin.sperl.org> wrote: >> We do get to control the permissions on sysfs files, though it's a bit >> more unusual to make things root only (and there is the histogram). > > I left histogram as a single file because I remember having seen a file in > /sys with similar semantics using multiple values (but I can not > remember which one). Now that I am back here some examples from /sys which contain multiple values: /sys/devices/platform/soc/20980000.usb/pools: poolinfo - 0.1 buffer-2048 0 0 2048 0 buffer-512 0 0 512 0 buffer-128 1 32 128 1 buffer-32 0 0 32 0 /sys/devices/platform/soc/20980000.usb/usb1/1-1/1-1.3/1-1.3:1.0/host0/target0:0:0/0:0:0:0/block/sda/sda1/stat: /sys/devices/platform/soc/20300000.sdhci/mmc_host/mmc0/mmc0:e624/block/mmcblk0/mmcblk0p1/stat: 425 56 3842 670 7 9 128 2080 0 1530 2750 /sys/kernel/vmcoreinfo: 85d84c 1024 /sys/devices/platform/soc/20300000.sdhci/mmc_host/mmc0/mmc0:e624/block/mmcblk0/inflight: /sys/devices/platform/soc/20980000.usb/usb1/1-1/1-1.3/1-1.3:1.0/host0/target0:0:0/0:0:0:0/block/sda/sda1/inflight: 0 0 So it is rare, but not totally uncommon - especially those block statistics. I can still remove the histogram or move it to separate files per bin (similar to /sys/kernel/slab/:t-*) What would you prefer so that I can fix the patch?-- To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, Jun 18, 2015 at 02:54:35PM +0200, Martin Sperl wrote: > Now that I am back here some examples from /sys which contain multiple values: > /sys/devices/platform/soc/20980000.usb/pools: The fact that other people have broken the ABI doesn't mean it's a good idea to introduce further ABI breakage.
On Thu, 18 Jun 2015 14:49:18 +0100, Mark Brown wrote: > On Thu, Jun 18, 2015 at 02:54:35PM +0200, Martin Sperl wrote: > > > Now that I am back here some examples from /sys which contain multiple values: > > /sys/devices/platform/soc/20980000.usb/pools: > > The fact that other people have broken the ABI doesn't mean it's a good > idea to introduce further ABI breakage. How about putting this file in debugfs after all? Mark suggested it initially but the conversation went in other direction. Martin said that his main purpose is to help *debugging* performance of RPi dma, so it's a perfect candidate for debugfs. I can't in my mind see any use for this information on a production system to be honest... -- To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, 18 Jun 2015 14:49:18 +0100, Mark Brown wrote: > On Thu, Jun 18, 2015 at 02:54:35PM +0200, Martin Sperl wrote: > > > Now that I am back here some examples from /sys which contain multiple values: > > /sys/devices/platform/soc/20980000.usb/pools: > > The fact that other people have broken the ABI doesn't mean it's a good > idea to introduce further ABI breakage. How about putting this file in debugfs after all? Mark suggested it initially but the conversation went in other direction. Martin said that his main purpose is to help *debugging* performance of RPi dma, so it's a perfect candidate for debugfs. I can't in my mind see any use for this information on a production system to be honest... -- To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, Jun 19, 2015 at 11:35:39AM +0200, Jakub Kici?ski wrote: > How about putting this file in debugfs after all? Mark suggested it > initially but the conversation went in other direction. Martin said > that his main purpose is to help *debugging* performance of RPi dma, > so it's a perfect candidate for debugfs. I can't in my mind see any > use for this information on a production system to be honest... That's the solution I'd been expecting.
On Thu, 18 Jun 2015 14:49:18 +0100, Mark Brown wrote: > On Thu, Jun 18, 2015 at 02:54:35PM +0200, Martin Sperl wrote: > > > Now that I am back here some examples from /sys which contain multiple values: > > /sys/devices/platform/soc/20980000.usb/pools: > > The fact that other people have broken the ABI doesn't mean it's a good > idea to introduce further ABI breakage. How about putting this file in debugfs after all? Mark suggested it initially but the conversation went in other direction. Martin said that his main purpose is to help *debugging* performance of RPi dma, so it's a perfect candidate for debugfs. I can't in my mind see any use for this information on a production system to be honest... -- To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, 19 Jun 2015 11:56:25 +0200, Jakub Kici?ski wrote: > On Thu, 18 Jun 2015 14:49:18 +0100, Mark Brown wrote: > > On Thu, Jun 18, 2015 at 02:54:35PM +0200, Martin Sperl wrote: > > > > > Now that I am back here some examples from /sys which contain multiple values: > > > /sys/devices/platform/soc/20980000.usb/pools: > > > > The fact that other people have broken the ABI doesn't mean it's a good > > idea to introduce further ABI breakage. > > How about putting this file in debugfs after all? Mark suggested it > initially but the conversation went in other direction. Martin said > that his main purpose is to help *debugging* performance of RPi dma, > so it's a perfect candidate for debugfs. I can't in my mind see any > use for this information on a production system to be honest... Sorry about triple posting, my mail provider got banned by spamcop :$ -- To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
> On 19.06.2015, at 11:53, Mark Brown <broonie@kernel.org> wrote: > > On Fri, Jun 19, 2015 at 11:35:39AM +0200, Jakub Kici?ski wrote: > >> How about putting this file in debugfs after all? Mark suggested it >> initially but the conversation went in other direction. Martin said >> that his main purpose is to help *debugging* performance of RPi dma, >> so it's a perfect candidate for debugfs. I can't in my mind see any >> use for this information on a production system to be honest... > > That's the solution I'd been expecting. I got a patch in the meantime exposing the following files in /sys/devices/platform/soc/20204000.spi/spi_master/spi32766/statistics/: bytes bytes_rx bytes_tx bytes_transfer_histo_0-1 bytes_transfer_histo_1024-2047 bytes_transfer_histo_128-255 bytes_transfer_histo_16-31 bytes_transfer_histo_16384-32767 bytes_transfer_histo_2048-4095 bytes_transfer_histo_2-3 bytes_transfer_histo_256-511 bytes_transfer_histo_32-63 bytes_transfer_histo_32768-65535 bytes_transfer_histo_4096-8191 bytes_transfer_histo_4-7 bytes_transfer_histo_512-1023 bytes_transfer_histo_64-127 bytes_transfer_histo_65536+ bytes_transfer_histo_8-15 bytes_transfer_histo_8192-16383 errors messages spi_async spi_sync spi_sync_immediate timedout transfers You want me to move the bytes_transfer_histo_* now into debugfs instead? If so then I would post a “basic” patch for the other statistics and have debugfs for the histogram as a separate patch. Martin-- To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, Jun 19, 2015 at 12:02:22PM +0200, Martin Sperl wrote: > I got a patch in the meantime exposing the following files in > /sys/devices/platform/soc/20204000.spi/spi_master/spi32766/statistics/: > bytes > bytes_rx > bytes_tx > bytes_transfer_histo_0-1 > bytes_transfer_histo_1024-2047 > If so then I would post a “basic” patch for the other statistics > and have debugfs for the histogram as a separate patch. Either approach works for me, though I suppose we might want to bikeshed the naming of the histogram files above (but I can't think of better ideas immediately) and I guess from a user point of view getting the histogram as a histogram might be more helpful so people might be happier with debugfs.
On Fri, Jun 19, 2015 at 12:10 PM, Mark Brown <broonie@kernel.org> wrote: > On Fri, Jun 19, 2015 at 12:02:22PM +0200, Martin Sperl wrote: > >> I got a patch in the meantime exposing the following files in >> /sys/devices/platform/soc/20204000.spi/spi_master/spi32766/statistics/: >> bytes >> bytes_rx >> bytes_tx >> bytes_transfer_histo_0-1 >> bytes_transfer_histo_1024-2047 > >> If so then I would post a “basic” patch for the other statistics >> and have debugfs for the histogram as a separate patch. > > Either approach works for me, though I suppose we might want to bikeshed > the naming of the histogram files above (but I can't think of better > ideas immediately) and I guess from a user point of view getting the Zero-prefixing the numbers in the filenames would make it a bit less ugly and auto-sorted... > histogram as a histogram might be more helpful so people might be > happier with debugfs. ... but indeed, quoting Documentation/filesystems/debugfs.txt: "Unlike sysfs, which has strict one-value-per-file rules, debugfs has no rules at all." So storing the whole histogram in a single file sounds like the logical thing to me. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds -- To unsubscribe from this list: send the line "unsubscribe linux-spi" in
> On 20.06.2015, at 14:10, Geert Uytterhoeven <geert@linux-m68k.org> wrote: > Zero-prefixing the numbers in the filenames would make it a bit less ugly > and auto-sorted… a possibility >> histogram as a histogram might be more helpful so people might be >> happier with debugfs. > > ... but indeed, quoting Documentation/filesystems/debugfs.txt: > > "Unlike sysfs, which has strict one-value-per-file rules, debugfs has no > rules at all." > > So storing the whole histogram in a single file sounds like the logical > thing to me. The point with debugfs would be that we would need to start a “structure” in the framework that can get easily extended, which obviously would need more thought, so that a driver can easily expose additional data. So something along the lines of: /sys/kernel/debug/spi/<bus>/* /sys/kernel/debug/spi/<bus>/<device>/* And with the right api we could make it easily extendable (much more easily than with sysfs...) So what I would do I post a patch to expose those “basics” via sysfs and then a patch to expose the histogram and potentially more via debugfs. -- To unsubscribe from this list: send the line "unsubscribe linux-spi" in
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index d35c1a1..f50cee3 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -67,11 +67,163 @@ modalias_show(struct device *dev, struct device_attribute *a, char *buf) } static DEVICE_ATTR_RO(modalias); +#define SPI_STATISTICS_ATTRS(field) \ +static ssize_t spi_master_##field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct spi_master *master = container_of(dev, \ + struct spi_master, dev); \ + return spi_statistics_##field##_show(&master->statistics, buf); \ +} \ +static struct device_attribute dev_attr_spi_master_##field = { \ + .attr = { .name = __stringify(field), .mode = S_IRUGO }, \ + .show = spi_master_##field##_show, \ +}; \ +static ssize_t spi_device_##field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct spi_device *spi = container_of(dev, \ + struct spi_device, dev); \ + return spi_statistics_##field##_show(&spi->statistics, buf); \ +} \ +static struct device_attribute dev_attr_spi_device_##field = { \ + .attr = { .name = __stringify(field), .mode = S_IRUGO }, \ + .show = spi_device_##field##_show, \ +} + +#define SPI_STATISTICS_SHOW(field, format_string) \ +static ssize_t spi_statistics_##field##_show(struct spi_statistics *stat, \ + char *buf) \ +{ \ + unsigned long flags; \ + ssize_t len; \ + spin_lock_irqsave(&stat->lock, flags); \ + len = sprintf(buf, format_string, stat->field); \ + spin_unlock_irqrestore(&stat->lock, flags); \ + return len; \ + } \ +SPI_STATISTICS_ATTRS(field) + +SPI_STATISTICS_SHOW(messages, "%lu"); +SPI_STATISTICS_SHOW(transfers, "%lu"); +SPI_STATISTICS_SHOW(errors, "%lu"); +SPI_STATISTICS_SHOW(timedout, "%lu"); + +SPI_STATISTICS_SHOW(spi_sync, "%lu"); +SPI_STATISTICS_SHOW(spi_sync_immediate, "%lu"); +SPI_STATISTICS_SHOW(spi_async, "%lu"); + +SPI_STATISTICS_SHOW(bytes, "%llu"); +SPI_STATISTICS_SHOW(bytes_rx, "%llu"); +SPI_STATISTICS_SHOW(bytes_tx, "%llu"); + +static ssize_t spi_statistics_bytes_histo_show(struct spi_statistics *stats, + char *buf) +{ + int i; + ssize_t len; + unsigned long flags; + + spin_lock_irqsave(&stats->lock, flags); + len = sprintf(buf, "%lu", stats->bytes_l2histo[0]); + for (i = 1; i < SPI_STATISTICS_L2HISTO_SIZE; i++) + len += sprintf(buf + len, " %lu", + stats->bytes_l2histo[i]); + spin_unlock_irqrestore(&stats->lock, flags); + + return len; +} +SPI_STATISTICS_ATTRS(bytes_histo); + static struct attribute *spi_dev_attrs[] = { &dev_attr_modalias.attr, NULL, }; -ATTRIBUTE_GROUPS(spi_dev); + +static const struct attribute_group spi_dev_group = { + .attrs = spi_dev_attrs, +}; + +static struct attribute *spi_device_statistics_attrs[] = { + &dev_attr_spi_device_messages.attr, + &dev_attr_spi_device_transfers.attr, + &dev_attr_spi_device_errors.attr, + &dev_attr_spi_device_timedout.attr, + &dev_attr_spi_device_spi_sync.attr, + &dev_attr_spi_device_spi_sync_immediate.attr, + &dev_attr_spi_device_spi_async.attr, + &dev_attr_spi_device_bytes.attr, + &dev_attr_spi_device_bytes_rx.attr, + &dev_attr_spi_device_bytes_tx.attr, + &dev_attr_spi_device_bytes_histo.attr, + NULL, +}; + +static const struct attribute_group spi_device_statistics_group = { + .name = "statistics", + .attrs = spi_device_statistics_attrs, +}; + +static const struct attribute_group *spi_dev_groups[] = { + &spi_dev_group, + &spi_device_statistics_group, + NULL, +}; + +static struct attribute *spi_master_statistics_attrs[] = { + &dev_attr_spi_master_messages.attr, + &dev_attr_spi_master_transfers.attr, + &dev_attr_spi_master_errors.attr, + &dev_attr_spi_master_timedout.attr, + &dev_attr_spi_master_spi_sync.attr, + &dev_attr_spi_master_spi_sync_immediate.attr, + &dev_attr_spi_master_spi_async.attr, + &dev_attr_spi_master_bytes.attr, + &dev_attr_spi_master_bytes_rx.attr, + &dev_attr_spi_master_bytes_tx.attr, + &dev_attr_spi_master_bytes_histo.attr, + NULL, +}; + +static const struct attribute_group spi_master_statistics_group = { + .name = "statistics", + .attrs = spi_master_statistics_attrs, +}; + +static const struct attribute_group *spi_master_groups[] = { + &spi_master_statistics_group, + NULL, +}; + +void spi_statistics_add_transfer_stats(struct spi_statistics *stats, + struct spi_transfer *xfer, + struct spi_master *master) +{ + unsigned long flags; + int l2len = min(fls(xfer->len), SPI_STATISTICS_L2HISTO_SIZE) - 1; + + if (l2len < 0) + l2len = 0; + + spin_lock_irqsave(&stats->lock, flags); + + stats->transfers++; + + stats->bytes_l2histo[l2len]++; + + stats->bytes += xfer->len; + if ((xfer->tx_buf) && + (xfer->tx_buf != master->dummy_tx)) + stats->bytes_tx += xfer->len; + if ((xfer->rx_buf) && + (xfer->rx_buf != master->dummy_rx)) + stats->bytes_rx += xfer->len; + + spin_unlock_irqrestore(&stats->lock, flags); +} +EXPORT_SYMBOL_GPL(spi_statistics_add_transfer_stats); /* modalias support makes "modprobe $MODALIAS" new-style hotplug work, * and the sysfs version makes coldplug work too. @@ -249,6 +401,9 @@ struct spi_device *spi_alloc_device(struct spi_master *master) spi->dev.bus = &spi_bus_type; spi->dev.release = spidev_release; spi->cs_gpio = -ENOENT; + + spin_lock_init(&spi->statistics.lock); + device_initialize(&spi->dev); return spi; } @@ -679,17 +834,29 @@ static int spi_transfer_one_message(struct spi_master *master, bool keep_cs = false; int ret = 0; unsigned long ms = 1; + struct spi_statistics *statm = &master->statistics; + struct spi_statistics *stats = &msg->spi->statistics; spi_set_cs(msg->spi, true); + SPI_STATISTICS_INCREMENT_FIELD(statm, messages); + SPI_STATISTICS_INCREMENT_FIELD(stats, messages); + list_for_each_entry(xfer, &msg->transfers, transfer_list) { trace_spi_transfer_start(msg, xfer); + spi_statistics_add_transfer_stats(statm, xfer, master); + spi_statistics_add_transfer_stats(stats, xfer, master); + if (xfer->tx_buf || xfer->rx_buf) { reinit_completion(&master->xfer_completion); ret = master->transfer_one(master, msg->spi, xfer); if (ret < 0) { + SPI_STATISTICS_INCREMENT_FIELD(statm, + errors); + SPI_STATISTICS_INCREMENT_FIELD(stats, + errors); dev_err(&msg->spi->dev, "SPI transfer failed: %d\n", ret); goto out; @@ -705,6 +872,10 @@ static int spi_transfer_one_message(struct spi_master *master, } if (ms == 0) { + SPI_STATISTICS_INCREMENT_FIELD(statm, + timedout); + SPI_STATISTICS_INCREMENT_FIELD(stats, + timedout); dev_err(&msg->spi->dev, "SPI transfer timed out\n"); msg->status = -ETIMEDOUT; @@ -1406,10 +1577,10 @@ static struct class spi_master_class = { .name = "spi_master", .owner = THIS_MODULE, .dev_release = spi_master_release, + .dev_groups = spi_master_groups, }; - /** * spi_alloc_master - allocate SPI master controller * @dev: the controller, possibly using the platform_bus @@ -1575,6 +1746,8 @@ int spi_register_master(struct spi_master *master) goto done; } } + /* add statistics */ + spin_lock_init(&master->statistics.lock); mutex_lock(&board_lock); list_add_tail(&master->list, &spi_master_list); @@ -1929,6 +2102,9 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) message->spi = spi; + SPI_STATISTICS_INCREMENT_FIELD(&master->statistics, spi_async); + SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics, spi_async); + trace_spi_message_submit(message); return master->transfer(spi, message); @@ -2065,6 +2241,9 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message, message->context = &done; message->spi = spi; + SPI_STATISTICS_INCREMENT_FIELD(&master->statistics, spi_sync); + SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics, spi_sync); + if (!bus_locked) mutex_lock(&master->bus_lock_mutex); @@ -2092,8 +2271,13 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message, /* Push out the messages in the calling context if we * can. */ - if (master->transfer == spi_queued_transfer) + if (master->transfer == spi_queued_transfer) { + SPI_STATISTICS_INCREMENT_FIELD(&master->statistics, + spi_sync_immediate); + SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics, + spi_sync_immediate); __spi_pump_messages(master, false); + } wait_for_completion(&done); status = message->status; diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index d673072..606212a 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -23,6 +23,8 @@ #include <linux/scatterlist.h> struct dma_chan; +struct spi_master; +struct spi_transfer; /* * INTERFACES between SPI master-side drivers and SPI infrastructure. @@ -31,6 +33,63 @@ struct dma_chan; extern struct bus_type spi_bus_type; /** + * struct spi_statistics - statistics for spi transfers + * @clock: lock protecting this structure + * + * @messages: number of spi-messages handled + * @transfers: number of spi_transfers handled + * @errors: number of errors during spi_transfer + * @timedout: number of timeouts during spi_transfer + * + * @spi_sync: number of times spi_sync is used + * @spi_sync_immediate: + * number of times spi_sync is executed immediately + * in calling context without queuing and scheduling + * @spi_async: number of times spi_async is used + * + * @bytes: number of bytes transferred to/from device + * @bytes_tx: number of bytes sent to device + * @bytes_rx: number of bytes received from device + * + * @bytes_l2histo: histogram of bytes per spi_transfer (log2 with saturation) + */ +struct spi_statistics { + spinlock_t lock; /* lock for the whole structure */ + + unsigned long messages; + unsigned long transfers; + unsigned long errors; + unsigned long timedout; + + unsigned long spi_sync; + unsigned long spi_sync_immediate; + unsigned long spi_async; + + unsigned long long bytes; + unsigned long long bytes_rx; + unsigned long long bytes_tx; + + /* histogram of log2(size) between 0 and 65536 with saturation */ +#define SPI_STATISTICS_L2HISTO_SIZE 17 + unsigned long bytes_l2histo[SPI_STATISTICS_L2HISTO_SIZE]; +}; + +void spi_statistics_add_transfer_stats(struct spi_statistics *stats, + struct spi_transfer *xfer, + struct spi_master *master); + +#define SPI_STATISTICS_ADD_TO_FIELD(stats, field, count) \ + do { \ + unsigned long flags; \ + spin_lock_irqsave(&(stats)->lock, flags); \ + (stats)->field += count; \ + spin_unlock_irqrestore(&(stats)->lock, flags); \ + } while (0) + +#define SPI_STATISTICS_INCREMENT_FIELD(stats, field) \ + SPI_STATISTICS_ADD_TO_FIELD(stats, field, 1) + +/** * struct spi_device - Master side proxy for an SPI slave device * @dev: Driver model representation of the device. * @master: SPI controller used with the device. @@ -60,6 +119,8 @@ extern struct bus_type spi_bus_type; * @cs_gpio: gpio number of the chipselect line (optional, -ENOENT when * when not using a GPIO line) * + * @statistics: statistics for the spi_device + * * A @spi_device is used to interchange data between an SPI slave * (usually a discrete chip) and CPU memory. * @@ -98,6 +159,9 @@ struct spi_device { char modalias[SPI_NAME_SIZE]; int cs_gpio; /* chip select gpio */ + /* the statistics */ + struct spi_statistics statistics; + /* * likely need more hooks for more protocol options affecting how * the controller talks to each chip, like: @@ -296,6 +360,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS * number. Any individual value may be -ENOENT for CS lines that * are not GPIOs (driven by the SPI controller itself). + * @statistics: statistics for the spi_master * @dma_tx: DMA transmit channel * @dma_rx: DMA receive channel * @dummy_rx: dummy receive buffer for full-duplex devices @@ -452,6 +517,9 @@ struct spi_master { /* gpio chip select */ int *cs_gpios; + /* statistics */ + struct spi_statistics statistics; + /* DMA channels for use with core dmaengine helpers */ struct dma_chan *dma_tx; struct dma_chan *dma_rx;