18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * ISHTP client logic 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2003-2016, Intel Corporation. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#ifndef _ISHTP_CLIENT_H_ 98c2ecf20Sopenharmony_ci#define _ISHTP_CLIENT_H_ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/types.h> 128c2ecf20Sopenharmony_ci#include "ishtp-dev.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci/* Tx and Rx ring size */ 158c2ecf20Sopenharmony_ci#define CL_DEF_RX_RING_SIZE 2 168c2ecf20Sopenharmony_ci#define CL_DEF_TX_RING_SIZE 2 178c2ecf20Sopenharmony_ci#define CL_MAX_RX_RING_SIZE 32 188c2ecf20Sopenharmony_ci#define CL_MAX_TX_RING_SIZE 32 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#define DMA_SLOT_SIZE 4096 218c2ecf20Sopenharmony_ci/* Number of IPC fragments after which it's worth sending via DMA */ 228c2ecf20Sopenharmony_ci#define DMA_WORTH_THRESHOLD 3 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci/* DMA/IPC Tx paths. Other the default means enforcement */ 258c2ecf20Sopenharmony_ci#define CL_TX_PATH_DEFAULT 0 268c2ecf20Sopenharmony_ci#define CL_TX_PATH_IPC 1 278c2ecf20Sopenharmony_ci#define CL_TX_PATH_DMA 2 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci/* Client Tx buffer list entry */ 308c2ecf20Sopenharmony_cistruct ishtp_cl_tx_ring { 318c2ecf20Sopenharmony_ci struct list_head list; 328c2ecf20Sopenharmony_ci struct ishtp_msg_data send_buf; 338c2ecf20Sopenharmony_ci}; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci/* ISHTP client instance */ 368c2ecf20Sopenharmony_cistruct ishtp_cl { 378c2ecf20Sopenharmony_ci struct list_head link; 388c2ecf20Sopenharmony_ci struct ishtp_device *dev; 398c2ecf20Sopenharmony_ci enum cl_state state; 408c2ecf20Sopenharmony_ci int status; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci /* Link to ISHTP bus device */ 438c2ecf20Sopenharmony_ci struct ishtp_cl_device *device; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci /* ID of client connected */ 468c2ecf20Sopenharmony_ci uint8_t host_client_id; 478c2ecf20Sopenharmony_ci uint8_t fw_client_id; 488c2ecf20Sopenharmony_ci uint8_t ishtp_flow_ctrl_creds; 498c2ecf20Sopenharmony_ci uint8_t out_flow_ctrl_creds; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci /* dma */ 528c2ecf20Sopenharmony_ci int last_tx_path; 538c2ecf20Sopenharmony_ci /* 0: ack wasn't received,1:ack was received */ 548c2ecf20Sopenharmony_ci int last_dma_acked; 558c2ecf20Sopenharmony_ci unsigned char *last_dma_addr; 568c2ecf20Sopenharmony_ci /* 0: ack wasn't received,1:ack was received */ 578c2ecf20Sopenharmony_ci int last_ipc_acked; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci /* Rx ring buffer pool */ 608c2ecf20Sopenharmony_ci unsigned int rx_ring_size; 618c2ecf20Sopenharmony_ci struct ishtp_cl_rb free_rb_list; 628c2ecf20Sopenharmony_ci spinlock_t free_list_spinlock; 638c2ecf20Sopenharmony_ci /* Rx in-process list */ 648c2ecf20Sopenharmony_ci struct ishtp_cl_rb in_process_list; 658c2ecf20Sopenharmony_ci spinlock_t in_process_spinlock; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci /* Client Tx buffers list */ 688c2ecf20Sopenharmony_ci unsigned int tx_ring_size; 698c2ecf20Sopenharmony_ci struct ishtp_cl_tx_ring tx_list, tx_free_list; 708c2ecf20Sopenharmony_ci int tx_ring_free_size; 718c2ecf20Sopenharmony_ci spinlock_t tx_list_spinlock; 728c2ecf20Sopenharmony_ci spinlock_t tx_free_list_spinlock; 738c2ecf20Sopenharmony_ci size_t tx_offs; /* Offset in buffer at head of 'tx_list' */ 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci /** 768c2ecf20Sopenharmony_ci * if we get a FC, and the list is not empty, we must know whether we 778c2ecf20Sopenharmony_ci * are at the middle of sending. 788c2ecf20Sopenharmony_ci * if so -need to increase FC counter, otherwise, need to start sending 798c2ecf20Sopenharmony_ci * the first msg in list 808c2ecf20Sopenharmony_ci * (!)This is for counting-FC implementation only. Within single-FC the 818c2ecf20Sopenharmony_ci * other party may NOT send FC until it receives complete message 828c2ecf20Sopenharmony_ci */ 838c2ecf20Sopenharmony_ci int sending; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci /* Send FC spinlock */ 868c2ecf20Sopenharmony_ci spinlock_t fc_spinlock; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci /* wait queue for connect and disconnect response from FW */ 898c2ecf20Sopenharmony_ci wait_queue_head_t wait_ctrl_res; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci /* Error stats */ 928c2ecf20Sopenharmony_ci unsigned int err_send_msg; 938c2ecf20Sopenharmony_ci unsigned int err_send_fc; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci /* Send/recv stats */ 968c2ecf20Sopenharmony_ci unsigned int send_msg_cnt_ipc; 978c2ecf20Sopenharmony_ci unsigned int send_msg_cnt_dma; 988c2ecf20Sopenharmony_ci unsigned int recv_msg_cnt_ipc; 998c2ecf20Sopenharmony_ci unsigned int recv_msg_cnt_dma; 1008c2ecf20Sopenharmony_ci unsigned int recv_msg_num_frags; 1018c2ecf20Sopenharmony_ci unsigned int ishtp_flow_ctrl_cnt; 1028c2ecf20Sopenharmony_ci unsigned int out_flow_ctrl_cnt; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci /* Rx msg ... out FC timing */ 1058c2ecf20Sopenharmony_ci ktime_t ts_rx; 1068c2ecf20Sopenharmony_ci ktime_t ts_out_fc; 1078c2ecf20Sopenharmony_ci ktime_t ts_max_fc_delay; 1088c2ecf20Sopenharmony_ci void *client_data; 1098c2ecf20Sopenharmony_ci}; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci/* Client connection managenment internal functions */ 1128c2ecf20Sopenharmony_ciint ishtp_can_client_connect(struct ishtp_device *ishtp_dev, guid_t *uuid); 1138c2ecf20Sopenharmony_ciint ishtp_fw_cl_by_id(struct ishtp_device *dev, uint8_t client_id); 1148c2ecf20Sopenharmony_civoid ishtp_cl_send_msg(struct ishtp_device *dev, struct ishtp_cl *cl); 1158c2ecf20Sopenharmony_civoid recv_ishtp_cl_msg(struct ishtp_device *dev, 1168c2ecf20Sopenharmony_ci struct ishtp_msg_hdr *ishtp_hdr); 1178c2ecf20Sopenharmony_ciint ishtp_cl_read_start(struct ishtp_cl *cl); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci/* Ring Buffer I/F */ 1208c2ecf20Sopenharmony_ciint ishtp_cl_alloc_rx_ring(struct ishtp_cl *cl); 1218c2ecf20Sopenharmony_ciint ishtp_cl_alloc_tx_ring(struct ishtp_cl *cl); 1228c2ecf20Sopenharmony_civoid ishtp_cl_free_rx_ring(struct ishtp_cl *cl); 1238c2ecf20Sopenharmony_civoid ishtp_cl_free_tx_ring(struct ishtp_cl *cl); 1248c2ecf20Sopenharmony_ciint ishtp_cl_get_tx_free_buffer_size(struct ishtp_cl *cl); 1258c2ecf20Sopenharmony_ciint ishtp_cl_get_tx_free_rings(struct ishtp_cl *cl); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci/* DMA I/F functions */ 1288c2ecf20Sopenharmony_civoid recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg, 1298c2ecf20Sopenharmony_ci struct dma_xfer_hbm *hbm); 1308c2ecf20Sopenharmony_civoid ishtp_cl_alloc_dma_buf(struct ishtp_device *dev); 1318c2ecf20Sopenharmony_civoid ishtp_cl_free_dma_buf(struct ishtp_device *dev); 1328c2ecf20Sopenharmony_civoid *ishtp_cl_get_dma_send_buf(struct ishtp_device *dev, 1338c2ecf20Sopenharmony_ci uint32_t size); 1348c2ecf20Sopenharmony_civoid ishtp_cl_release_dma_acked_mem(struct ishtp_device *dev, 1358c2ecf20Sopenharmony_ci void *msg_addr, 1368c2ecf20Sopenharmony_ci uint8_t size); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci/* Request blocks alloc/free I/F */ 1398c2ecf20Sopenharmony_cistruct ishtp_cl_rb *ishtp_io_rb_init(struct ishtp_cl *cl); 1408c2ecf20Sopenharmony_civoid ishtp_io_rb_free(struct ishtp_cl_rb *priv_rb); 1418c2ecf20Sopenharmony_ciint ishtp_io_rb_alloc_buf(struct ishtp_cl_rb *rb, size_t length); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci/** 1448c2ecf20Sopenharmony_ci * ishtp_cl_cmp_id - tells if file private data have same id 1458c2ecf20Sopenharmony_ci * returns true - if ids are the same and not NULL 1468c2ecf20Sopenharmony_ci */ 1478c2ecf20Sopenharmony_cistatic inline bool ishtp_cl_cmp_id(const struct ishtp_cl *cl1, 1488c2ecf20Sopenharmony_ci const struct ishtp_cl *cl2) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci return cl1 && cl2 && 1518c2ecf20Sopenharmony_ci (cl1->host_client_id == cl2->host_client_id) && 1528c2ecf20Sopenharmony_ci (cl1->fw_client_id == cl2->fw_client_id); 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci#endif /* _ISHTP_CLIENT_H_ */ 156