162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * ISHTP client logic 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2003-2016, Intel Corporation. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#ifndef _ISHTP_CLIENT_H_ 962306a36Sopenharmony_ci#define _ISHTP_CLIENT_H_ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/types.h> 1262306a36Sopenharmony_ci#include "ishtp-dev.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/* Tx and Rx ring size */ 1562306a36Sopenharmony_ci#define CL_DEF_RX_RING_SIZE 2 1662306a36Sopenharmony_ci#define CL_DEF_TX_RING_SIZE 2 1762306a36Sopenharmony_ci#define CL_MAX_RX_RING_SIZE 32 1862306a36Sopenharmony_ci#define CL_MAX_TX_RING_SIZE 32 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#define DMA_SLOT_SIZE 4096 2162306a36Sopenharmony_ci/* Number of IPC fragments after which it's worth sending via DMA */ 2262306a36Sopenharmony_ci#define DMA_WORTH_THRESHOLD 3 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* DMA/IPC Tx paths. Other the default means enforcement */ 2562306a36Sopenharmony_ci#define CL_TX_PATH_DEFAULT 0 2662306a36Sopenharmony_ci#define CL_TX_PATH_IPC 1 2762306a36Sopenharmony_ci#define CL_TX_PATH_DMA 2 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/* Client Tx buffer list entry */ 3062306a36Sopenharmony_cistruct ishtp_cl_tx_ring { 3162306a36Sopenharmony_ci struct list_head list; 3262306a36Sopenharmony_ci struct ishtp_msg_data send_buf; 3362306a36Sopenharmony_ci}; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* ISHTP client instance */ 3662306a36Sopenharmony_cistruct ishtp_cl { 3762306a36Sopenharmony_ci struct list_head link; 3862306a36Sopenharmony_ci struct ishtp_device *dev; 3962306a36Sopenharmony_ci enum cl_state state; 4062306a36Sopenharmony_ci int status; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci /* Link to ISHTP bus device */ 4362306a36Sopenharmony_ci struct ishtp_cl_device *device; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci /* ID of client connected */ 4662306a36Sopenharmony_ci uint8_t host_client_id; 4762306a36Sopenharmony_ci uint8_t fw_client_id; 4862306a36Sopenharmony_ci uint8_t ishtp_flow_ctrl_creds; 4962306a36Sopenharmony_ci uint8_t out_flow_ctrl_creds; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci /* dma */ 5262306a36Sopenharmony_ci int last_tx_path; 5362306a36Sopenharmony_ci /* 0: ack wasn't received,1:ack was received */ 5462306a36Sopenharmony_ci int last_dma_acked; 5562306a36Sopenharmony_ci unsigned char *last_dma_addr; 5662306a36Sopenharmony_ci /* 0: ack wasn't received,1:ack was received */ 5762306a36Sopenharmony_ci int last_ipc_acked; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci /* Rx ring buffer pool */ 6062306a36Sopenharmony_ci unsigned int rx_ring_size; 6162306a36Sopenharmony_ci struct ishtp_cl_rb free_rb_list; 6262306a36Sopenharmony_ci spinlock_t free_list_spinlock; 6362306a36Sopenharmony_ci /* Rx in-process list */ 6462306a36Sopenharmony_ci struct ishtp_cl_rb in_process_list; 6562306a36Sopenharmony_ci spinlock_t in_process_spinlock; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci /* Client Tx buffers list */ 6862306a36Sopenharmony_ci unsigned int tx_ring_size; 6962306a36Sopenharmony_ci struct ishtp_cl_tx_ring tx_list, tx_free_list; 7062306a36Sopenharmony_ci int tx_ring_free_size; 7162306a36Sopenharmony_ci spinlock_t tx_list_spinlock; 7262306a36Sopenharmony_ci spinlock_t tx_free_list_spinlock; 7362306a36Sopenharmony_ci size_t tx_offs; /* Offset in buffer at head of 'tx_list' */ 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci /** 7662306a36Sopenharmony_ci * if we get a FC, and the list is not empty, we must know whether we 7762306a36Sopenharmony_ci * are at the middle of sending. 7862306a36Sopenharmony_ci * if so -need to increase FC counter, otherwise, need to start sending 7962306a36Sopenharmony_ci * the first msg in list 8062306a36Sopenharmony_ci * (!)This is for counting-FC implementation only. Within single-FC the 8162306a36Sopenharmony_ci * other party may NOT send FC until it receives complete message 8262306a36Sopenharmony_ci */ 8362306a36Sopenharmony_ci int sending; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci /* Send FC spinlock */ 8662306a36Sopenharmony_ci spinlock_t fc_spinlock; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci /* wait queue for connect and disconnect response from FW */ 8962306a36Sopenharmony_ci wait_queue_head_t wait_ctrl_res; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci /* Error stats */ 9262306a36Sopenharmony_ci unsigned int err_send_msg; 9362306a36Sopenharmony_ci unsigned int err_send_fc; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci /* Send/recv stats */ 9662306a36Sopenharmony_ci unsigned int send_msg_cnt_ipc; 9762306a36Sopenharmony_ci unsigned int send_msg_cnt_dma; 9862306a36Sopenharmony_ci unsigned int recv_msg_cnt_ipc; 9962306a36Sopenharmony_ci unsigned int recv_msg_cnt_dma; 10062306a36Sopenharmony_ci unsigned int recv_msg_num_frags; 10162306a36Sopenharmony_ci unsigned int ishtp_flow_ctrl_cnt; 10262306a36Sopenharmony_ci unsigned int out_flow_ctrl_cnt; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci /* Rx msg ... out FC timing */ 10562306a36Sopenharmony_ci ktime_t ts_rx; 10662306a36Sopenharmony_ci ktime_t ts_out_fc; 10762306a36Sopenharmony_ci ktime_t ts_max_fc_delay; 10862306a36Sopenharmony_ci void *client_data; 10962306a36Sopenharmony_ci}; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci/* Client connection managenment internal functions */ 11262306a36Sopenharmony_ciint ishtp_can_client_connect(struct ishtp_device *ishtp_dev, guid_t *uuid); 11362306a36Sopenharmony_ciint ishtp_fw_cl_by_id(struct ishtp_device *dev, uint8_t client_id); 11462306a36Sopenharmony_civoid ishtp_cl_send_msg(struct ishtp_device *dev, struct ishtp_cl *cl); 11562306a36Sopenharmony_civoid recv_ishtp_cl_msg(struct ishtp_device *dev, 11662306a36Sopenharmony_ci struct ishtp_msg_hdr *ishtp_hdr); 11762306a36Sopenharmony_ciint ishtp_cl_read_start(struct ishtp_cl *cl); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci/* Ring Buffer I/F */ 12062306a36Sopenharmony_ciint ishtp_cl_alloc_rx_ring(struct ishtp_cl *cl); 12162306a36Sopenharmony_ciint ishtp_cl_alloc_tx_ring(struct ishtp_cl *cl); 12262306a36Sopenharmony_civoid ishtp_cl_free_rx_ring(struct ishtp_cl *cl); 12362306a36Sopenharmony_civoid ishtp_cl_free_tx_ring(struct ishtp_cl *cl); 12462306a36Sopenharmony_ciint ishtp_cl_get_tx_free_buffer_size(struct ishtp_cl *cl); 12562306a36Sopenharmony_ciint ishtp_cl_get_tx_free_rings(struct ishtp_cl *cl); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci/* DMA I/F functions */ 12862306a36Sopenharmony_civoid recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg, 12962306a36Sopenharmony_ci struct dma_xfer_hbm *hbm); 13062306a36Sopenharmony_civoid ishtp_cl_alloc_dma_buf(struct ishtp_device *dev); 13162306a36Sopenharmony_civoid ishtp_cl_free_dma_buf(struct ishtp_device *dev); 13262306a36Sopenharmony_civoid *ishtp_cl_get_dma_send_buf(struct ishtp_device *dev, 13362306a36Sopenharmony_ci uint32_t size); 13462306a36Sopenharmony_civoid ishtp_cl_release_dma_acked_mem(struct ishtp_device *dev, 13562306a36Sopenharmony_ci void *msg_addr, 13662306a36Sopenharmony_ci uint8_t size); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci/* Request blocks alloc/free I/F */ 13962306a36Sopenharmony_cistruct ishtp_cl_rb *ishtp_io_rb_init(struct ishtp_cl *cl); 14062306a36Sopenharmony_civoid ishtp_io_rb_free(struct ishtp_cl_rb *priv_rb); 14162306a36Sopenharmony_ciint ishtp_io_rb_alloc_buf(struct ishtp_cl_rb *rb, size_t length); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci/** 14462306a36Sopenharmony_ci * ishtp_cl_cmp_id - tells if file private data have same id 14562306a36Sopenharmony_ci * returns true - if ids are the same and not NULL 14662306a36Sopenharmony_ci */ 14762306a36Sopenharmony_cistatic inline bool ishtp_cl_cmp_id(const struct ishtp_cl *cl1, 14862306a36Sopenharmony_ci const struct ishtp_cl *cl2) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci return cl1 && cl2 && 15162306a36Sopenharmony_ci (cl1->host_client_id == cl2->host_client_id) && 15262306a36Sopenharmony_ci (cl1->fw_client_id == cl2->fw_client_id); 15362306a36Sopenharmony_ci} 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci#endif /* _ISHTP_CLIENT_H_ */ 156