1 /*
2  * Huawei HiNIC PCI Express Linux driver
3  * Copyright(c) 2017 Huawei Technologies Co., Ltd
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * for more details.
13  *
14  */
15 
16 #ifndef HINIC_HW_WQ_H
17 #define HINIC_HW_WQ_H
18 
19 #include <linux/types.h>
20 #include <linux/semaphore.h>
21 #include <linux/atomic.h>
22 
23 #include "hinic_hw_if.h"
24 #include "hinic_hw_wqe.h"
25 
26 struct hinic_free_block {
27 	int     page_idx;
28 	int     block_idx;
29 };
30 
31 struct hinic_wq {
32 	struct hinic_hwif       *hwif;
33 
34 	int             page_idx;
35 	int             block_idx;
36 
37 	u16             wqebb_size;
38 	u16             wq_page_size;
39 	u16             q_depth;
40 	u16             max_wqe_size;
41 	u16             num_wqebbs_per_page;
42 
43 	/* The addresses are 64 bit in the HW */
44 	u64             block_paddr;
45 	void            **shadow_block_vaddr;
46 	u64             *block_vaddr;
47 
48 	int             num_q_pages;
49 	u8              *shadow_wqe;
50 	u16             *shadow_idx;
51 
52 	atomic_t        cons_idx;
53 	atomic_t        prod_idx;
54 	atomic_t        delta;
55 	u16             mask;
56 };
57 
58 struct hinic_wqs {
59 	struct hinic_hwif       *hwif;
60 	int                     num_pages;
61 
62 	/* The addresses are 64 bit in the HW */
63 	u64                     *page_paddr;
64 	u64                     **page_vaddr;
65 	void                    ***shadow_page_vaddr;
66 
67 	struct hinic_free_block *free_blocks;
68 	int                     alloc_blk_pos;
69 	int                     return_blk_pos;
70 	int                     num_free_blks;
71 
72 	/* Lock for getting a free block from the WQ set */
73 	struct semaphore        alloc_blocks_lock;
74 };
75 
76 struct hinic_cmdq_pages {
77 	/* The addresses are 64 bit in the HW */
78 	u64                     page_paddr;
79 	u64                     *page_vaddr;
80 	void                    **shadow_page_vaddr;
81 
82 	struct hinic_hwif       *hwif;
83 };
84 
85 int hinic_wqs_cmdq_alloc(struct hinic_cmdq_pages *cmdq_pages,
86 			 struct hinic_wq *wq, struct hinic_hwif *hwif,
87 			 int cmdq_blocks, u16 wqebb_size, u16 wq_page_size,
88 			 u16 q_depth, u16 max_wqe_size);
89 
90 void hinic_wqs_cmdq_free(struct hinic_cmdq_pages *cmdq_pages,
91 			 struct hinic_wq *wq, int cmdq_blocks);
92 
93 int hinic_wqs_alloc(struct hinic_wqs *wqs, int num_wqs,
94 		    struct hinic_hwif *hwif);
95 
96 void hinic_wqs_free(struct hinic_wqs *wqs);
97 
98 int hinic_wq_allocate(struct hinic_wqs *wqs, struct hinic_wq *wq,
99 		      u16 wqebb_size, u16 wq_page_size, u16 q_depth,
100 		      u16 max_wqe_size);
101 
102 void hinic_wq_free(struct hinic_wqs *wqs, struct hinic_wq *wq);
103 
104 struct hinic_hw_wqe *hinic_get_wqe(struct hinic_wq *wq, unsigned int wqe_size,
105 				   u16 *prod_idx);
106 
107 void hinic_put_wqe(struct hinic_wq *wq, unsigned int wqe_size);
108 
109 struct hinic_hw_wqe *hinic_read_wqe(struct hinic_wq *wq, unsigned int wqe_size,
110 				    u16 *cons_idx);
111 
112 struct hinic_hw_wqe *hinic_read_wqe_direct(struct hinic_wq *wq, u16 cons_idx);
113 
114 void hinic_write_wqe(struct hinic_wq *wq, struct hinic_hw_wqe *wqe,
115 		     unsigned int wqe_size);
116 
117 #endif
118