diff options
Diffstat (limited to 'kernel/kfifo.c')
-rw-r--r-- | kernel/kfifo.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/kernel/kfifo.c b/kernel/kfifo.c index 64ab045c3d9d..5d1d907378a2 100644 --- a/kernel/kfifo.c +++ b/kernel/kfifo.c | |||
@@ -122,6 +122,13 @@ unsigned int __kfifo_put(struct kfifo *fifo, | |||
122 | 122 | ||
123 | len = min(len, fifo->size - fifo->in + fifo->out); | 123 | len = min(len, fifo->size - fifo->in + fifo->out); |
124 | 124 | ||
125 | /* | ||
126 | * Ensure that we sample the fifo->out index -before- we | ||
127 | * start putting bytes into the kfifo. | ||
128 | */ | ||
129 | |||
130 | smp_mb(); | ||
131 | |||
125 | /* first put the data starting from fifo->in to buffer end */ | 132 | /* first put the data starting from fifo->in to buffer end */ |
126 | l = min(len, fifo->size - (fifo->in & (fifo->size - 1))); | 133 | l = min(len, fifo->size - (fifo->in & (fifo->size - 1))); |
127 | memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l); | 134 | memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l); |
@@ -129,6 +136,13 @@ unsigned int __kfifo_put(struct kfifo *fifo, | |||
129 | /* then put the rest (if any) at the beginning of the buffer */ | 136 | /* then put the rest (if any) at the beginning of the buffer */ |
130 | memcpy(fifo->buffer, buffer + l, len - l); | 137 | memcpy(fifo->buffer, buffer + l, len - l); |
131 | 138 | ||
139 | /* | ||
140 | * Ensure that we add the bytes to the kfifo -before- | ||
141 | * we update the fifo->in index. | ||
142 | */ | ||
143 | |||
144 | smp_wmb(); | ||
145 | |||
132 | fifo->in += len; | 146 | fifo->in += len; |
133 | 147 | ||
134 | return len; | 148 | return len; |
@@ -154,6 +168,13 @@ unsigned int __kfifo_get(struct kfifo *fifo, | |||
154 | 168 | ||
155 | len = min(len, fifo->in - fifo->out); | 169 | len = min(len, fifo->in - fifo->out); |
156 | 170 | ||
171 | /* | ||
172 | * Ensure that we sample the fifo->in index -before- we | ||
173 | * start removing bytes from the kfifo. | ||
174 | */ | ||
175 | |||
176 | smp_rmb(); | ||
177 | |||
157 | /* first get the data from fifo->out until the end of the buffer */ | 178 | /* first get the data from fifo->out until the end of the buffer */ |
158 | l = min(len, fifo->size - (fifo->out & (fifo->size - 1))); | 179 | l = min(len, fifo->size - (fifo->out & (fifo->size - 1))); |
159 | memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l); | 180 | memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l); |
@@ -161,6 +182,13 @@ unsigned int __kfifo_get(struct kfifo *fifo, | |||
161 | /* then get the rest (if any) from the beginning of the buffer */ | 182 | /* then get the rest (if any) from the beginning of the buffer */ |
162 | memcpy(buffer + l, fifo->buffer, len - l); | 183 | memcpy(buffer + l, fifo->buffer, len - l); |
163 | 184 | ||
185 | /* | ||
186 | * Ensure that we remove the bytes from the kfifo -before- | ||
187 | * we update the fifo->out index. | ||
188 | */ | ||
189 | |||
190 | smp_mb(); | ||
191 | |||
164 | fifo->out += len; | 192 | fifo->out += len; |
165 | 193 | ||
166 | return len; | 194 | return len; |