linux/drivers/misc/genwqe/card_dev.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * IBM Accelerator Family 'GenWQE'
 *
 * (C) Copyright IBM Corp. 2013
 *
 * Author: Frank Haverkamp <[email protected]>
 * Author: Joerg-Stephan Vogt <[email protected]>
 * Author: Michael Jung <[email protected]>
 * Author: Michael Ruettger <[email protected]>
 */

/*
 * Character device representation of the GenWQE device. This allows
 * user-space applications to communicate with the card.
 */

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/string.h>
#include <linux/fs.h>
#include <linux/sched/signal.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <linux/atomic.h>

#include "card_base.h"
#include "card_ddcb.h"

static int genwqe_open_files(struct genwqe_dev *cd)
{}

static void genwqe_add_file(struct genwqe_dev *cd, struct genwqe_file *cfile)
{}

static int genwqe_del_file(struct genwqe_dev *cd, struct genwqe_file *cfile)
{}

static void genwqe_add_pin(struct genwqe_file *cfile, struct dma_mapping *m)
{}

static int genwqe_del_pin(struct genwqe_file *cfile, struct dma_mapping *m)
{}

/**
 * genwqe_search_pin() - Search for the mapping for a userspace address
 * @cfile:	Descriptor of opened file
 * @u_addr:	User virtual address
 * @size:	Size of buffer
 * @virt_addr:	Virtual address to be updated
 *
 * Return: Pointer to the corresponding mapping	NULL if not found
 */
static struct dma_mapping *genwqe_search_pin(struct genwqe_file *cfile,
					    unsigned long u_addr,
					    unsigned int size,
					    void **virt_addr)
{}

static void __genwqe_add_mapping(struct genwqe_file *cfile,
			      struct dma_mapping *dma_map)
{}

static void __genwqe_del_mapping(struct genwqe_file *cfile,
			      struct dma_mapping *dma_map)
{}


/**
 * __genwqe_search_mapping() - Search for the mapping for a userspace address
 * @cfile:	descriptor of opened file
 * @u_addr:	user virtual address
 * @size:	size of buffer
 * @dma_addr:	DMA address to be updated
 * @virt_addr:	Virtual address to be updated
 * Return: Pointer to the corresponding mapping	NULL if not found
 */
static struct dma_mapping *__genwqe_search_mapping(struct genwqe_file *cfile,
						   unsigned long u_addr,
						   unsigned int size,
						   dma_addr_t *dma_addr,
						   void **virt_addr)
{}

static void genwqe_remove_mappings(struct genwqe_file *cfile)
{}

static void genwqe_remove_pinnings(struct genwqe_file *cfile)
{}

/**
 * genwqe_kill_fasync() - Send signal to all processes with open GenWQE files
 * @cd: GenWQE device information
 * @sig: Signal to send out
 *
 * E.g. genwqe_send_signal(cd, SIGIO);
 */
static int genwqe_kill_fasync(struct genwqe_dev *cd, int sig)
{}

static int genwqe_terminate(struct genwqe_dev *cd)
{}

/**
 * genwqe_open() - file open
 * @inode:      file system information
 * @filp:	file handle
 *
 * This function is executed whenever an application calls
 * open("/dev/genwqe",..).
 *
 * Return: 0 if successful or <0 if errors
 */
static int genwqe_open(struct inode *inode, struct file *filp)
{}

/**
 * genwqe_fasync() - Setup process to receive SIGIO.
 * @fd:        file descriptor
 * @filp:      file handle
 * @mode:      file mode
 *
 * Sending a signal is working as following:
 *
 * if (cdev->async_queue)
 *         kill_fasync(&cdev->async_queue, SIGIO, POLL_IN);
 *
 * Some devices also implement asynchronous notification to indicate
 * when the device can be written; in this case, of course,
 * kill_fasync must be called with a mode of POLL_OUT.
 */
static int genwqe_fasync(int fd, struct file *filp, int mode)
{}


/**
 * genwqe_release() - file close
 * @inode:      file system information
 * @filp:       file handle
 *
 * This function is executed whenever an application calls 'close(fd_genwqe)'
 *
 * Return: always 0
 */
static int genwqe_release(struct inode *inode, struct file *filp)
{}

static void genwqe_vma_open(struct vm_area_struct *vma)
{}

