diff options
author | Mark Brown <broonie@kernel.org> | 2015-10-12 13:09:27 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-10-12 13:09:27 -0400 |
commit | 79828b4fa835f73cdaf4bffa48696abdcbea9d02 (patch) | |
tree | 5e0fa7156acb75ba603022bc807df8f2fedb97a8 /drivers/spi/spi.c | |
parent | 721b51fcf91898299d96f4b72cb9434cda29dce6 (diff) | |
parent | 8c1a9d6323abf0fb1e5dad96cf3f1c783505ea5a (diff) |
Merge remote-tracking branch 'asoc/fix/rt5645' into asoc-fix-rt5645
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r-- | drivers/spi/spi.c | 235 |
1 files changed, 217 insertions, 18 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index cf8b91b23a76..3abb3903f2ad 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -67,11 +67,141 @@ modalias_show(struct device *dev, struct device_attribute *a, char *buf) | |||
67 | } | 67 | } |
68 | static DEVICE_ATTR_RO(modalias); | 68 | static DEVICE_ATTR_RO(modalias); |
69 | 69 | ||
70 | #define SPI_STATISTICS_ATTRS(field, file) \ | ||
71 | static ssize_t spi_master_##field##_show(struct device *dev, \ | ||
72 | struct device_attribute *attr, \ | ||
73 | char *buf) \ | ||
74 | { \ | ||
75 | struct spi_master *master = container_of(dev, \ | ||
76 | struct spi_master, dev); \ | ||
77 | return spi_statistics_##field##_show(&master->statistics, buf); \ | ||
78 | } \ | ||
79 | static struct device_attribute dev_attr_spi_master_##field = { \ | ||
80 | .attr = { .name = file, .mode = S_IRUGO }, \ | ||
81 | .show = spi_master_##field##_show, \ | ||
82 | }; \ | ||
83 | static ssize_t spi_device_##field##_show(struct device *dev, \ | ||
84 | struct device_attribute *attr, \ | ||
85 | char *buf) \ | ||
86 | { \ | ||
87 | struct spi_device *spi = container_of(dev, \ | ||
88 | struct spi_device, dev); \ | ||
89 | return spi_statistics_##field##_show(&spi->statistics, buf); \ | ||
90 | } \ | ||
91 | static struct device_attribute dev_attr_spi_device_##field = { \ | ||
92 | .attr = { .name = file, .mode = S_IRUGO }, \ | ||
93 | .show = spi_device_##field##_show, \ | ||
94 | } | ||
95 | |||
96 | #define SPI_STATISTICS_SHOW_NAME(name, file, field, format_string) \ | ||
97 | static ssize_t spi_statistics_##name##_show(struct spi_statistics *stat, \ | ||
98 | char *buf) \ | ||
99 | { \ | ||
100 | unsigned long flags; \ | ||
101 | ssize_t len; \ | ||
102 | spin_lock_irqsave(&stat->lock, flags); \ | ||
103 | len = sprintf(buf, format_string, stat->field); \ | ||
104 | spin_unlock_irqrestore(&stat->lock, flags); \ | ||
105 | return len; \ | ||
106 | } \ | ||
107 | SPI_STATISTICS_ATTRS(name, file) | ||
108 | |||
109 | #define SPI_STATISTICS_SHOW(field, format_string) \ | ||
110 | SPI_STATISTICS_SHOW_NAME(field, __stringify(field), \ | ||
111 | field, format_string) | ||
112 | |||
113 | SPI_STATISTICS_SHOW(messages, "%lu"); | ||
114 | SPI_STATISTICS_SHOW(transfers, "%lu"); | ||
115 | SPI_STATISTICS_SHOW(errors, "%lu"); | ||
116 | SPI_STATISTICS_SHOW(timedout, "%lu"); | ||
117 | |||
118 | SPI_STATISTICS_SHOW(spi_sync, "%lu"); | ||
119 | SPI_STATISTICS_SHOW(spi_sync_immediate, "%lu"); | ||
120 | SPI_STATISTICS_SHOW(spi_async, "%lu"); | ||
121 | |||
122 | SPI_STATISTICS_SHOW(bytes, "%llu"); | ||
123 | SPI_STATISTICS_SHOW(bytes_rx, "%llu"); | ||
124 | SPI_STATISTICS_SHOW(bytes_tx, "%llu"); | ||
125 | |||
70 | static struct attribute *spi_dev_attrs[] = { | 126 | static struct attribute *spi_dev_attrs[] = { |
71 | &dev_attr_modalias.attr, | 127 | &dev_attr_modalias.attr, |
72 | NULL, | 128 | NULL, |
73 | }; | 129 | }; |
74 | ATTRIBUTE_GROUPS(spi_dev); | 130 | |
131 | static const struct attribute_group spi_dev_group = { | ||
132 | .attrs = spi_dev_attrs, | ||
133 | }; | ||
134 | |||
135 | static struct attribute *spi_device_statistics_attrs[] = { | ||
136 | &dev_attr_spi_device_messages.attr, | ||
137 | &dev_attr_spi_device_transfers.attr, | ||
138 | &dev_attr_spi_device_errors.attr, | ||
139 | &dev_attr_spi_device_timedout.attr, | ||
140 | &dev_attr_spi_device_spi_sync.attr, | ||
141 | &dev_attr_spi_device_spi_sync_immediate.attr, | ||
142 | &dev_attr_spi_device_spi_async.attr, | ||
143 | &dev_attr_spi_device_bytes.attr, | ||
144 | &dev_attr_spi_device_bytes_rx.attr, | ||
145 | &dev_attr_spi_device_bytes_tx.attr, | ||
146 | NULL, | ||
147 | }; | ||
148 | |||
149 | static const struct attribute_group spi_device_statistics_group = { | ||
150 | .name = "statistics", | ||
151 | .attrs = spi_device_statistics_attrs, | ||
152 | }; | ||
153 | |||
154 | static const struct attribute_group *spi_dev_groups[] = { | ||
155 | &spi_dev_group, | ||
156 | &spi_device_statistics_group, | ||
157 | NULL, | ||
158 | }; | ||
159 | |||
160 | static struct attribute *spi_master_statistics_attrs[] = { | ||
161 | &dev_attr_spi_master_messages.attr, | ||
162 | &dev_attr_spi_master_transfers.attr, | ||
163 | &dev_attr_spi_master_errors.attr, | ||
164 | &dev_attr_spi_master_timedout.attr, | ||
165 | &dev_attr_spi_master_spi_sync.attr, | ||
166 | &dev_attr_spi_master_spi_sync_immediate.attr, | ||
167 | &dev_attr_spi_master_spi_async.attr, | ||
168 | &dev_attr_spi_master_bytes.attr, | ||
169 | &dev_attr_spi_master_bytes_rx.attr, | ||
170 | &dev_attr_spi_master_bytes_tx.attr, | ||
171 | NULL, | ||
172 | }; | ||
173 | |||
174 | static const struct attribute_group spi_master_statistics_group = { | ||
175 | .name = "statistics", | ||
176 | .attrs = spi_master_statistics_attrs, | ||
177 | }; | ||
178 | |||
179 | static const struct attribute_group *spi_master_groups[] = { | ||
180 | &spi_master_statistics_group, | ||
181 | NULL, | ||
182 | }; | ||
183 | |||
184 | void spi_statistics_add_transfer_stats(struct spi_statistics *stats, | ||
185 | struct spi_transfer *xfer, | ||
186 | struct spi_master *master) | ||
187 | { | ||
188 | unsigned long flags; | ||
189 | |||
190 | spin_lock_irqsave(&stats->lock, flags); | ||
191 | |||
192 | stats->transfers++; | ||
193 | |||
194 | stats->bytes += xfer->len; | ||
195 | if ((xfer->tx_buf) && | ||
196 | (xfer->tx_buf != master->dummy_tx)) | ||
197 | stats->bytes_tx += xfer->len; | ||
198 | if ((xfer->rx_buf) && | ||
199 | (xfer->rx_buf != master->dummy_rx)) | ||
200 | stats->bytes_rx += xfer->len; | ||
201 | |||
202 | spin_unlock_irqrestore(&stats->lock, flags); | ||
203 | } | ||
204 | EXPORT_SYMBOL_GPL(spi_statistics_add_transfer_stats); | ||
75 | 205 | ||
76 | /* modalias support makes "modprobe $MODALIAS" new-style hotplug work, | 206 | /* modalias support makes "modprobe $MODALIAS" new-style hotplug work, |
77 | * and the sysfs version makes coldplug work too. | 207 | * and the sysfs version makes coldplug work too. |
@@ -249,6 +379,9 @@ struct spi_device *spi_alloc_device(struct spi_master *master) | |||
249 | spi->dev.bus = &spi_bus_type; | 379 | spi->dev.bus = &spi_bus_type; |
250 | spi->dev.release = spidev_release; | 380 | spi->dev.release = spidev_release; |
251 | spi->cs_gpio = -ENOENT; | 381 | spi->cs_gpio = -ENOENT; |
382 | |||
383 | spin_lock_init(&spi->statistics.lock); | ||
384 | |||
252 | device_initialize(&spi->dev); | 385 | device_initialize(&spi->dev); |
253 | return spi; | 386 | return spi; |
254 | } | 387 | } |
@@ -476,21 +609,30 @@ static int spi_map_buf(struct spi_master *master, struct device *dev, | |||
476 | enum dma_data_direction dir) | 609 | enum dma_data_direction dir) |
477 | { | 610 | { |
478 | const bool vmalloced_buf = is_vmalloc_addr(buf); | 611 | const bool vmalloced_buf = is_vmalloc_addr(buf); |
479 | const int desc_len = vmalloced_buf ? PAGE_SIZE : master->max_dma_len; | 612 | int desc_len; |
480 | const int sgs = DIV_ROUND_UP(len, desc_len); | 613 | int sgs; |
481 | struct page *vm_page; | 614 | struct page *vm_page; |
482 | void *sg_buf; | 615 | void *sg_buf; |
483 | size_t min; | 616 | size_t min; |
484 | int i, ret; | 617 | int i, ret; |
485 | 618 | ||
619 | if (vmalloced_buf) { | ||
620 | desc_len = PAGE_SIZE; | ||
621 | sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len); | ||
622 | } else { | ||
623 | desc_len = master->max_dma_len; | ||
624 | sgs = DIV_ROUND_UP(len, desc_len); | ||
625 | } | ||
626 | |||
486 | ret = sg_alloc_table(sgt, sgs, GFP_KERNEL); | 627 | ret = sg_alloc_table(sgt, sgs, GFP_KERNEL); |
487 | if (ret != 0) | 628 | if (ret != 0) |
488 | return ret; | 629 | return ret; |
489 | 630 | ||
490 | for (i = 0; i < sgs; i++) { | 631 | for (i = 0; i < sgs; i++) { |
491 | min = min_t(size_t, len, desc_len); | ||
492 | 632 | ||
493 | if (vmalloced_buf) { | 633 | if (vmalloced_buf) { |
634 | min = min_t(size_t, | ||
635 | len, desc_len - offset_in_page(buf)); | ||
494 | vm_page = vmalloc_to_page(buf); | 636 | vm_page = vmalloc_to_page(buf); |
495 | if (!vm_page) { | 637 | if (!vm_page) { |
496 | sg_free_table(sgt); | 638 | sg_free_table(sgt); |
@@ -499,6 +641,7 @@ static int spi_map_buf(struct spi_master *master, struct device *dev, | |||
499 | sg_set_page(&sgt->sgl[i], vm_page, | 641 | sg_set_page(&sgt->sgl[i], vm_page, |
500 | min, offset_in_page(buf)); | 642 | min, offset_in_page(buf)); |
501 | } else { | 643 | } else { |
644 | min = min_t(size_t, len, desc_len); | ||
502 | sg_buf = buf; | 645 | sg_buf = buf; |
503 | sg_set_buf(&sgt->sgl[i], sg_buf, min); | 646 | sg_set_buf(&sgt->sgl[i], sg_buf, min); |
504 | } | 647 | } |
@@ -539,8 +682,15 @@ static int __spi_map_msg(struct spi_master *master, struct spi_message *msg) | |||
539 | if (!master->can_dma) | 682 | if (!master->can_dma) |
540 | return 0; | 683 | return 0; |
541 | 684 | ||
542 | tx_dev = master->dma_tx->device->dev; | 685 | if (master->dma_tx) |
543 | rx_dev = master->dma_rx->device->dev; | 686 | tx_dev = master->dma_tx->device->dev; |
687 | else | ||
688 | tx_dev = &master->dev; | ||
689 | |||
690 | if (master->dma_rx) | ||
691 | rx_dev = master->dma_rx->device->dev; | ||
692 | else | ||
693 | rx_dev = &master->dev; | ||
544 | 694 | ||
545 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { | 695 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { |
546 | if (!master->can_dma(master, msg->spi, xfer)) | 696 | if (!master->can_dma(master, msg->spi, xfer)) |
@@ -579,8 +729,15 @@ static int __spi_unmap_msg(struct spi_master *master, struct spi_message *msg) | |||
579 | if (!master->cur_msg_mapped || !master->can_dma) | 729 | if (!master->cur_msg_mapped || !master->can_dma) |
580 | return 0; | 730 | return 0; |
581 | 731 | ||
582 | tx_dev = master->dma_tx->device->dev; | 732 | if (master->dma_tx) |
583 | rx_dev = master->dma_rx->device->dev; | 733 | tx_dev = master->dma_tx->device->dev; |
734 | else | ||
735 | tx_dev = &master->dev; | ||
736 | |||
737 | if (master->dma_rx) | ||
738 | rx_dev = master->dma_rx->device->dev; | ||
739 | else | ||
740 | rx_dev = &master->dev; | ||
584 | 741 | ||
585 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { | 742 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { |
586 | if (!master->can_dma(master, msg->spi, xfer)) | 743 | if (!master->can_dma(master, msg->spi, xfer)) |
@@ -689,17 +846,29 @@ static int spi_transfer_one_message(struct spi_master *master, | |||
689 | bool keep_cs = false; | 846 | bool keep_cs = false; |
690 | int ret = 0; | 847 | int ret = 0; |
691 | unsigned long ms = 1; | 848 | unsigned long ms = 1; |
849 | struct spi_statistics *statm = &master->statistics; | ||
850 | struct spi_statistics *stats = &msg->spi->statistics; | ||
692 | 851 | ||
693 | spi_set_cs(msg->spi, true); | 852 | spi_set_cs(msg->spi, true); |
694 | 853 | ||
854 | SPI_STATISTICS_INCREMENT_FIELD(statm, messages); | ||
855 | SPI_STATISTICS_INCREMENT_FIELD(stats, messages); | ||
856 | |||
695 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { | 857 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { |
696 | trace_spi_transfer_start(msg, xfer); | 858 | trace_spi_transfer_start(msg, xfer); |
697 | 859 | ||
860 | spi_statistics_add_transfer_stats(statm, xfer, master); | ||
861 | spi_statistics_add_transfer_stats(stats, xfer, master); | ||
862 | |||
698 | if (xfer->tx_buf || xfer->rx_buf) { | 863 | if (xfer->tx_buf || xfer->rx_buf) { |
699 | reinit_completion(&master->xfer_completion); | 864 | reinit_completion(&master->xfer_completion); |
700 | 865 | ||
701 | ret = master->transfer_one(master, msg->spi, xfer); | 866 | ret = master->transfer_one(master, msg->spi, xfer); |
702 | if (ret < 0) { | 867 | if (ret < 0) { |
868 | SPI_STATISTICS_INCREMENT_FIELD(statm, | ||
869 | errors); | ||
870 | SPI_STATISTICS_INCREMENT_FIELD(stats, | ||
871 | errors); | ||
703 | dev_err(&msg->spi->dev, | 872 | dev_err(&msg->spi->dev, |
704 | "SPI transfer failed: %d\n", ret); | 873 | "SPI transfer failed: %d\n", ret); |
705 | goto out; | 874 | goto out; |
@@ -715,6 +884,10 @@ static int spi_transfer_one_message(struct spi_master *master, | |||
715 | } | 884 | } |
716 | 885 | ||
717 | if (ms == 0) { | 886 | if (ms == 0) { |
887 | SPI_STATISTICS_INCREMENT_FIELD(statm, | ||
888 | timedout); | ||
889 | SPI_STATISTICS_INCREMENT_FIELD(stats, | ||
890 | timedout); | ||
718 | dev_err(&msg->spi->dev, | 891 | dev_err(&msg->spi->dev, |
719 | "SPI transfer timed out\n"); | 892 | "SPI transfer timed out\n"); |
720 | msg->status = -ETIMEDOUT; | 893 | msg->status = -ETIMEDOUT; |
@@ -1416,10 +1589,10 @@ static struct class spi_master_class = { | |||
1416 | .name = "spi_master", | 1589 | .name = "spi_master", |
1417 | .owner = THIS_MODULE, | 1590 | .owner = THIS_MODULE, |
1418 | .dev_release = spi_master_release, | 1591 | .dev_release = spi_master_release, |
1592 | .dev_groups = spi_master_groups, | ||
1419 | }; | 1593 | }; |
1420 | 1594 | ||
1421 | 1595 | ||
1422 | |||
1423 | /** | 1596 | /** |
1424 | * spi_alloc_master - allocate SPI master controller | 1597 | * spi_alloc_master - allocate SPI master controller |
1425 | * @dev: the controller, possibly using the platform_bus | 1598 | * @dev: the controller, possibly using the platform_bus |
@@ -1585,6 +1758,8 @@ int spi_register_master(struct spi_master *master) | |||
1585 | goto done; | 1758 | goto done; |
1586 | } | 1759 | } |
1587 | } | 1760 | } |
1761 | /* add statistics */ | ||
1762 | spin_lock_init(&master->statistics.lock); | ||
1588 | 1763 | ||
1589 | mutex_lock(&board_lock); | 1764 | mutex_lock(&board_lock); |
1590 | list_add_tail(&master->list, &spi_master_list); | 1765 | list_add_tail(&master->list, &spi_master_list); |
@@ -1740,6 +1915,20 @@ EXPORT_SYMBOL_GPL(spi_busnum_to_master); | |||
1740 | * other core methods are currently defined as inline functions. | 1915 | * other core methods are currently defined as inline functions. |
1741 | */ | 1916 | */ |
1742 | 1917 | ||
1918 | static int __spi_validate_bits_per_word(struct spi_master *master, u8 bits_per_word) | ||
1919 | { | ||
1920 | if (master->bits_per_word_mask) { | ||
1921 | /* Only 32 bits fit in the mask */ | ||
1922 | if (bits_per_word > 32) | ||
1923 | return -EINVAL; | ||
1924 | if (!(master->bits_per_word_mask & | ||
1925 | SPI_BPW_MASK(bits_per_word))) | ||
1926 | return -EINVAL; | ||
1927 | } | ||
1928 | |||
1929 | return 0; | ||
1930 | } | ||
1931 | |||
1743 | /** | 1932 | /** |
1744 | * spi_setup - setup SPI mode and clock rate | 1933 | * spi_setup - setup SPI mode and clock rate |
1745 | * @spi: the device whose settings are being modified | 1934 | * @spi: the device whose settings are being modified |
@@ -1798,6 +1987,9 @@ int spi_setup(struct spi_device *spi) | |||
1798 | if (!spi->bits_per_word) | 1987 | if (!spi->bits_per_word) |
1799 | spi->bits_per_word = 8; | 1988 | spi->bits_per_word = 8; |
1800 | 1989 | ||
1990 | if (__spi_validate_bits_per_word(spi->master, spi->bits_per_word)) | ||
1991 | return -EINVAL; | ||
1992 | |||
1801 | if (!spi->max_speed_hz) | 1993 | if (!spi->max_speed_hz) |
1802 | spi->max_speed_hz = spi->master->max_speed_hz; | 1994 | spi->max_speed_hz = spi->master->max_speed_hz; |
1803 | 1995 | ||
@@ -1860,19 +2052,15 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) | |||
1860 | 2052 | ||
1861 | if (!xfer->speed_hz) | 2053 | if (!xfer->speed_hz) |
1862 | xfer->speed_hz = spi->max_speed_hz; | 2054 | xfer->speed_hz = spi->max_speed_hz; |
2055 | if (!xfer->speed_hz) | ||
2056 | xfer->speed_hz = master->max_speed_hz; | ||
1863 | 2057 | ||
1864 | if (master->max_speed_hz && | 2058 | if (master->max_speed_hz && |
1865 | xfer->speed_hz > master->max_speed_hz) | 2059 | xfer->speed_hz > master->max_speed_hz) |
1866 | xfer->speed_hz = master->max_speed_hz; | 2060 | xfer->speed_hz = master->max_speed_hz; |
1867 | 2061 | ||
1868 | if (master->bits_per_word_mask) { | 2062 | if (__spi_validate_bits_per_word(master, xfer->bits_per_word)) |
1869 | /* Only 32 bits fit in the mask */ | 2063 | return -EINVAL; |
1870 | if (xfer->bits_per_word > 32) | ||
1871 | return -EINVAL; | ||
1872 | if (!(master->bits_per_word_mask & | ||
1873 | BIT(xfer->bits_per_word - 1))) | ||
1874 | return -EINVAL; | ||
1875 | } | ||
1876 | 2064 | ||
1877 | /* | 2065 | /* |
1878 | * SPI transfer length should be multiple of SPI word size | 2066 | * SPI transfer length should be multiple of SPI word size |
@@ -1939,6 +2127,9 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) | |||
1939 | 2127 | ||
1940 | message->spi = spi; | 2128 | message->spi = spi; |
1941 | 2129 | ||
2130 | SPI_STATISTICS_INCREMENT_FIELD(&master->statistics, spi_async); | ||
2131 | SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics, spi_async); | ||
2132 | |||
1942 | trace_spi_message_submit(message); | 2133 | trace_spi_message_submit(message); |
1943 | 2134 | ||
1944 | return master->transfer(spi, message); | 2135 | return master->transfer(spi, message); |
@@ -2075,6 +2266,9 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message, | |||
2075 | message->context = &done; | 2266 | message->context = &done; |
2076 | message->spi = spi; | 2267 | message->spi = spi; |
2077 | 2268 | ||
2269 | SPI_STATISTICS_INCREMENT_FIELD(&master->statistics, spi_sync); | ||
2270 | SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics, spi_sync); | ||
2271 | |||
2078 | if (!bus_locked) | 2272 | if (!bus_locked) |
2079 | mutex_lock(&master->bus_lock_mutex); | 2273 | mutex_lock(&master->bus_lock_mutex); |
2080 | 2274 | ||
@@ -2102,8 +2296,13 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message, | |||
2102 | /* Push out the messages in the calling context if we | 2296 | /* Push out the messages in the calling context if we |
2103 | * can. | 2297 | * can. |
2104 | */ | 2298 | */ |
2105 | if (master->transfer == spi_queued_transfer) | 2299 | if (master->transfer == spi_queued_transfer) { |
2300 | SPI_STATISTICS_INCREMENT_FIELD(&master->statistics, | ||
2301 | spi_sync_immediate); | ||
2302 | SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics, | ||
2303 | spi_sync_immediate); | ||
2106 | __spi_pump_messages(master, false); | 2304 | __spi_pump_messages(master, false); |
2305 | } | ||
2107 | 2306 | ||
2108 | wait_for_completion(&done); | 2307 | wait_for_completion(&done); |
2109 | status = message->status; | 2308 | status = message->status; |