cregit-Linux how code gets into the kernel

Release 4.11 drivers/misc/mic/scif/scif_rb.c

/*
 * Intel MIC Platform Software Stack (MPSS)
 *
 * Copyright(c) 2014 Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, version 2, as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * 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; }

Contributors

PersonTokensPropCommitsCommitProp
Sudeep Dutt67100.00%1100.00%
Total67100.00%1100.00%

/* 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); } }

Contributors

PersonTokensPropCommitsCommitProp
Sudeep Dutt119100.00%1100.00%
Total119100.00%1100.00%

/* 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); } }

Contributors

PersonTokensPropCommitsCommitProp
Sudeep Dutt119100.00%1100.00%
Total119100.00%1100.00%

/** * 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); }

Contributors

PersonTokensPropCommitsCommitProp
Sudeep Dutt39100.00%1100.00%
Total39100.00%1100.00%

/** * 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; }

Contributors

PersonTokensPropCommitsCommitProp
Sudeep Dutt79100.00%1100.00%
Total79100.00%1100.00%

/** * 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(); ACCESS_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. */ ACCESS_ONCE(*rb->write_ptr) = rb->current_write_offset; #endif }

Contributors

PersonTokensPropCommitsCommitProp
Sudeep Dutt44100.00%1100.00%
Total44100.00%1100.00%

/** * 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; }

Contributors

PersonTokensPropCommitsCommitProp
Sudeep Dutt45100.00%1100.00%
Total45100.00%1100.00%

/* * 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; }

Contributors

PersonTokensPropCommitsCommitProp
Sudeep Dutt86100.00%1100.00%
Total86100.00%1100.00%

/** * 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(); ACCESS_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. */ ACCESS_ONCE(*rb->read_ptr) = new_offset; #endif }

Contributors

PersonTokensPropCommitsCommitProp
Sudeep Dutt49100.00%1100.00%
Total49100.00%1100.00%

/** * 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); }

Contributors

PersonTokensPropCommitsCommitProp
Sudeep Dutt63100.00%1100.00%
Total63100.00%1100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Sudeep Dutt758100.00%2100.00%
Total758100.00%2100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.