linux/drivers/misc/mei/client.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2003-2022, Intel Corporation. All rights reserved.
 * Intel Management Engine Interface (Intel MEI) Linux driver
 */

#include <linux/sched/signal.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/dma-mapping.h>

#include <linux/mei.h>

#include "mei_dev.h"
#include "hbm.h"
#include "client.h"

/**
 * mei_me_cl_init - initialize me client
 *
 * @me_cl: me client
 */
void mei_me_cl_init(struct mei_me_client *me_cl)
{}

/**
 * mei_me_cl_get - increases me client refcount
 *
 * @me_cl: me client
 *
 * Locking: called under "dev->device_lock" lock
 *
 * Return: me client or NULL
 */
struct mei_me_client *mei_me_cl_get(struct mei_me_client *me_cl)
{}

/**
 * mei_me_cl_release - free me client
 *
 * @ref: me_client refcount
 *
 * Locking: called under "dev->device_lock" lock
 */
static void mei_me_cl_release(struct kref *ref)
{}

/**
 * mei_me_cl_put - decrease me client refcount and free client if necessary
 *
 * @me_cl: me client
 *
 * Locking: called under "dev->device_lock" lock
 */
void mei_me_cl_put(struct mei_me_client *me_cl)
{}

/**
 * __mei_me_cl_del  - delete me client from the list and decrease
 *     reference counter
 *
 * @dev: mei device
 * @me_cl: me client
 *
 * Locking: dev->me_clients_rwsem
 */
static void __mei_me_cl_del(struct mei_device *dev, struct mei_me_client *me_cl)
{}

/**
 * mei_me_cl_del - delete me client from the list and decrease
 *     reference counter
 *
 * @dev: mei device
 * @me_cl: me client
 */
void mei_me_cl_del(struct mei_device *dev, struct mei_me_client *me_cl)
{}

/**
 * mei_me_cl_add - add me client to the list
 *
 * @dev: mei device
 * @me_cl: me client
 */
void mei_me_cl_add(struct mei_device *dev, struct mei_me_client *me_cl)
{}

/**
 * __mei_me_cl_by_uuid - locate me client by uuid
 *	increases ref count
 *
 * @dev: mei device
 * @uuid: me client uuid
 *
 * Return: me client or NULL if not found
 *
 * Locking: dev->me_clients_rwsem
 */
static struct mei_me_client *__mei_me_cl_by_uuid(struct mei_device *dev,
					const uuid_le *uuid)
{}

/**
 * mei_me_cl_by_uuid - locate me client by uuid
 *	increases ref count
 *
 * @dev: mei device
 * @uuid: me client uuid
 *
 * Return: me client or NULL if not found
 *
 * Locking: dev->me_clients_rwsem
 */
struct mei_me_client *mei_me_cl_by_uuid(struct mei_device *dev,
					const uuid_le *uuid)
{}

/**
 * mei_me_cl_by_id - locate me client by client id
 *	increases ref count
 *
 * @dev: the device structure
 * @client_id: me client id
 *
 * Return: me client or NULL if not found
 *
 * Locking: dev->me_clients_rwsem
 */
struct mei_me_client *mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
{}

/**
 * __mei_me_cl_by_uuid_id - locate me client by client id and uuid
 *	increases ref count
 *
 * @dev: the device structure
 * @uuid: me client uuid
 * @client_id: me client id
 *
 * Return: me client or null if not found
 *
 * Locking: dev->me_clients_rwsem
 */
static struct mei_me_client *__mei_me_cl_by_uuid_id(struct mei_device *dev,
					   const uuid_le *uuid, u8 client_id)
{}


/**
 * mei_me_cl_by_uuid_id - locate me client by client id and uuid
 *	increases ref count
 *
 * @dev: the device structure
 * @uuid: me client uuid
 * @client_id: me client id
 *
 * Return: me client or null if not found
 */
struct mei_me_client *mei_me_cl_by_uuid_id(struct mei_device *dev,
					   const uuid_le *uuid, u8 client_id)
{}

/**
 * mei_me_cl_rm_by_uuid - remove all me clients matching uuid
 *
 * @dev: the device structure
 * @uuid: me client uuid
 *
 * Locking: called under "dev->device_lock" lock
 */
void mei_me_cl_rm_by_uuid(struct mei_device *dev, const uuid_le *uuid)
{}

