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; |