/**
 * genwqe_vma_close() - Called each time when vma is unmapped
 * @vma: VMA area to close
 *
 * Free memory which got allocated by GenWQE mmap().
 */
static void genwqe_vma_close(struct vm_area_struct *vma)
{}

static const struct vm_operations_struct genwqe_vma_ops =;

/**
 * genwqe_mmap() - Provide contignous buffers to userspace
 * @filp:	File pointer (unused)
 * @vma:	VMA area to map
 *
 * We use mmap() to allocate contignous buffers used for DMA
 * transfers. After the buffer is allocated we remap it to user-space
 * and remember a reference to our dma_mapping data structure, where
 * we store the associated DMA address and allocated size.
 *
 * When we receive a DDCB execution request with the ATS bits set to
 * plain buffer, we lookup our dma_mapping list to find the
 * corresponding DMA address for the associated user-space address.
 */
static int genwqe_mmap(struct file *filp, struct vm_area_struct *vma)
{}

#define FLASH_BLOCK

/**
 * do_flash_update() - Excute flash update (write image or CVPD)
 * @cfile:	Descriptor of opened file
 * @load:      details about image load
 *
 * Return: 0 if successful
 */
static int do_flash_update(struct genwqe_file *cfile,
			   struct genwqe_bitstream *load)
{}

static int do_flash_read(struct genwqe_file *cfile,
			 struct genwqe_bitstream *load)
{}

static int genwqe_pin_mem(struct genwqe_file *cfile, struct genwqe_mem *m)
{}

static int genwqe_unpin_mem(struct genwqe_file *cfile, struct genwqe_mem *m)
{}

/**
 * ddcb_cmd_cleanup() - Remove dynamically created fixup entries
 * @cfile:	Descriptor of opened file
 * @req:	DDCB work request
 *
 * Only if there are any. Pinnings are not removed.
 */
static int ddcb_cmd_cleanup(struct genwqe_file *cfile, struct ddcb_requ *req)
{}

/**
 * ddcb_cmd_fixups() - Establish DMA fixups/sglists for user memory references
 * @cfile:	Descriptor of opened file
 * @req:	DDCB work request
 *
 * Before the DDCB gets executed we need to handle the fixups. We
 * replace the user-space addresses with DMA addresses or do
 * additional setup work e.g. generating a scatter-gather list which
 * is used to describe the memory referred to in the fixup.
 */
static int ddcb_cmd_fixups(struct genwqe_file *cfile, struct ddcb_requ *req)
{}

/**
 * genwqe_execute_ddcb() - Execute DDCB using userspace address fixups
 * @cfile:	Descriptor of opened file
 * @cmd:        Command identifier (passed from user)
 *
 * The code will build up the translation tables or lookup the
 * contignous memory allocation table to find the right translations
 * and DMA addresses.
 */
static int genwqe_execute_ddcb(struct genwqe_file *cfile,
			       struct genwqe_ddcb_cmd *cmd)
{}

static int do_execute_ddcb(struct genwqe_file *cfile,
			   unsigned long arg, int raw)
{}

/**
 * genwqe_ioctl() - IO control
 * @filp:       file handle
 * @cmd:        command identifier (passed from user)
 * @arg:        argument (passed from user)
 *
 * Return: 0 success
 */
static long genwqe_ioctl(struct file *filp, unsigned int cmd,
			 unsigned long arg)
{}

static const struct file_operations genwqe_fops =;

static int genwqe_device_initialized(struct genwqe_dev *cd)
{}

/**
 * genwqe_device_create() - Create and configure genwqe char device
 * @cd:      genwqe device descriptor
 *
 * This function must be called before we create any more genwqe
 * character devices, because it is allocating the major and minor
 * number which are supposed to be used by the client drivers.
 */
int genwqe_device_create(struct genwqe_dev *cd)
{}

static int genwqe_inform_and_stop_processes(struct genwqe_dev *cd)
{}

/**
 * genwqe_device_remove() - Remove genwqe's char device
 * @cd: GenWQE device information
 *
 * This function must be called after the client devices are removed
 * because it will free the major/minor number range for the genwqe
 * drivers.
 *
 * This function must be robust enough to be called twice.
 */
int genwqe_device_remove(struct genwqe_dev *cd)
{}