/**
 * mei_me_cl_rm_by_uuid_id - remove all me clients matching client id
 *
 * @dev: the device structure
 * @uuid: me client uuid
 * @id: me client id
 *
 * Locking: called under "dev->device_lock" lock
 */
void mei_me_cl_rm_by_uuid_id(struct mei_device *dev, const uuid_le *uuid, u8 id)
{}

/**
 * mei_me_cl_rm_all - remove all me clients
 *
 * @dev: the device structure
 *
 * Locking: called under "dev->device_lock" lock
 */
void mei_me_cl_rm_all(struct mei_device *dev)
{}

/**
 * mei_io_cb_free - free mei_cb_private related memory
 *
 * @cb: mei callback struct
 */
void mei_io_cb_free(struct mei_cl_cb *cb)
{}

/**
 * mei_tx_cb_enqueue - queue tx callback
 *
 * @cb: mei callback struct
 * @head: an instance of list to queue on
 *
 * Locking: called under "dev->device_lock" lock
 */
static inline void mei_tx_cb_enqueue(struct mei_cl_cb *cb,
				     struct list_head *head)
{}

/**
 * mei_tx_cb_dequeue - dequeue tx callback
 *
 * @cb: mei callback struct to dequeue and free
 *
 * Locking: called under "dev->device_lock" lock
 */
static inline void mei_tx_cb_dequeue(struct mei_cl_cb *cb)
{}

/**
 * mei_cl_set_read_by_fp - set pending_read flag to vtag struct for given fp
 *
 * @cl: mei client
 * @fp: pointer to file structure
 *
 * Locking: called under "dev->device_lock" lock
 */
static void mei_cl_set_read_by_fp(const struct mei_cl *cl,
				  const struct file *fp)
{}

/**
 * mei_io_cb_init - allocate and initialize io callback
 *
 * @cl: mei client
 * @type: operation type
 * @fp: pointer to file structure
 *
 * Return: mei_cl_cb pointer or NULL;
 */
static struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl,
					enum mei_cb_file_ops type,
					const struct file *fp)
{}

/**
 * mei_io_list_flush_cl - removes cbs belonging to the cl.
 *
 * @head:  an instance of our list structure
 * @cl:    host client
 */
static void mei_io_list_flush_cl(struct list_head *head,
				 const struct mei_cl *cl)
{}

/**
 * mei_io_tx_list_free_cl - removes cb belonging to the cl and free them
 *
 * @head: An instance of our list structure
 * @cl: host client
 * @fp: file pointer (matching cb file object), may be NULL
 */
static void mei_io_tx_list_free_cl(struct list_head *head,
				   const struct mei_cl *cl,
				   const struct file *fp)
{}

/**
 * mei_io_list_free_fp - free cb from a list that matches file pointer
 *
 * @head: io list
 * @fp: file pointer (matching cb file object), may be NULL
 */
static void mei_io_list_free_fp(struct list_head *head, const struct file *fp)
{}

/**
 * mei_cl_free_pending - free pending cb
 *
 * @cl: host client
 */
static void mei_cl_free_pending(struct mei_cl *cl)
{}

/**
 * mei_cl_alloc_cb - a convenient wrapper for allocating read cb
 *
 * @cl: host client
 * @length: size of the buffer
 * @fop_type: operation type
 * @fp: associated file pointer (might be NULL)
 *
 * Return: cb on success and NULL on failure
 */
struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length,
				  enum mei_cb_file_ops fop_type,
				  const struct file *fp)
{}

/**
 * mei_cl_enqueue_ctrl_wr_cb - a convenient wrapper for allocating
 *     and enqueuing of the control commands cb
 *
 * @cl: host client
 * @length: size of the buffer
 * @fop_type: operation type
 * @fp: associated file pointer (might be NULL)
 *
 * Return: cb on success and NULL on failure
 * Locking: called under "dev->device_lock" lock
 */
struct mei_cl_cb *mei_cl_enqueue_ctrl_wr_cb(struct mei_cl *cl, size_t length,
					    enum mei_cb_file_ops fop_type,
					    const struct file *fp)
{}

/**
 * mei_cl_read_cb - find this cl's callback in the read list
 *     for a specific file
 *
 * @cl: host client
 * @fp: file pointer (matching cb file object), may be NULL
 *
 * Return: cb on success, NULL if cb is not found
 */
struct mei_cl_cb *mei_cl_read_cb(struct mei_cl *cl, const struct file *fp)
{}

