1*2025cf9eSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */ 23703f53bSSrinivas Pandruvada /* 33703f53bSSrinivas Pandruvada * ISHTP client logic 43703f53bSSrinivas Pandruvada * 53703f53bSSrinivas Pandruvada * Copyright (c) 2003-2016, Intel Corporation. 63703f53bSSrinivas Pandruvada */ 73703f53bSSrinivas Pandruvada 83703f53bSSrinivas Pandruvada #ifndef _ISHTP_CLIENT_H_ 93703f53bSSrinivas Pandruvada #define _ISHTP_CLIENT_H_ 103703f53bSSrinivas Pandruvada 113703f53bSSrinivas Pandruvada #include <linux/types.h> 123703f53bSSrinivas Pandruvada #include "ishtp-dev.h" 133703f53bSSrinivas Pandruvada 143703f53bSSrinivas Pandruvada /* Tx and Rx ring size */ 153703f53bSSrinivas Pandruvada #define CL_DEF_RX_RING_SIZE 2 163703f53bSSrinivas Pandruvada #define CL_DEF_TX_RING_SIZE 2 173703f53bSSrinivas Pandruvada #define CL_MAX_RX_RING_SIZE 32 183703f53bSSrinivas Pandruvada #define CL_MAX_TX_RING_SIZE 32 193703f53bSSrinivas Pandruvada 203703f53bSSrinivas Pandruvada #define DMA_SLOT_SIZE 4096 213703f53bSSrinivas Pandruvada /* Number of IPC fragments after which it's worth sending via DMA */ 223703f53bSSrinivas Pandruvada #define DMA_WORTH_THRESHOLD 3 233703f53bSSrinivas Pandruvada 243703f53bSSrinivas Pandruvada /* DMA/IPC Tx paths. Other the default means enforcement */ 253703f53bSSrinivas Pandruvada #define CL_TX_PATH_DEFAULT 0 263703f53bSSrinivas Pandruvada #define CL_TX_PATH_IPC 1 273703f53bSSrinivas Pandruvada #define CL_TX_PATH_DMA 2 283703f53bSSrinivas Pandruvada 293703f53bSSrinivas Pandruvada /* Client Tx buffer list entry */ 303703f53bSSrinivas Pandruvada struct ishtp_cl_tx_ring { 313703f53bSSrinivas Pandruvada struct list_head list; 323703f53bSSrinivas Pandruvada struct ishtp_msg_data send_buf; 333703f53bSSrinivas Pandruvada }; 343703f53bSSrinivas Pandruvada 353703f53bSSrinivas Pandruvada /* ISHTP client instance */ 363703f53bSSrinivas Pandruvada struct ishtp_cl { 373703f53bSSrinivas Pandruvada struct list_head link; 383703f53bSSrinivas Pandruvada struct ishtp_device *dev; 393703f53bSSrinivas Pandruvada enum cl_state state; 403703f53bSSrinivas Pandruvada int status; 413703f53bSSrinivas Pandruvada 423703f53bSSrinivas Pandruvada /* Link to ISHTP bus device */ 433703f53bSSrinivas Pandruvada struct ishtp_cl_device *device; 443703f53bSSrinivas Pandruvada 453703f53bSSrinivas Pandruvada /* ID of client connected */ 463703f53bSSrinivas Pandruvada uint8_t host_client_id; 473703f53bSSrinivas Pandruvada uint8_t fw_client_id; 483703f53bSSrinivas Pandruvada uint8_t ishtp_flow_ctrl_creds; 493703f53bSSrinivas Pandruvada uint8_t out_flow_ctrl_creds; 503703f53bSSrinivas Pandruvada 513703f53bSSrinivas Pandruvada /* dma */ 523703f53bSSrinivas Pandruvada int last_tx_path; 533703f53bSSrinivas Pandruvada /* 0: ack wasn't received,1:ack was received */ 543703f53bSSrinivas Pandruvada int last_dma_acked; 553703f53bSSrinivas Pandruvada unsigned char *last_dma_addr; 563703f53bSSrinivas Pandruvada /* 0: ack wasn't received,1:ack was received */ 573703f53bSSrinivas Pandruvada int last_ipc_acked; 583703f53bSSrinivas Pandruvada 593703f53bSSrinivas Pandruvada /* Rx ring buffer pool */ 603703f53bSSrinivas Pandruvada unsigned int rx_ring_size; 613703f53bSSrinivas Pandruvada struct ishtp_cl_rb free_rb_list; 623703f53bSSrinivas Pandruvada spinlock_t free_list_spinlock; 633703f53bSSrinivas Pandruvada /* Rx in-process list */ 643703f53bSSrinivas Pandruvada struct ishtp_cl_rb in_process_list; 653703f53bSSrinivas Pandruvada spinlock_t in_process_spinlock; 663703f53bSSrinivas Pandruvada 673703f53bSSrinivas Pandruvada /* Client Tx buffers list */ 683703f53bSSrinivas Pandruvada unsigned int tx_ring_size; 693703f53bSSrinivas Pandruvada struct ishtp_cl_tx_ring tx_list, tx_free_list; 7018c0b546SSrinivas Pandruvada int tx_ring_free_size; 713703f53bSSrinivas Pandruvada spinlock_t tx_list_spinlock; 723703f53bSSrinivas Pandruvada spinlock_t tx_free_list_spinlock; 733703f53bSSrinivas Pandruvada size_t tx_offs; /* Offset in buffer at head of 'tx_list' */ 743703f53bSSrinivas Pandruvada 753703f53bSSrinivas Pandruvada /** 763703f53bSSrinivas Pandruvada * if we get a FC, and the list is not empty, we must know whether we 773703f53bSSrinivas Pandruvada * are at the middle of sending. 783703f53bSSrinivas Pandruvada * if so -need to increase FC counter, otherwise, need to start sending 793703f53bSSrinivas Pandruvada * the first msg in list 803703f53bSSrinivas Pandruvada * (!)This is for counting-FC implementation only. Within single-FC the 813703f53bSSrinivas Pandruvada * other party may NOT send FC until it receives complete message 823703f53bSSrinivas Pandruvada */ 833703f53bSSrinivas Pandruvada int sending; 843703f53bSSrinivas Pandruvada 853703f53bSSrinivas Pandruvada /* Send FC spinlock */ 863703f53bSSrinivas Pandruvada spinlock_t fc_spinlock; 873703f53bSSrinivas Pandruvada 883703f53bSSrinivas Pandruvada /* wait queue for connect and disconnect response from FW */ 893703f53bSSrinivas Pandruvada wait_queue_head_t wait_ctrl_res; 903703f53bSSrinivas Pandruvada 913703f53bSSrinivas Pandruvada /* Error stats */ 923703f53bSSrinivas Pandruvada unsigned int err_send_msg; 933703f53bSSrinivas Pandruvada unsigned int err_send_fc; 943703f53bSSrinivas Pandruvada 953703f53bSSrinivas Pandruvada /* Send/recv stats */ 963703f53bSSrinivas Pandruvada unsigned int send_msg_cnt_ipc; 973703f53bSSrinivas Pandruvada unsigned int send_msg_cnt_dma; 983703f53bSSrinivas Pandruvada unsigned int recv_msg_cnt_ipc; 993703f53bSSrinivas Pandruvada unsigned int recv_msg_cnt_dma; 1003703f53bSSrinivas Pandruvada unsigned int recv_msg_num_frags; 1013703f53bSSrinivas Pandruvada unsigned int ishtp_flow_ctrl_cnt; 1023703f53bSSrinivas Pandruvada unsigned int out_flow_ctrl_cnt; 1033703f53bSSrinivas Pandruvada 1043703f53bSSrinivas Pandruvada /* Rx msg ... out FC timing */ 1052503f7baSArnd Bergmann ktime_t ts_rx; 1062503f7baSArnd Bergmann ktime_t ts_out_fc; 1072503f7baSArnd Bergmann ktime_t ts_max_fc_delay; 1083703f53bSSrinivas Pandruvada void *client_data; 1093703f53bSSrinivas Pandruvada }; 1103703f53bSSrinivas Pandruvada 1113703f53bSSrinivas Pandruvada /* Client connection managenment internal functions */ 11214106501SAndy Shevchenko int ishtp_can_client_connect(struct ishtp_device *ishtp_dev, guid_t *uuid); 1133703f53bSSrinivas Pandruvada int ishtp_fw_cl_by_id(struct ishtp_device *dev, uint8_t client_id); 1143703f53bSSrinivas Pandruvada void ishtp_cl_send_msg(struct ishtp_device *dev, struct ishtp_cl *cl); 1153703f53bSSrinivas Pandruvada void recv_ishtp_cl_msg(struct ishtp_device *dev, 1163703f53bSSrinivas Pandruvada struct ishtp_msg_hdr *ishtp_hdr); 1173703f53bSSrinivas Pandruvada int ishtp_cl_read_start(struct ishtp_cl *cl); 1183703f53bSSrinivas Pandruvada 1193703f53bSSrinivas Pandruvada /* Ring Buffer I/F */ 1203703f53bSSrinivas Pandruvada int ishtp_cl_alloc_rx_ring(struct ishtp_cl *cl); 1213703f53bSSrinivas Pandruvada int ishtp_cl_alloc_tx_ring(struct ishtp_cl *cl); 1223703f53bSSrinivas Pandruvada void ishtp_cl_free_rx_ring(struct ishtp_cl *cl); 1233703f53bSSrinivas Pandruvada void ishtp_cl_free_tx_ring(struct ishtp_cl *cl); 12418c0b546SSrinivas Pandruvada int ishtp_cl_get_tx_free_buffer_size(struct ishtp_cl *cl); 12518c0b546SSrinivas Pandruvada int ishtp_cl_get_tx_free_rings(struct ishtp_cl *cl); 1263703f53bSSrinivas Pandruvada 1273703f53bSSrinivas Pandruvada /* DMA I/F functions */ 1283703f53bSSrinivas Pandruvada void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg, 1293703f53bSSrinivas Pandruvada struct dma_xfer_hbm *hbm); 1303703f53bSSrinivas Pandruvada void ishtp_cl_alloc_dma_buf(struct ishtp_device *dev); 1313703f53bSSrinivas Pandruvada void ishtp_cl_free_dma_buf(struct ishtp_device *dev); 1323703f53bSSrinivas Pandruvada void *ishtp_cl_get_dma_send_buf(struct ishtp_device *dev, 1333703f53bSSrinivas Pandruvada uint32_t size); 1343703f53bSSrinivas Pandruvada void ishtp_cl_release_dma_acked_mem(struct ishtp_device *dev, 1353703f53bSSrinivas Pandruvada void *msg_addr, 1363703f53bSSrinivas Pandruvada uint8_t size); 1373703f53bSSrinivas Pandruvada 1383703f53bSSrinivas Pandruvada /* Request blocks alloc/free I/F */ 1393703f53bSSrinivas Pandruvada struct ishtp_cl_rb *ishtp_io_rb_init(struct ishtp_cl *cl); 1403703f53bSSrinivas Pandruvada void ishtp_io_rb_free(struct ishtp_cl_rb *priv_rb); 1413703f53bSSrinivas Pandruvada int ishtp_io_rb_alloc_buf(struct ishtp_cl_rb *rb, size_t length); 1423703f53bSSrinivas Pandruvada 1433703f53bSSrinivas Pandruvada /** 1443703f53bSSrinivas Pandruvada * ishtp_cl_cmp_id - tells if file private data have same id 1453703f53bSSrinivas Pandruvada * returns true - if ids are the same and not NULL 1463703f53bSSrinivas Pandruvada */ 1473703f53bSSrinivas Pandruvada static inline bool ishtp_cl_cmp_id(const struct ishtp_cl *cl1, 1483703f53bSSrinivas Pandruvada const struct ishtp_cl *cl2) 1493703f53bSSrinivas Pandruvada { 1503703f53bSSrinivas Pandruvada return cl1 && cl2 && 1513703f53bSSrinivas Pandruvada (cl1->host_client_id == cl2->host_client_id) && 1523703f53bSSrinivas Pandruvada (cl1->fw_client_id == cl2->fw_client_id); 1533703f53bSSrinivas Pandruvada } 1543703f53bSSrinivas Pandruvada 1553703f53bSSrinivas Pandruvada #endif /* _ISHTP_CLIENT_H_ */ 156