diff options
Diffstat (limited to 'drivers/misc/mic/scif/scif_rb.c')
-rw-r--r-- | drivers/misc/mic/scif/scif_rb.c | 240 |
1 files changed, 0 insertions, 240 deletions
diff --git a/drivers/misc/mic/scif/scif_rb.c b/drivers/misc/mic/scif/scif_rb.c deleted file mode 100644 index e425882ae06d..000000000000 --- a/drivers/misc/mic/scif/scif_rb.c +++ /dev/null @@ -1,240 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Intel MIC Platform Software Stack (MPSS) - * - * Copyright(c) 2014 Intel Corporation. - * - * Intel SCIF driver. - */ -#include <linux/circ_buf.h> -#include <linux/types.h> -#include <linux/io.h> -#include <linux/errno.h> - -#include "scif_rb.h" - -#define scif_rb_ring_cnt(head, tail, size) CIRC_CNT(head, tail, size) -#define scif_rb_ring_space(head, tail, size) CIRC_SPACE(head, tail, size) - -/** - * scif_rb_init - Initializes the ring buffer - * @rb: ring buffer - * @read_ptr: A pointer to the read offset - * @write_ptr: A pointer to the write offset - * @rb_base: A pointer to the base of the ring buffer - * @size: The size of the ring buffer in powers of two - */ -void scif_rb_init(struct scif_rb *rb, u32 *read_ptr, u32 *write_ptr, - void *rb_base, u8 size) -{ - rb->rb_base = rb_base; - rb->size = (1 << size); - rb->read_ptr = read_ptr; - rb->write_ptr = write_ptr; - rb->current_read_offset = *read_ptr; - rb->current_write_offset = *write_ptr; -} - -/* Copies a message to the ring buffer -- handles the wrap around case */ -static void memcpy_torb(struct scif_rb *rb, void *header, - void *msg, u32 size) -{ - u32 size1, size2; - - if (header + size >= rb->rb_base + rb->size) { - /* Need to call two copies if it wraps around */ - size1 = (u32)(rb->rb_base + rb->size - header); - size2 = size - size1; - memcpy_toio((void __iomem __force *)header, msg, size1); - memcpy_toio((void __iomem __force *)rb->rb_base, - msg + size1, size2); - } else { - memcpy_toio((void __iomem __force *)header, msg, size); - } -} - -/* Copies a message from the ring buffer -- handles the wrap around case */ -static void memcpy_fromrb(struct scif_rb *rb, void *header, - void *msg, u32 size) -{ - u32 size1, size2; - - if (header + size >= rb->rb_base + rb->size) { - /* Need to call two copies if it wraps around */ - size1 = (u32)(rb->rb_base + rb->size - header); - size2 = size - size1; - memcpy_fromio(msg, (void __iomem __force *)header, size1); - memcpy_fromio(msg + size1, - (void __iomem __force *)rb->rb_base, size2); - } else { - memcpy_fromio(msg, (void __iomem __force *)header, size); - } -} - -/** - * scif_rb_space - Query space available for writing to the RB - * @rb: ring buffer - * - * Return: size available for writing to RB in bytes. - */ -u32 scif_rb_space(struct scif_rb *rb) -{ - rb->current_read_offset = *rb->read_ptr; - /* - * Update from the HW read pointer only once the peer has exposed the - * new empty slot. This barrier is paired with the memory barrier - * scif_rb_update_read_ptr() - */ - mb(); - return scif_rb_ring_space(rb->current_write_offset, - rb->current_read_offset, rb->size); -} - -/** - * scif_rb_write - Write a message to the RB - * @rb: ring buffer - * @msg: buffer to send the message. Must be at least size bytes long - * @size: the size (in bytes) to be copied to the RB - * - * This API does not block if there isn't enough space in the RB. - * Returns: 0 on success or -ENOMEM on failure - */ -int scif_rb_write(struct scif_rb *rb, void *msg, u32 size) -{ - void *header; - - if (scif_rb_space(rb) < size) - return -ENOMEM; - header = rb->rb_base + rb->current_write_offset; - memcpy_torb(rb, header, msg, size); - /* - * Wait until scif_rb_commit(). Update the local ring - * buffer data, not the shared data until commit. - */ - rb->current_write_offset = - (rb->current_write_offset + size) & (rb->size - 1); - return 0; -} - -/** - * scif_rb_commit - To submit the message to let the peer fetch it - * @rb: ring buffer - */ -void scif_rb_commit(struct scif_rb *rb) -{ - /* - * We must ensure ordering between the all the data committed - * previously before we expose the new message to the peer by - * updating the write_ptr. This write barrier is paired with - * the read barrier in scif_rb_count(..) - */ - wmb(); - WRITE_ONCE(*rb->write_ptr, rb->current_write_offset); -#ifdef CONFIG_INTEL_MIC_CARD - /* - * X100 Si bug: For the case where a Core is performing an EXT_WR - * followed by a Doorbell Write, the Core must perform two EXT_WR to the - * same address with the same data before it does the Doorbell Write. - * This way, if ordering is violated for the Interrupt Message, it will - * fall just behind the first Posted associated with the first EXT_WR. - */ - WRITE_ONCE(*rb->write_ptr, rb->current_write_offset); -#endif -} - -/** - * scif_rb_get - To get next message from the ring buffer - * @rb: ring buffer - * @size: Number of bytes to be read - * - * Return: NULL if no bytes to be read from the ring buffer, otherwise the - * pointer to the next byte - */ -static void *scif_rb_get(struct scif_rb *rb, u32 size) -{ - void *header = NULL; - - if (scif_rb_count(rb, size) >= size) - header = rb->rb_base + rb->current_read_offset; - return header; -} - -/* - * scif_rb_get_next - Read from ring buffer. - * @rb: ring buffer - * @msg: buffer to hold the message. Must be at least size bytes long - * @size: Number of bytes to be read - * - * Return: number of bytes read if available bytes are >= size, otherwise - * returns zero. - */ -u32 scif_rb_get_next(struct scif_rb *rb, void *msg, u32 size) -{ - void *header = NULL; - int read_size = 0; - - header = scif_rb_get(rb, size); - if (header) { - u32 next_cmd_offset = - (rb->current_read_offset + size) & (rb->size - 1); - - read_size = size; - rb->current_read_offset = next_cmd_offset; - memcpy_fromrb(rb, header, msg, size); - } - return read_size; -} - -/** - * scif_rb_update_read_ptr - * @rb: ring buffer - */ -void scif_rb_update_read_ptr(struct scif_rb *rb) -{ - u32 new_offset; - - new_offset = rb->current_read_offset; - /* - * We must ensure ordering between the all the data committed or read - * previously before we expose the empty slot to the peer by updating - * the read_ptr. This barrier is paired with the memory barrier in - * scif_rb_space(..) - */ - mb(); - WRITE_ONCE(*rb->read_ptr, new_offset); -#ifdef CONFIG_INTEL_MIC_CARD - /* - * X100 Si Bug: For the case where a Core is performing an EXT_WR - * followed by a Doorbell Write, the Core must perform two EXT_WR to the - * same address with the same data before it does the Doorbell Write. - * This way, if ordering is violated for the Interrupt Message, it will - * fall just behind the first Posted associated with the first EXT_WR. - */ - WRITE_ONCE(*rb->read_ptr, new_offset); -#endif -} - -/** - * scif_rb_count - * @rb: ring buffer - * @size: Number of bytes expected to be read - * - * Return: number of bytes that can be read from the RB - */ -u32 scif_rb_count(struct scif_rb *rb, u32 size) -{ - if (scif_rb_ring_cnt(rb->current_write_offset, - rb->current_read_offset, - rb->size) < size) { - rb->current_write_offset = *rb->write_ptr; - /* - * Update from the HW write pointer if empty only once the peer - * has exposed the new message. This read barrier is paired - * with the write barrier in scif_rb_commit(..) - */ - smp_rmb(); - } - return scif_rb_ring_cnt(rb->current_write_offset, - rb->current_read_offset, - rb->size); -} |