/**
 * mei_cl_flush_queues - flushes queue lists belonging to cl.
 *
 * @cl: host client
 * @fp: file pointer (matching cb file object), may be NULL
 *
 * Return: 0 on success, -EINVAL if cl or cl->dev is NULL.
 */
int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp)
{}

/**
 * mei_cl_init - initializes cl.
 *
 * @cl: host client to be initialized
 * @dev: mei device
 */
static void mei_cl_init(struct mei_cl *cl, struct mei_device *dev)
{}

/**
 * mei_cl_allocate - allocates cl  structure and sets it up.
 *
 * @dev: mei device
 * Return:  The allocated file or NULL on failure
 */
struct mei_cl *mei_cl_allocate(struct mei_device *dev)
{}

/**
 * mei_cl_link - allocate host id in the host map
 *
 * @cl: host client
 *
 * Return: 0 on success
 *	-EINVAL on incorrect values
 *	-EMFILE if open count exceeded.
 */
int mei_cl_link(struct mei_cl *cl)
{}

/**
 * mei_cl_unlink - remove host client from the list
 *
 * @cl: host client
 *
 * Return: always 0
 */
int mei_cl_unlink(struct mei_cl *cl)
{}

void mei_host_client_init(struct mei_device *dev)
{}

/**
 * mei_hbuf_acquire - try to acquire host buffer
 *
 * @dev: the device structure
 * Return: true if host buffer was acquired
 */
bool mei_hbuf_acquire(struct mei_device *dev)
{}

/**
 * mei_cl_wake_all - wake up readers, writers and event waiters so
 *                 they can be interrupted
 *
 * @cl: host client
 */
static void mei_cl_wake_all(struct mei_cl *cl)
{}

/**
 * mei_cl_set_disconnected - set disconnected state and clear
 *   associated states and resources
 *
 * @cl: host client
 */
static void mei_cl_set_disconnected(struct mei_cl *cl)
{}

static int mei_cl_set_connecting(struct mei_cl *cl, struct mei_me_client *me_cl)
{}

/*
 * mei_cl_send_disconnect - send disconnect request
 *
 * @cl: host client
 * @cb: callback block
 *
 * Return: 0, OK; otherwise, error.
 */
static int mei_cl_send_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb)
{}

/**
 * mei_cl_irq_disconnect - processes close related operation from
 *	interrupt thread context - send disconnect request
 *
 * @cl: client
 * @cb: callback block.
 * @cmpl_list: complete list.
 *
 * Return: 0, OK; otherwise, error.
 */
int mei_cl_irq_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb,
			  struct list_head *cmpl_list)
{}

/**
 * __mei_cl_disconnect - disconnect host client from the me one
 *     internal function runtime pm has to be already acquired
 *
 * @cl: host client
 *
 * Return: 0 on success, <0 on failure.
 */
static int __mei_cl_disconnect(struct mei_cl *cl)
{}

/**
 * mei_cl_disconnect - disconnect host client from the me one
 *
 * @cl: host client
 *
 * Locking: called under "dev->device_lock" lock
 *
 * Return: 0 on success, <0 on failure.
 */
int mei_cl_disconnect(struct mei_cl *cl)
{}


/**
 * mei_cl_is_other_connecting - checks if other
 *    client with the same me client id is connecting
 *
 * @cl: private data of the file object
 *
 * Return: true if other client is connected, false - otherwise.
 */
static bool mei_cl_is_other_connecting(struct mei_cl *cl)
{}

/**
 * mei_cl_send_connect - send connect request
 *
 * @cl: host client
 * @cb: callback block
 *
 * Return: 0, OK; otherwise, error.
 */
static int mei_cl_send_connect(struct mei_cl *cl, struct mei_cl_cb *cb)
{}

/**
 * mei_cl_irq_connect - send connect request in irq_thread context
 *
 * @cl: host client
 * @cb: callback block
 * @cmpl_list: complete list
 *
 * Return: 0, OK; otherwise, error.
 */
int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
		       struct list_head *cmpl_list)
{}

/**
 * mei_cl_connect - connect host client to the me one
 *
 * @cl: host client
 * @me_cl: me client
 * @fp: pointer to file structure
 *
 * Locking: called under "dev->device_lock" lock
 *
 * Return: 0 on success, <0 on failure.
 */
int mei_cl_connect(struct mei_cl *cl, struct mei_me_client *me_cl,
		   const struct file *fp)
{}

