aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/function/f_fs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/function/f_fs.c')
-rw-r--r--drivers/usb/gadget/function/f_fs.c107
1 files changed, 92 insertions, 15 deletions
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 54ad100af35b..e40d47d47d82 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -136,8 +136,60 @@ struct ffs_epfile {
136 /* 136 /*
137 * Buffer for holding data from partial reads which may happen since 137 * Buffer for holding data from partial reads which may happen since
138 * we’re rounding user read requests to a multiple of a max packet size. 138 * we’re rounding user read requests to a multiple of a max packet size.
139 *
140 * The pointer is initialised with NULL value and may be set by
141 * __ffs_epfile_read_data function to point to a temporary buffer.
142 *
143 * In normal operation, calls to __ffs_epfile_read_buffered will consume
144 * data from said buffer and eventually free it. Importantly, while the
145 * function is using the buffer, it sets the pointer to NULL. This is
146 * all right since __ffs_epfile_read_data and __ffs_epfile_read_buffered
147 * can never run concurrently (they are synchronised by epfile->mutex)
148 * so the latter will not assign a new value to the pointer.
149 *
150 * Meanwhile ffs_func_eps_disable frees the buffer (if the pointer is
151 * valid) and sets the pointer to READ_BUFFER_DROP value. This special
152 * value is crux of the synchronisation between ffs_func_eps_disable and
153 * __ffs_epfile_read_data.
154 *
155 * Once __ffs_epfile_read_data is about to finish it will try to set the
156 * pointer back to its old value (as described above), but seeing as the
157 * pointer is not-NULL (namely READ_BUFFER_DROP) it will instead free
158 * the buffer.
159 *
160 * == State transitions ==
161 *
162 * • ptr == NULL: (initial state)
163 * ◦ __ffs_epfile_read_buffer_free: go to ptr == DROP
164 * ◦ __ffs_epfile_read_buffered: nop
165 * ◦ __ffs_epfile_read_data allocates temp buffer: go to ptr == buf
166 * ◦ reading finishes: n/a, not in ‘and reading’ state
167 * • ptr == DROP:
168 * ◦ __ffs_epfile_read_buffer_free: nop
169 * ◦ __ffs_epfile_read_buffered: go to ptr == NULL
170 * ◦ __ffs_epfile_read_data allocates temp buffer: free buf, nop
171 * ◦ reading finishes: n/a, not in ‘and reading’ state
172 * • ptr == buf:
173 * ◦ __ffs_epfile_read_buffer_free: free buf, go to ptr == DROP
174 * ◦ __ffs_epfile_read_buffered: go to ptr == NULL and reading
175 * ◦ __ffs_epfile_read_data: n/a, __ffs_epfile_read_buffered
176 * is always called first
177 * ◦ reading finishes: n/a, not in ‘and reading’ state
178 * • ptr == NULL and reading:
179 * ◦ __ffs_epfile_read_buffer_free: go to ptr == DROP and reading
180 * ◦ __ffs_epfile_read_buffered: n/a, mutex is held
181 * ◦ __ffs_epfile_read_data: n/a, mutex is held
182 * ◦ reading finishes and …
183 * … all data read: free buf, go to ptr == NULL
184 * … otherwise: go to ptr == buf and reading
185 * • ptr == DROP and reading:
186 * ◦ __ffs_epfile_read_buffer_free: nop
187 * ◦ __ffs_epfile_read_buffered: n/a, mutex is held
188 * ◦ __ffs_epfile_read_data: n/a, mutex is held
189 * ◦ reading finishes: free buf, go to ptr == DROP
139 */ 190 */
140 struct ffs_buffer *read_buffer; /* P: epfile->mutex */ 191 struct ffs_buffer *read_buffer;
192#define READ_BUFFER_DROP ((struct ffs_buffer *)ERR_PTR(-ESHUTDOWN))
141 193
142 char name[5]; 194 char name[5];
143 195
@@ -736,25 +788,47 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
736 schedule_work(&io_data->work); 788 schedule_work(&io_data->work);
737} 789}
738 790
791static void __ffs_epfile_read_buffer_free(struct ffs_epfile *epfile)
792{
793 /*
794 * See comment in struct ffs_epfile for full read_buffer pointer
795 * synchronisation story.
796 */
797 struct ffs_buffer *buf = xchg(&epfile->read_buffer, READ_BUFFER_DROP);
798 if (buf && buf != READ_BUFFER_DROP)
799 kfree(buf);
800}
801
739/* Assumes epfile->mutex is held. */ 802/* Assumes epfile->mutex is held. */
740static ssize_t __ffs_epfile_read_buffered(struct ffs_epfile *epfile, 803static ssize_t __ffs_epfile_read_buffered(struct ffs_epfile *epfile,
741 struct iov_iter *iter) 804 struct iov_iter *iter)
742{ 805{
743 struct ffs_buffer *buf = epfile->read_buffer; 806 /*
807 * Null out epfile->read_buffer so ffs_func_eps_disable does not free
808 * the buffer while we are using it. See comment in struct ffs_epfile
809 * for full read_buffer pointer synchronisation story.
810 */
811 struct ffs_buffer *buf = xchg(&epfile->read_buffer, NULL);
744 ssize_t ret; 812 ssize_t ret;
745 if (!buf) 813 if (!buf || buf == READ_BUFFER_DROP)
746 return 0; 814 return 0;
747 815
748 ret = copy_to_iter(buf->data, buf->length, iter); 816 ret = copy_to_iter(buf->data, buf->length, iter);
749 if (buf->length == ret) { 817 if (buf->length == ret) {
750 kfree(buf); 818 kfree(buf);
751 epfile->read_buffer = NULL; 819 return ret;
752 } else if (unlikely(iov_iter_count(iter))) { 820 }
821
822 if (unlikely(iov_iter_count(iter))) {
753 ret = -EFAULT; 823 ret = -EFAULT;
754 } else { 824 } else {
755 buf->length -= ret; 825 buf->length -= ret;
756 buf->data += ret; 826 buf->data += ret;
757 } 827 }
828
829 if (cmpxchg(&epfile->read_buffer, NULL, buf))
830 kfree(buf);
831
758 return ret; 832 return ret;
759} 833}
760 834
@@ -783,7 +857,15 @@ static ssize_t __ffs_epfile_read_data(struct ffs_epfile *epfile,
783 buf->length = data_len; 857 buf->length = data_len;
784 buf->data = buf->storage; 858 buf->data = buf->storage;
785 memcpy(buf->storage, data + ret, data_len); 859 memcpy(buf->storage, data + ret, data_len);
786 epfile->read_buffer = buf; 860
861 /*
862 * At this point read_buffer is NULL or READ_BUFFER_DROP (if
863 * ffs_func_eps_disable has been called in the meanwhile). See comment
864 * in struct ffs_epfile for full read_buffer pointer synchronisation
865 * story.
866 */
867 if (unlikely(cmpxchg(&epfile->read_buffer, NULL, buf)))
868 kfree(buf);
787 869
788 return ret; 870 return ret;
789} 871}
@@ -1097,8 +1179,7 @@ ffs_epfile_release(struct inode *inode, struct file *file)
1097 1179
1098 ENTER(); 1180 ENTER();
1099 1181
1100 kfree(epfile->read_buffer); 1182 __ffs_epfile_read_buffer_free(epfile);
1101 epfile->read_buffer = NULL;
1102 ffs_data_closed(epfile->ffs); 1183 ffs_data_closed(epfile->ffs);
1103 1184
1104 return 0; 1185 return 0;
@@ -1724,24 +1805,20 @@ static void ffs_func_eps_disable(struct ffs_function *func)
1724 unsigned count = func->ffs->eps_count; 1805 unsigned count = func->ffs->eps_count;
1725 unsigned long flags; 1806 unsigned long flags;
1726 1807
1808 spin_lock_irqsave(&func->ffs->eps_lock, flags);
1727 do { 1809 do {
1728 if (epfile)
1729 mutex_lock(&epfile->mutex);
1730 spin_lock_irqsave(&func->ffs->eps_lock, flags);
1731 /* pending requests get nuked */ 1810 /* pending requests get nuked */
1732 if (likely(ep->ep)) 1811 if (likely(ep->ep))
1733 usb_ep_disable(ep->ep); 1812 usb_ep_disable(ep->ep);
1734 ++ep; 1813 ++ep;
1735 spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
1736 1814
1737 if (epfile) { 1815 if (epfile) {
1738 epfile->ep = NULL; 1816 epfile->ep = NULL;
1739 kfree(epfile->read_buffer); 1817 __ffs_epfile_read_buffer_free(epfile);
1740 epfile->read_buffer = NULL;
1741 mutex_unlock(&epfile->mutex);
1742 ++epfile; 1818 ++epfile;
1743 } 1819 }
1744 } while (--count); 1820 } while (--count);
1821 spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
1745} 1822}
1746 1823
1747static int ffs_func_eps_enable(struct ffs_function *func) 1824static int ffs_func_eps_enable(struct ffs_function *func)