Merge git://oss.sgi.com:8090/xfs/xfs-2.6
[linux-drm-fsl-dcu.git] / kernel / kfifo.c
index 64ab045c3d9d3a72126971f51c0081e199a4468d..cee419143fd47bb410b0cf80e7762a0f02ffbfce 100644 (file)
@@ -32,8 +32,8 @@
  * @gfp_mask: get_free_pages mask, passed to kmalloc()
  * @lock: the lock to be used to protect the fifo buffer
  *
- * Do NOT pass the kfifo to kfifo_free() after use ! Simply free the
- * struct kfifo with kfree().
+ * Do NOT pass the kfifo to kfifo_free() after use! Simply free the
+ * &struct kfifo with kfree().
  */
 struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size,
                         gfp_t gfp_mask, spinlock_t *lock)
@@ -108,7 +108,7 @@ EXPORT_SYMBOL(kfifo_free);
  * @buffer: the data to be added.
  * @len: the length of the data to be added.
  *
- * This function copies at most 'len' bytes from the 'buffer' into
+ * This function copies at most @len bytes from the @buffer into
  * the FIFO depending on the free space, and returns the number of
  * bytes copied.
  *
@@ -122,6 +122,13 @@ unsigned int __kfifo_put(struct kfifo *fifo,
 
        len = min(len, fifo->size - fifo->in + fifo->out);
 
+       /*
+        * Ensure that we sample the fifo->out index -before- we
+        * start putting bytes into the kfifo.
+        */
+
+       smp_mb();
+
        /* first put the data starting from fifo->in to buffer end */
        l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));
        memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);
@@ -129,6 +136,13 @@ unsigned int __kfifo_put(struct kfifo *fifo,
        /* then put the rest (if any) at the beginning of the buffer */
        memcpy(fifo->buffer, buffer + l, len - l);
 
+       /*
+        * Ensure that we add the bytes to the kfifo -before-
+        * we update the fifo->in index.
+        */
+
+       smp_wmb();
+
        fifo->in += len;
 
        return len;
@@ -141,8 +155,8 @@ EXPORT_SYMBOL(__kfifo_put);
  * @buffer: where the data must be copied.
  * @len: the size of the destination buffer.
  *
- * This function copies at most 'len' bytes from the FIFO into the
- * 'buffer' and returns the number of copied bytes.
+ * This function copies at most @len bytes from the FIFO into the
+ * @buffer and returns the number of copied bytes.
  *
  * Note that with only one concurrent reader and one concurrent
  * writer, you don't need extra locking to use these functions.
@@ -154,6 +168,13 @@ unsigned int __kfifo_get(struct kfifo *fifo,
 
        len = min(len, fifo->in - fifo->out);
 
+       /*
+        * Ensure that we sample the fifo->in index -before- we
+        * start removing bytes from the kfifo.
+        */
+
+       smp_rmb();
+
        /* first get the data from fifo->out until the end of the buffer */
        l = min(len, fifo->size - (fifo->out & (fifo->size - 1)));
        memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l);
@@ -161,6 +182,13 @@ unsigned int __kfifo_get(struct kfifo *fifo,
        /* then get the rest (if any) from the beginning of the buffer */
        memcpy(buffer + l, fifo->buffer, len - l);
 
+       /*
+        * Ensure that we remove the bytes from the kfifo -before-
+        * we update the fifo->out index.
+        */
+
+       smp_mb();
+
        fifo->out += len;
 
        return len;