/**
 * mei_cl_alloc_linked - allocate and link host client
 *
 * @dev: the device structure
 *
 * Return: cl on success ERR_PTR on failure
 */
struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev)
{}

/**
 * mei_cl_tx_flow_ctrl_creds - checks flow_control credits for cl.
 *
 * @cl: host client
 *
 * Return: 1 if tx_flow_ctrl_creds >0, 0 - otherwise.
 */
static int mei_cl_tx_flow_ctrl_creds(struct mei_cl *cl)
{}

/**
 * mei_cl_tx_flow_ctrl_creds_reduce - reduces transmit flow control credits
 *   for a client
 *
 * @cl: host client
 *
 * Return:
 *	0 on success
 *	-EINVAL when ctrl credits are <= 0
 */
static int mei_cl_tx_flow_ctrl_creds_reduce(struct mei_cl *cl)
{}

/**
 * mei_cl_vtag_alloc - allocate and fill the vtag structure
 *
 * @fp: pointer to file structure
 * @vtag: vm tag
 *
 * Return:
 * * Pointer to allocated struct - on success
 * * ERR_PTR(-ENOMEM) on memory allocation failure
 */
struct mei_cl_vtag *mei_cl_vtag_alloc(struct file *fp, u8 vtag)
{}

/**
 * mei_cl_fp_by_vtag - obtain the file pointer by vtag
 *
 * @cl: host client
 * @vtag: virtual tag
 *
 * Return:
 * * A file pointer - on success
 * * ERR_PTR(-ENOENT) if vtag is not found in the client vtag list
 */
const struct file *mei_cl_fp_by_vtag(const struct mei_cl *cl, u8 vtag)
{}

/**
 * mei_cl_reset_read_by_vtag - reset pending_read flag by given vtag
 *
 * @cl: host client
 * @vtag: vm tag
 */
static void mei_cl_reset_read_by_vtag(const struct mei_cl *cl, u8 vtag)
{}

/**
 * mei_cl_read_vtag_add_fc - add flow control for next pending reader
 *                           in the vtag list
 *
 * @cl: host client
 */
static void mei_cl_read_vtag_add_fc(struct mei_cl *cl)
{}

/**
 * mei_cl_vt_support_check - check if client support vtags
 *
 * @cl: host client
 *
 * Return:
 * * 0 - supported, or not connected at all
 * * -EOPNOTSUPP - vtags are not supported by client
 */
int mei_cl_vt_support_check(const struct mei_cl *cl)
{}

/**
 * mei_cl_add_rd_completed - add read completed callback to list with lock
 *                           and vtag check
 *
 * @cl: host client
 * @cb: callback block
 *
 */
void mei_cl_add_rd_completed(struct mei_cl *cl, struct mei_cl_cb *cb)
{}

/**
 * mei_cl_del_rd_completed - free read completed callback with lock
 *
 * @cl: host client
 * @cb: callback block
 *
 */
void mei_cl_del_rd_completed(struct mei_cl *cl, struct mei_cl_cb *cb)
{}

/**
 *  mei_cl_notify_fop2req - convert fop to proper request
 *
 * @fop: client notification start response command
 *
 * Return:  MEI_HBM_NOTIFICATION_START/STOP
 */
u8 mei_cl_notify_fop2req(enum mei_cb_file_ops fop)
{}

/**
 *  mei_cl_notify_req2fop - convert notification request top file operation type
 *
 * @req: hbm notification request type
 *
 * Return:  MEI_FOP_NOTIFY_START/STOP
 */
enum mei_cb_file_ops mei_cl_notify_req2fop(u8 req)
{}

/**
 * mei_cl_irq_notify - send notification request in irq_thread context
 *
 * @cl: client
 * @cb: callback block.
 * @cmpl_list: complete list.
 *
 * Return: 0 on such and error otherwise.
 */
int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb,
		      struct list_head *cmpl_list)
{}

/**
 * mei_cl_notify_request - send notification stop/start request
 *
 * @cl: host client
 * @fp: associate request with file
 * @request: 1 for start or 0 for stop
 *
 * Locking: called under "dev->device_lock" lock
 *
 * Return: 0 on such and error otherwise.
 */
int mei_cl_notify_request(struct mei_cl *cl,
			  const struct file *fp, u8 request)
{}

/**
 * mei_cl_notify - raise notification
 *
 * @cl: host client
 *
 * Locking: called under "dev->device_lock" lock
 */
void mei_cl_notify(struct mei_cl *cl)
{}

