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