1 #ifndef __COMMAND_H__
2 #define __COMMAND_H__
3
4 /* This file containes the slow-path send queue and the L2 Command code */
5 #include "57712_reg.h"
6 #include "577xx_int_offsets.h"
7 #include "context.h"
8 #include "lm5710.h"
9 //#include "5710_hsi.h"
10 //#define MAX_PROTO 2
11
12 /* How many slow-path-queue elements can be sent in parallel divided into normal and high priority */
13 #define MAX_NORMAL_PRIORITY_SPE 7
14 #define MAX_HIGH_PRIORITY_SPE 1
15 #define MAX_NUM_SPE 8
16
17 #define CMD_PRIORITY_NORMAL 0x10
18 #define CMD_PRIORITY_MEDIUM 0x20
19 #define CMD_PRIORITY_HIGH 0x30
20
21
22
23
24 /* structure representing a list of slow-path-completions */
25 typedef struct _sp_cqes_info {
26 union eth_rx_cqe sp_cqe[MAX_NUM_SPE];
27 u8_t idx;
28 } sp_cqes_info;
29
30
_lm_sq_post(struct _lm_device_t * pdev,struct sq_pending_command * pending)31 static __inline void _lm_sq_post(struct _lm_device_t *pdev,struct sq_pending_command * pending)
32 {
33 u32_t func = FUNC_ID(pdev);
34
35 /* TODO replace this with the proper struct */
36 /* CID needs port number to be encoded int it */
37 mm_memcpy(pdev->sq_info.sq_chain.prod_bd, &pending->command, sizeof(pending->command));
38
39 pdev->sq_info.sq_chain.prod_idx ++;
40 pdev->sq_info.sq_chain.bd_left --;
41
42 if (pdev->sq_info.sq_chain.prod_bd == pdev->sq_info.sq_chain.last_bd) {
43 pdev->sq_info.sq_chain.prod_bd = pdev->sq_info.sq_chain.sq_chain_virt;
44 }else{
45 pdev->sq_info.sq_chain.prod_bd ++ ;
46 }
47
48
49 DbgMessage(pdev,VERBOSEl2sp | VERBOSEl4sp, "Writing SP prod %d, conn_and_cmd_data=%x, type=%d \n",pdev->sq_info.sq_chain.prod_idx, pending->command.hdr.conn_and_cmd_data, pending->command.hdr.type);
50
51 if (IS_PFDEV(pdev) && pdev->sq_info.sq_state == SQ_STATE_NORMAL) {
52 LM_INTMEM_WRITE16(pdev, XSTORM_SPQ_PROD_OFFSET(func), pdev->sq_info.sq_chain.prod_idx, BAR_XSTRORM_INTMEM);
53 }
54 #ifdef VF_INVOLVED
55 else {
56 LM_INTMEM_WRITE16(PFDEV(pdev),XSTORM_VF_SPQ_PROD_OFFSET(ABS_VFID(pdev)), pdev->sq_info.sq_chain.prod_idx, BAR_XSTRORM_INTMEM);
57 }
58 #endif
59 }
60
61 /**
62 * @Description: This function fills a command that is received
63 * as a parameter given the input...
64 *
65 * @param pdev
66 * @param pending - OUT: this entry is filled given the input
67 * below
68 * @param cid
69 * @param command - FW Command ID
70 * @param type - The type of connection, can optionally
71 * include the function id as well if it differs
72 * from the function of pdev (for example for VFs)
73 *
74 * @param data - Data for FW ramrod
75 * @param release_mem_flag - Determines whether the sp pending
76 * command will be returned to the pool
77 * at the end of usage.
78 */
lm_sq_post_fill_entry(struct _lm_device_t * pdev,struct sq_pending_command * pending,u32_t cid,u8_t command,u16_t type,u64_t data,u8_t release_mem_flag)79 static __inline void lm_sq_post_fill_entry(struct _lm_device_t* pdev,
80 struct sq_pending_command * pending,
81 u32_t cid,
82 u8_t command,
83 u16_t type,
84 u64_t data,
85 u8_t release_mem_flag)
86 {
87 /* In some cases type may already contain the func-id (VF specifically) so we add it only if it's not there... */
88 if (!(type & SPE_HDR_T_FUNCTION_ID))
89 {
90 type |= (FUNC_ID(pdev) << SPE_HDR_T_FUNCTION_ID_SHIFT);
91 }
92
93 // CID MSB is function number
94 pending->command.hdr.conn_and_cmd_data = mm_cpu_to_le32((command << SPE_HDR_T_CMD_ID_SHIFT ) | HW_CID(pdev,cid));
95 pending->command.hdr.type = mm_cpu_to_le16(type);
96 pending->command.protocol_data.hi = mm_cpu_to_le32(U64_HI(data));
97 pending->command.protocol_data.lo = mm_cpu_to_le32(U64_LO(data));
98 pending->flags = 0;
99
100 if (release_mem_flag)
101 {
102 SET_FLAGS(pending->flags, SQ_PEND_RELEASE_MEM);
103 }
104
105 pending->cid = cid;
106 pending->type = type; /* don't kill function ID, RSC VF update really uses the value (& SPE_HDR_T_CONN_TYPE);*/
107 pending->cmd = command;
108
109 }
110
111 /**
112 * Description
113 * Add the entry to the pending SP list.
114 * Try to add entry's from the list to the sq_chain if possible.(there is are less then 8 ramrod commands pending)
115 *
116 * @param pdev
117 * @param pending - The pending list entry.
118 * @param priority - (high or low) to witch list to insert the pending list entry.
119 *
120 * @return lm_status_t: LM_STATUS_SUCCESS on success or
121 * LM_STATUS_REQUEST_NOT_ACCEPTED if slowpath queue is
122 * in blocked state.
123 */
124 lm_status_t lm_sq_post_entry(struct _lm_device_t * pdev,
125 struct sq_pending_command * pending,
126 u8_t priority);
127
128 /*
129 post a ramrod to the sq
130 takes the sq pending list spinlock and adds the request
131 will not block
132 but the actuall posting to the sq might be deffered until there is room
133 MUST only have one request pending per CID (this is up to the caller to enforce)
134 */
135 lm_status_t lm_sq_post(struct _lm_device_t *pdev,
136 u32_t cid,
137 u8_t command,
138 u8_t priority,
139 u16_t type,
140 u64_t data);
141
142 /**
143 * @Description
144 * inform the sq mechanism of completed ramrods because the
145 * completions arrive on the fast-path rings the fast-path
146 * needs to inform the sq that the ramrod has been serviced
147 * will not block, it also needs to notify which ramrod has
148 * been completed since completions can arrive in a different
149 * sequence than sent.
150 * @param pdev
151 * @param priority: priority of ramrod being completed
152 * (different credits)
153 * @param command: which command is completed
154 * @param type: connection type
155 * @param cid: connection id that ramrod was sent with
156 */
157 void lm_sq_complete(struct _lm_device_t *pdev, u8_t priority,
158 u8_t command, u16_t type, u32_t cid );
159
160 /**
161 * @description
162 * do any deffered posting pending on the sq, will take the list spinlock
163 * will not block. Check sq state, if its pending (it means no hw...) call flush
164 * at the end, which will take care of completing these completions internally.
165 * @param pdev
166 *
167 * @return lm_status_t SUCCESS: is no pending requests were sent. PENDING if a
168 * if pending request was sent.
169 */
170 lm_status_t lm_sq_post_pending(struct _lm_device_t *pdev);
171
172 /*
173 post a slow-path command
174 takes a spinlock, does not sleep
175 actuall command posting may be delayed
176 */
lm_command_post(struct _lm_device_t * pdev,u32_t cid,u8_t command,u8_t priority,u16_t type,u64_t data)177 static __inline lm_status_t lm_command_post( struct _lm_device_t* pdev,
178 u32_t cid,
179 u8_t command,
180 u8_t priority,
181 u16_t type,
182 u64_t data )
183 {
184 return lm_sq_post(pdev, cid, command, priority, type, data );
185 }
186
187
188 /* TODO: move functions above to lm_sp.c */
189 /**
190 * @Description
191 * change state of slowpath queue.
192 *
193 * @param pdev
194 * @param state NORMAL, PENDING, BLOCKED
195 */
196 void lm_sq_change_state(struct _lm_device_t *pdev, lm_sq_state_t state);
197
198 /**
199 * @Description
200 * This function completes any pending slowpath requests.
201 * It does this as if they were completed via cookie...
202 * It needs to know all the possible cookies and which
203 * completions to give. Any new ramrod should be added to
204 * this function. Also if it should be ignored.
205 *
206 * @param pdev
207 */
208 void lm_sq_complete_pending_requests(struct _lm_device_t *pdev);
209
210 /**
211 * @Description
212 * This function takes care of registering a DPC for
213 * completing slowpaths internally in the driver (if such
214 * exist)
215 * @param pdev
216 *
217 * @return lm_status_t SUCCESS: if all flushed (i.e. dpc not
218 * scheduled)
219 * PENDING: if dpc is scheduled
220 */
221 lm_status_t lm_sq_flush(struct _lm_device_t *pdev);
222
223 /**
224 * @Description
225 * Checks if the sq is empty
226 *
227 * @param pdev
228 *
229 * @return u8_t TRUE if empty FALSE o/w
230 */
231 u8_t lm_sq_is_empty(struct _lm_device_t *pdev);
232
233
234 lm_status_t lm_sq_comp_cb_register(struct _lm_device_t *pdev, u8_t type, lm_sq_comp_cb_t cb);
235
236 lm_status_t lm_sq_comp_cb_deregister(struct _lm_device_t *pdev, u8_t type);
237
238
239
240 #endif //__COMMAND_H__
241