/**
 * mei_cl_notify_get - get or wait for notification event
 *
 * @cl: host client
 * @block: this request is blocking
 * @notify_ev: true if notification event was received
 *
 * Locking: called under "dev->device_lock" lock
 *
 * Return: 0 on such and error otherwise.
 */
int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev)
{}

/**
 * mei_cl_read_start - the start read client message function.
 *
 * @cl: host client
 * @length: number of bytes to read
 * @fp: pointer to file structure
 *
 * Return: 0 on success, <0 on failure.
 */
int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp)
{}

static inline u8 mei_ext_hdr_set_vtag(void *ext, u8 vtag)
{}

static inline bool mei_ext_hdr_is_gsc(struct mei_ext_hdr *ext)
{}

static inline u8 mei_ext_hdr_set_gsc(struct mei_ext_hdr *ext, struct mei_ext_hdr *gsc_hdr)
{}

/**
 * mei_msg_hdr_init - allocate and initialize mei message header
 *
 * @cb: message callback structure
 *
 * Return: a pointer to initialized header or ERR_PTR on failure
 */
static struct mei_msg_hdr *mei_msg_hdr_init(const struct mei_cl_cb *cb)
{}

/**
 * mei_cl_irq_write - write a message to device
 *	from the interrupt thread context
 *
 * @cl: client
 * @cb: callback block.
 * @cmpl_list: complete list.
 *
 * Return: 0, OK; otherwise error.
 */
int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
		     struct list_head *cmpl_list)
{}

/**
 * mei_cl_write - submit a write cb to mei device
 *	assumes device_lock is locked
 *
 * @cl: host client
 * @cb: write callback with filled data
 * @timeout: send timeout in milliseconds.
 *           effective only for blocking writes: the cb->blocking is set.
 *           set timeout to the MAX_SCHEDULE_TIMEOUT to maixum allowed wait.
 *
 * Return: number of bytes sent on success, <0 on failure.
 */
ssize_t mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, unsigned long timeout)
{}

/**
 * mei_cl_complete - processes completed operation for a client
 *
 * @cl: private data of the file object.
 * @cb: callback block.
 */
void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
{}


/**
 * mei_cl_all_disconnect - disconnect forcefully all connected clients
 *
 * @dev: mei device
 */
void mei_cl_all_disconnect(struct mei_device *dev)
{}
EXPORT_SYMBOL_GPL();

static struct mei_cl *mei_cl_dma_map_find(struct mei_device *dev, u8 buffer_id)
{}

/**
 * mei_cl_irq_dma_map - send client dma map request in irq_thread context
 *
 * @cl: client
 * @cb: callback block.
 * @cmpl_list: complete list.
 *
 * Return: 0 on such and error otherwise.
 */
int mei_cl_irq_dma_map(struct mei_cl *cl, struct mei_cl_cb *cb,
		       struct list_head *cmpl_list)
{}

/**
 * mei_cl_irq_dma_unmap - send client dma unmap request in irq_thread context
 *
 * @cl: client
 * @cb: callback block.
 * @cmpl_list: complete list.
 *
 * Return: 0 on such and error otherwise.
 */
int mei_cl_irq_dma_unmap(struct mei_cl *cl, struct mei_cl_cb *cb,
			 struct list_head *cmpl_list)
{}

static int mei_cl_dma_alloc(struct mei_cl *cl, u8 buf_id, size_t size)
{}

static void mei_cl_dma_free(struct mei_cl *cl)
{}

/**
 * mei_cl_dma_alloc_and_map - send client dma map request
 *
 * @cl: host client
 * @fp: pointer to file structure
 * @buffer_id: id of the mapped buffer
 * @size: size of the buffer
 *
 * Locking: called under "dev->device_lock" lock
 *
 * Return:
 * * -ENODEV
 * * -EINVAL
 * * -EOPNOTSUPP
 * * -EPROTO
 * * -ENOMEM;
 */
int mei_cl_dma_alloc_and_map(struct mei_cl *cl, const struct file *fp,
			     u8 buffer_id, size_t size)
{}

/**
 * mei_cl_dma_unmap - send client dma unmap request
 *
 * @cl: host client
 * @fp: pointer to file structure
 *
 * Locking: called under "dev->device_lock" lock
 *
 * Return: 0 on such and error otherwise.
 */
int mei_cl_dma_unmap(struct mei_cl *cl, const struct file *fp)
{}