13703f53bSSrinivas Pandruvada /* 23703f53bSSrinivas Pandruvada * ISHTP client logic 33703f53bSSrinivas Pandruvada * 43703f53bSSrinivas Pandruvada * Copyright (c) 2003-2016, Intel Corporation. 53703f53bSSrinivas Pandruvada * 63703f53bSSrinivas Pandruvada * This program is free software; you can redistribute it and/or modify it 73703f53bSSrinivas Pandruvada * under the terms and conditions of the GNU General Public License, 83703f53bSSrinivas Pandruvada * version 2, as published by the Free Software Foundation. 93703f53bSSrinivas Pandruvada * 103703f53bSSrinivas Pandruvada * This program is distributed in the hope it will be useful, but WITHOUT 113703f53bSSrinivas Pandruvada * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 123703f53bSSrinivas Pandruvada * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 133703f53bSSrinivas Pandruvada * more details. 143703f53bSSrinivas Pandruvada */ 153703f53bSSrinivas Pandruvada 163703f53bSSrinivas Pandruvada #ifndef _ISHTP_CLIENT_H_ 173703f53bSSrinivas Pandruvada #define _ISHTP_CLIENT_H_ 183703f53bSSrinivas Pandruvada 193703f53bSSrinivas Pandruvada #include <linux/types.h> 203703f53bSSrinivas Pandruvada #include "ishtp-dev.h" 213703f53bSSrinivas Pandruvada 223703f53bSSrinivas Pandruvada /* Client state */ 233703f53bSSrinivas Pandruvada enum cl_state { 243703f53bSSrinivas Pandruvada ISHTP_CL_INITIALIZING = 0, 253703f53bSSrinivas Pandruvada ISHTP_CL_CONNECTING, 263703f53bSSrinivas Pandruvada ISHTP_CL_CONNECTED, 273703f53bSSrinivas Pandruvada ISHTP_CL_DISCONNECTING, 283703f53bSSrinivas Pandruvada ISHTP_CL_DISCONNECTED 293703f53bSSrinivas Pandruvada }; 303703f53bSSrinivas Pandruvada 313703f53bSSrinivas Pandruvada /* Tx and Rx ring size */ 323703f53bSSrinivas Pandruvada #define CL_DEF_RX_RING_SIZE 2 333703f53bSSrinivas Pandruvada #define CL_DEF_TX_RING_SIZE 2 343703f53bSSrinivas Pandruvada #define CL_MAX_RX_RING_SIZE 32 353703f53bSSrinivas Pandruvada #define CL_MAX_TX_RING_SIZE 32 363703f53bSSrinivas Pandruvada 373703f53bSSrinivas Pandruvada #define DMA_SLOT_SIZE 4096 383703f53bSSrinivas Pandruvada /* Number of IPC fragments after which it's worth sending via DMA */ 393703f53bSSrinivas Pandruvada #define DMA_WORTH_THRESHOLD 3 403703f53bSSrinivas Pandruvada 413703f53bSSrinivas Pandruvada /* DMA/IPC Tx paths. Other the default means enforcement */ 423703f53bSSrinivas Pandruvada #define CL_TX_PATH_DEFAULT 0 433703f53bSSrinivas Pandruvada #define CL_TX_PATH_IPC 1 443703f53bSSrinivas Pandruvada #define CL_TX_PATH_DMA 2 453703f53bSSrinivas Pandruvada 463703f53bSSrinivas Pandruvada /* Client Tx buffer list entry */ 473703f53bSSrinivas Pandruvada struct ishtp_cl_tx_ring { 483703f53bSSrinivas Pandruvada struct list_head list; 493703f53bSSrinivas Pandruvada struct ishtp_msg_data send_buf; 503703f53bSSrinivas Pandruvada }; 513703f53bSSrinivas Pandruvada 523703f53bSSrinivas Pandruvada /* ISHTP client instance */ 533703f53bSSrinivas Pandruvada struct ishtp_cl { 543703f53bSSrinivas Pandruvada struct list_head link; 553703f53bSSrinivas Pandruvada struct ishtp_device *dev; 563703f53bSSrinivas Pandruvada enum cl_state state; 573703f53bSSrinivas Pandruvada int status; 583703f53bSSrinivas Pandruvada 593703f53bSSrinivas Pandruvada /* Link to ISHTP bus device */ 603703f53bSSrinivas Pandruvada struct ishtp_cl_device *device; 613703f53bSSrinivas Pandruvada 623703f53bSSrinivas Pandruvada /* ID of client connected */ 633703f53bSSrinivas Pandruvada uint8_t host_client_id; 643703f53bSSrinivas Pandruvada uint8_t fw_client_id; 653703f53bSSrinivas Pandruvada uint8_t ishtp_flow_ctrl_creds; 663703f53bSSrinivas Pandruvada uint8_t out_flow_ctrl_creds; 673703f53bSSrinivas Pandruvada 683703f53bSSrinivas Pandruvada /* dma */ 693703f53bSSrinivas Pandruvada int last_tx_path; 703703f53bSSrinivas Pandruvada /* 0: ack wasn't received,1:ack was received */ 713703f53bSSrinivas Pandruvada int last_dma_acked; 723703f53bSSrinivas Pandruvada unsigned char *last_dma_addr; 733703f53bSSrinivas Pandruvada /* 0: ack wasn't received,1:ack was received */ 743703f53bSSrinivas Pandruvada int last_ipc_acked; 753703f53bSSrinivas Pandruvada 763703f53bSSrinivas Pandruvada /* Rx ring buffer pool */ 773703f53bSSrinivas Pandruvada unsigned int rx_ring_size; 783703f53bSSrinivas Pandruvada struct ishtp_cl_rb free_rb_list; 793703f53bSSrinivas Pandruvada spinlock_t free_list_spinlock; 803703f53bSSrinivas Pandruvada /* Rx in-process list */ 813703f53bSSrinivas Pandruvada struct ishtp_cl_rb in_process_list; 823703f53bSSrinivas Pandruvada spinlock_t in_process_spinlock; 833703f53bSSrinivas Pandruvada 843703f53bSSrinivas Pandruvada /* Client Tx buffers list */ 853703f53bSSrinivas Pandruvada unsigned int tx_ring_size; 863703f53bSSrinivas Pandruvada struct ishtp_cl_tx_ring tx_list, tx_free_list; 8718c0b546SSrinivas Pandruvada int tx_ring_free_size; 883703f53bSSrinivas Pandruvada spinlock_t tx_list_spinlock; 893703f53bSSrinivas Pandruvada spinlock_t tx_free_list_spinlock; 903703f53bSSrinivas Pandruvada size_t tx_offs; /* Offset in buffer at head of 'tx_list' */ 913703f53bSSrinivas Pandruvada 923703f53bSSrinivas Pandruvada /** 933703f53bSSrinivas Pandruvada * if we get a FC, and the list is not empty, we must know whether we 943703f53bSSrinivas Pandruvada * are at the middle of sending. 953703f53bSSrinivas Pandruvada * if so -need to increase FC counter, otherwise, need to start sending 963703f53bSSrinivas Pandruvada * the first msg in list 973703f53bSSrinivas Pandruvada * (!)This is for counting-FC implementation only. Within single-FC the 983703f53bSSrinivas Pandruvada * other party may NOT send FC until it receives complete message 993703f53bSSrinivas Pandruvada */ 1003703f53bSSrinivas Pandruvada int sending; 1013703f53bSSrinivas Pandruvada 1023703f53bSSrinivas Pandruvada /* Send FC spinlock */ 1033703f53bSSrinivas Pandruvada spinlock_t fc_spinlock; 1043703f53bSSrinivas Pandruvada 1053703f53bSSrinivas Pandruvada /* wait queue for connect and disconnect response from FW */ 1063703f53bSSrinivas Pandruvada wait_queue_head_t wait_ctrl_res; 1073703f53bSSrinivas Pandruvada 1083703f53bSSrinivas Pandruvada /* Error stats */ 1093703f53bSSrinivas Pandruvada unsigned int err_send_msg; 1103703f53bSSrinivas Pandruvada unsigned int err_send_fc; 1113703f53bSSrinivas Pandruvada 1123703f53bSSrinivas Pandruvada /* Send/recv stats */ 1133703f53bSSrinivas Pandruvada unsigned int send_msg_cnt_ipc; 1143703f53bSSrinivas Pandruvada unsigned int send_msg_cnt_dma; 1153703f53bSSrinivas Pandruvada unsigned int recv_msg_cnt_ipc; 1163703f53bSSrinivas Pandruvada unsigned int recv_msg_cnt_dma; 1173703f53bSSrinivas Pandruvada unsigned int recv_msg_num_frags; 1183703f53bSSrinivas Pandruvada unsigned int ishtp_flow_ctrl_cnt; 1193703f53bSSrinivas Pandruvada unsigned int out_flow_ctrl_cnt; 1203703f53bSSrinivas Pandruvada 1213703f53bSSrinivas Pandruvada /* Rx msg ... out FC timing */ 1222503f7baSArnd Bergmann ktime_t ts_rx; 1232503f7baSArnd Bergmann ktime_t ts_out_fc; 1242503f7baSArnd Bergmann ktime_t ts_max_fc_delay; 1253703f53bSSrinivas Pandruvada void *client_data; 1263703f53bSSrinivas Pandruvada }; 1273703f53bSSrinivas Pandruvada 1283703f53bSSrinivas Pandruvada /* Client connection managenment internal functions */ 1293703f53bSSrinivas Pandruvada int ishtp_can_client_connect(struct ishtp_device *ishtp_dev, uuid_le *uuid); 1303703f53bSSrinivas Pandruvada int ishtp_fw_cl_by_id(struct ishtp_device *dev, uint8_t client_id); 1313703f53bSSrinivas Pandruvada void ishtp_cl_send_msg(struct ishtp_device *dev, struct ishtp_cl *cl); 1323703f53bSSrinivas Pandruvada void recv_ishtp_cl_msg(struct ishtp_device *dev, 1333703f53bSSrinivas Pandruvada struct ishtp_msg_hdr *ishtp_hdr); 1343703f53bSSrinivas Pandruvada int ishtp_cl_read_start(struct ishtp_cl *cl); 1353703f53bSSrinivas Pandruvada 1363703f53bSSrinivas Pandruvada /* Ring Buffer I/F */ 1373703f53bSSrinivas Pandruvada int ishtp_cl_alloc_rx_ring(struct ishtp_cl *cl); 1383703f53bSSrinivas Pandruvada int ishtp_cl_alloc_tx_ring(struct ishtp_cl *cl); 1393703f53bSSrinivas Pandruvada void ishtp_cl_free_rx_ring(struct ishtp_cl *cl); 1403703f53bSSrinivas Pandruvada void ishtp_cl_free_tx_ring(struct ishtp_cl *cl); 14118c0b546SSrinivas Pandruvada int ishtp_cl_get_tx_free_buffer_size(struct ishtp_cl *cl); 14218c0b546SSrinivas Pandruvada int ishtp_cl_get_tx_free_rings(struct ishtp_cl *cl); 1433703f53bSSrinivas Pandruvada 1443703f53bSSrinivas Pandruvada /* DMA I/F functions */ 1453703f53bSSrinivas Pandruvada void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg, 1463703f53bSSrinivas Pandruvada struct dma_xfer_hbm *hbm); 1473703f53bSSrinivas Pandruvada void ishtp_cl_alloc_dma_buf(struct ishtp_device *dev); 1483703f53bSSrinivas Pandruvada void ishtp_cl_free_dma_buf(struct ishtp_device *dev); 1493703f53bSSrinivas Pandruvada void *ishtp_cl_get_dma_send_buf(struct ishtp_device *dev, 1503703f53bSSrinivas Pandruvada uint32_t size); 1513703f53bSSrinivas Pandruvada void ishtp_cl_release_dma_acked_mem(struct ishtp_device *dev, 1523703f53bSSrinivas Pandruvada void *msg_addr, 1533703f53bSSrinivas Pandruvada uint8_t size); 1543703f53bSSrinivas Pandruvada 1553703f53bSSrinivas Pandruvada /* Request blocks alloc/free I/F */ 1563703f53bSSrinivas Pandruvada struct ishtp_cl_rb *ishtp_io_rb_init(struct ishtp_cl *cl); 1573703f53bSSrinivas Pandruvada void ishtp_io_rb_free(struct ishtp_cl_rb *priv_rb); 1583703f53bSSrinivas Pandruvada int ishtp_io_rb_alloc_buf(struct ishtp_cl_rb *rb, size_t length); 1593703f53bSSrinivas Pandruvada 1603703f53bSSrinivas Pandruvada /** 1613703f53bSSrinivas Pandruvada * ishtp_cl_cmp_id - tells if file private data have same id 1623703f53bSSrinivas Pandruvada * returns true - if ids are the same and not NULL 1633703f53bSSrinivas Pandruvada */ 1643703f53bSSrinivas Pandruvada static inline bool ishtp_cl_cmp_id(const struct ishtp_cl *cl1, 1653703f53bSSrinivas Pandruvada const struct ishtp_cl *cl2) 1663703f53bSSrinivas Pandruvada { 1673703f53bSSrinivas Pandruvada return cl1 && cl2 && 1683703f53bSSrinivas Pandruvada (cl1->host_client_id == cl2->host_client_id) && 1693703f53bSSrinivas Pandruvada (cl1->fw_client_id == cl2->fw_client_id); 1703703f53bSSrinivas Pandruvada } 1713703f53bSSrinivas Pandruvada 1723703f53bSSrinivas Pandruvada /* exported functions from ISHTP under client management scope */ 1733703f53bSSrinivas Pandruvada struct ishtp_cl *ishtp_cl_allocate(struct ishtp_device *dev); 1743703f53bSSrinivas Pandruvada void ishtp_cl_free(struct ishtp_cl *cl); 1753703f53bSSrinivas Pandruvada int ishtp_cl_link(struct ishtp_cl *cl, int id); 1763703f53bSSrinivas Pandruvada void ishtp_cl_unlink(struct ishtp_cl *cl); 1773703f53bSSrinivas Pandruvada int ishtp_cl_disconnect(struct ishtp_cl *cl); 1783703f53bSSrinivas Pandruvada int ishtp_cl_connect(struct ishtp_cl *cl); 1793703f53bSSrinivas Pandruvada int ishtp_cl_send(struct ishtp_cl *cl, uint8_t *buf, size_t length); 1803703f53bSSrinivas Pandruvada int ishtp_cl_flush_queues(struct ishtp_cl *cl); 1813703f53bSSrinivas Pandruvada 1823703f53bSSrinivas Pandruvada /* exported functions from ISHTP client buffer management scope */ 1833703f53bSSrinivas Pandruvada int ishtp_cl_io_rb_recycle(struct ishtp_cl_rb *rb); 184a1c40ce6SEven Xu bool ishtp_cl_tx_empty(struct ishtp_cl *cl); 185a1c40ce6SEven Xu struct ishtp_cl_rb *ishtp_cl_rx_get_rb(struct ishtp_cl *cl); 1863703f53bSSrinivas Pandruvada 1873703f53bSSrinivas Pandruvada #endif /* _ISHTP_CLIENT_H_ */ 188