diff options
Diffstat (limited to 'include/linux/spi')
-rw-r--r-- | include/linux/spi/spi.h | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 06ea1c3a04d7..f54667b7b3c8 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h | |||
@@ -54,6 +54,10 @@ extern struct bus_type spi_bus_type; | |||
54 | * | 54 | * |
55 | * @transfer_bytes_histo: | 55 | * @transfer_bytes_histo: |
56 | * transfer bytes histogramm | 56 | * transfer bytes histogramm |
57 | * | ||
58 | * @transfers_split_maxsize: | ||
59 | * number of transfers that have been split because of | ||
60 | * maxsize limit | ||
57 | */ | 61 | */ |
58 | struct spi_statistics { | 62 | struct spi_statistics { |
59 | spinlock_t lock; /* lock for the whole structure */ | 63 | spinlock_t lock; /* lock for the whole structure */ |
@@ -73,6 +77,8 @@ struct spi_statistics { | |||
73 | 77 | ||
74 | #define SPI_STATISTICS_HISTO_SIZE 17 | 78 | #define SPI_STATISTICS_HISTO_SIZE 17 |
75 | unsigned long transfer_bytes_histo[SPI_STATISTICS_HISTO_SIZE]; | 79 | unsigned long transfer_bytes_histo[SPI_STATISTICS_HISTO_SIZE]; |
80 | |||
81 | unsigned long transfers_split_maxsize; | ||
76 | }; | 82 | }; |
77 | 83 | ||
78 | void spi_statistics_add_transfer_stats(struct spi_statistics *stats, | 84 | void spi_statistics_add_transfer_stats(struct spi_statistics *stats, |
@@ -594,6 +600,37 @@ extern void spi_unregister_master(struct spi_master *master); | |||
594 | 600 | ||
595 | extern struct spi_master *spi_busnum_to_master(u16 busnum); | 601 | extern struct spi_master *spi_busnum_to_master(u16 busnum); |
596 | 602 | ||
603 | /* | ||
604 | * SPI resource management while processing a SPI message | ||
605 | */ | ||
606 | |||
607 | /** | ||
608 | * struct spi_res - spi resource management structure | ||
609 | * @entry: list entry | ||
610 | * @release: release code called prior to freeing this resource | ||
611 | * @data: extra data allocated for the specific use-case | ||
612 | * | ||
613 | * this is based on ideas from devres, but focused on life-cycle | ||
614 | * management during spi_message processing | ||
615 | */ | ||
616 | typedef void (*spi_res_release_t)(struct spi_master *master, | ||
617 | struct spi_message *msg, | ||
618 | void *res); | ||
619 | struct spi_res { | ||
620 | struct list_head entry; | ||
621 | spi_res_release_t release; | ||
622 | unsigned long long data[]; /* guarantee ull alignment */ | ||
623 | }; | ||
624 | |||
625 | extern void *spi_res_alloc(struct spi_device *spi, | ||
626 | spi_res_release_t release, | ||
627 | size_t size, gfp_t gfp); | ||
628 | extern void spi_res_add(struct spi_message *message, void *res); | ||
629 | extern void spi_res_free(void *res); | ||
630 | |||
631 | extern void spi_res_release(struct spi_master *master, | ||
632 | struct spi_message *message); | ||
633 | |||
597 | /*---------------------------------------------------------------------------*/ | 634 | /*---------------------------------------------------------------------------*/ |
598 | 635 | ||
599 | /* | 636 | /* |
@@ -732,6 +769,7 @@ struct spi_transfer { | |||
732 | * @status: zero for success, else negative errno | 769 | * @status: zero for success, else negative errno |
733 | * @queue: for use by whichever driver currently owns the message | 770 | * @queue: for use by whichever driver currently owns the message |
734 | * @state: for use by whichever driver currently owns the message | 771 | * @state: for use by whichever driver currently owns the message |
772 | * @resources: for resource management when the spi message is processed | ||
735 | * | 773 | * |
736 | * A @spi_message is used to execute an atomic sequence of data transfers, | 774 | * A @spi_message is used to execute an atomic sequence of data transfers, |
737 | * each represented by a struct spi_transfer. The sequence is "atomic" | 775 | * each represented by a struct spi_transfer. The sequence is "atomic" |
@@ -778,11 +816,15 @@ struct spi_message { | |||
778 | */ | 816 | */ |
779 | struct list_head queue; | 817 | struct list_head queue; |
780 | void *state; | 818 | void *state; |
819 | |||
820 | /* list of spi_res reources when the spi message is processed */ | ||
821 | struct list_head resources; | ||
781 | }; | 822 | }; |
782 | 823 | ||
783 | static inline void spi_message_init_no_memset(struct spi_message *m) | 824 | static inline void spi_message_init_no_memset(struct spi_message *m) |
784 | { | 825 | { |
785 | INIT_LIST_HEAD(&m->transfers); | 826 | INIT_LIST_HEAD(&m->transfers); |
827 | INIT_LIST_HEAD(&m->resources); | ||
786 | } | 828 | } |
787 | 829 | ||
788 | static inline void spi_message_init(struct spi_message *m) | 830 | static inline void spi_message_init(struct spi_message *m) |
@@ -866,6 +908,60 @@ spi_max_transfer_size(struct spi_device *spi) | |||
866 | 908 | ||
867 | /*---------------------------------------------------------------------------*/ | 909 | /*---------------------------------------------------------------------------*/ |
868 | 910 | ||
911 | /* SPI transfer replacement methods which make use of spi_res */ | ||
912 | |||
913 | struct spi_replaced_transfers; | ||
914 | typedef void (*spi_replaced_release_t)(struct spi_master *master, | ||
915 | struct spi_message *msg, | ||
916 | struct spi_replaced_transfers *res); | ||
917 | /** | ||
918 | * struct spi_replaced_transfers - structure describing the spi_transfer | ||
919 | * replacements that have occurred | ||
920 | * so that they can get reverted | ||
921 | * @release: some extra release code to get executed prior to | ||
922 | * relasing this structure | ||
923 | * @extradata: pointer to some extra data if requested or NULL | ||
924 | * @replaced_transfers: transfers that have been replaced and which need | ||
925 | * to get restored | ||
926 | * @replaced_after: the transfer after which the @replaced_transfers | ||
927 | * are to get re-inserted | ||
928 | * @inserted: number of transfers inserted | ||
929 | * @inserted_transfers: array of spi_transfers of array-size @inserted, | ||
930 | * that have been replacing replaced_transfers | ||
931 | * | ||
932 | * note: that @extradata will point to @inserted_transfers[@inserted] | ||
933 | * if some extra allocation is requested, so alignment will be the same | ||
934 | * as for spi_transfers | ||
935 | */ | ||
936 | struct spi_replaced_transfers { | ||
937 | spi_replaced_release_t release; | ||
938 | void *extradata; | ||
939 | struct list_head replaced_transfers; | ||
940 | struct list_head *replaced_after; | ||
941 | size_t inserted; | ||
942 | struct spi_transfer inserted_transfers[]; | ||
943 | }; | ||
944 | |||
945 | extern struct spi_replaced_transfers *spi_replace_transfers( | ||
946 | struct spi_message *msg, | ||
947 | struct spi_transfer *xfer_first, | ||
948 | size_t remove, | ||
949 | size_t insert, | ||
950 | spi_replaced_release_t release, | ||
951 | size_t extradatasize, | ||
952 | gfp_t gfp); | ||
953 | |||
954 | /*---------------------------------------------------------------------------*/ | ||
955 | |||
956 | /* SPI transfer transformation methods */ | ||
957 | |||
958 | extern int spi_split_transfers_maxsize(struct spi_master *master, | ||
959 | struct spi_message *msg, | ||
960 | size_t maxsize, | ||
961 | gfp_t gfp); | ||
962 | |||
963 | /*---------------------------------------------------------------------------*/ | ||
964 | |||
869 | /* All these synchronous SPI transfer routines are utilities layered | 965 | /* All these synchronous SPI transfer routines are utilities layered |
870 | * over the core async transfer primitive. Here, "synchronous" means | 966 | * over the core async transfer primitive. Here, "synchronous" means |
871 | * they will sleep uninterruptibly until the async transfer completes. | 967 | * they will sleep uninterruptibly until the async transfer completes. |