1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright(c) 2007 - 2018 Intel Corporation. */ |
3 | |
4 | #include "e1000_mbx.h" |
5 | |
6 | /** |
7 | * igb_read_mbx - Reads a message from the mailbox |
8 | * @hw: pointer to the HW structure |
9 | * @msg: The message buffer |
10 | * @size: Length of buffer |
11 | * @mbx_id: id of mailbox to read |
12 | * @unlock: skip locking or not |
13 | * |
14 | * returns SUCCESS if it successfully read message from buffer |
15 | **/ |
16 | s32 igb_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id, |
17 | bool unlock) |
18 | { |
19 | struct e1000_mbx_info *mbx = &hw->mbx; |
20 | s32 ret_val = -E1000_ERR_MBX; |
21 | |
22 | /* limit read to size of mailbox */ |
23 | if (size > mbx->size) |
24 | size = mbx->size; |
25 | |
26 | if (mbx->ops.read) |
27 | ret_val = mbx->ops.read(hw, msg, size, mbx_id, unlock); |
28 | |
29 | return ret_val; |
30 | } |
31 | |
32 | /** |
33 | * igb_write_mbx - Write a message to the mailbox |
34 | * @hw: pointer to the HW structure |
35 | * @msg: The message buffer |
36 | * @size: Length of buffer |
37 | * @mbx_id: id of mailbox to write |
38 | * |
39 | * returns SUCCESS if it successfully copied message into the buffer |
40 | **/ |
41 | s32 igb_write_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) |
42 | { |
43 | struct e1000_mbx_info *mbx = &hw->mbx; |
44 | s32 ret_val = 0; |
45 | |
46 | if (size > mbx->size) |
47 | ret_val = -E1000_ERR_MBX; |
48 | |
49 | else if (mbx->ops.write) |
50 | ret_val = mbx->ops.write(hw, msg, size, mbx_id); |
51 | |
52 | return ret_val; |
53 | } |
54 | |
55 | /** |
56 | * igb_check_for_msg - checks to see if someone sent us mail |
57 | * @hw: pointer to the HW structure |
58 | * @mbx_id: id of mailbox to check |
59 | * |
60 | * returns SUCCESS if the Status bit was found or else ERR_MBX |
61 | **/ |
62 | s32 igb_check_for_msg(struct e1000_hw *hw, u16 mbx_id) |
63 | { |
64 | struct e1000_mbx_info *mbx = &hw->mbx; |
65 | s32 ret_val = -E1000_ERR_MBX; |
66 | |
67 | if (mbx->ops.check_for_msg) |
68 | ret_val = mbx->ops.check_for_msg(hw, mbx_id); |
69 | |
70 | return ret_val; |
71 | } |
72 | |
73 | /** |
74 | * igb_check_for_ack - checks to see if someone sent us ACK |
75 | * @hw: pointer to the HW structure |
76 | * @mbx_id: id of mailbox to check |
77 | * |
78 | * returns SUCCESS if the Status bit was found or else ERR_MBX |
79 | **/ |
80 | s32 igb_check_for_ack(struct e1000_hw *hw, u16 mbx_id) |
81 | { |
82 | struct e1000_mbx_info *mbx = &hw->mbx; |
83 | s32 ret_val = -E1000_ERR_MBX; |
84 | |
85 | if (mbx->ops.check_for_ack) |
86 | ret_val = mbx->ops.check_for_ack(hw, mbx_id); |
87 | |
88 | return ret_val; |
89 | } |
90 | |
91 | /** |
92 | * igb_check_for_rst - checks to see if other side has reset |
93 | * @hw: pointer to the HW structure |
94 | * @mbx_id: id of mailbox to check |
95 | * |
96 | * returns SUCCESS if the Status bit was found or else ERR_MBX |
97 | **/ |
98 | s32 igb_check_for_rst(struct e1000_hw *hw, u16 mbx_id) |
99 | { |
100 | struct e1000_mbx_info *mbx = &hw->mbx; |
101 | s32 ret_val = -E1000_ERR_MBX; |
102 | |
103 | if (mbx->ops.check_for_rst) |
104 | ret_val = mbx->ops.check_for_rst(hw, mbx_id); |
105 | |
106 | return ret_val; |
107 | } |
108 | |
109 | /** |
110 | * igb_unlock_mbx - unlock the mailbox |
111 | * @hw: pointer to the HW structure |
112 | * @mbx_id: id of mailbox to check |
113 | * |
114 | * returns SUCCESS if the mailbox was unlocked or else ERR_MBX |
115 | **/ |
116 | s32 igb_unlock_mbx(struct e1000_hw *hw, u16 mbx_id) |
117 | { |
118 | struct e1000_mbx_info *mbx = &hw->mbx; |
119 | s32 ret_val = -E1000_ERR_MBX; |
120 | |
121 | if (mbx->ops.unlock) |
122 | ret_val = mbx->ops.unlock(hw, mbx_id); |
123 | |
124 | return ret_val; |
125 | } |
126 | |
127 | /** |
128 | * igb_poll_for_msg - Wait for message notification |
129 | * @hw: pointer to the HW structure |
130 | * @mbx_id: id of mailbox to write |
131 | * |
132 | * returns SUCCESS if it successfully received a message notification |
133 | **/ |
134 | static s32 igb_poll_for_msg(struct e1000_hw *hw, u16 mbx_id) |
135 | { |
136 | struct e1000_mbx_info *mbx = &hw->mbx; |
137 | int countdown = mbx->timeout; |
138 | |
139 | if (!countdown || !mbx->ops.check_for_msg) |
140 | goto out; |
141 | |
142 | while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) { |
143 | countdown--; |
144 | if (!countdown) |
145 | break; |
146 | udelay(mbx->usec_delay); |
147 | } |
148 | |
149 | /* if we failed, all future posted messages fail until reset */ |
150 | if (!countdown) |
151 | mbx->timeout = 0; |
152 | out: |
153 | return countdown ? 0 : -E1000_ERR_MBX; |
154 | } |
155 | |
156 | /** |
157 | * igb_poll_for_ack - Wait for message acknowledgement |
158 | * @hw: pointer to the HW structure |
159 | * @mbx_id: id of mailbox to write |
160 | * |
161 | * returns SUCCESS if it successfully received a message acknowledgement |
162 | **/ |
163 | static s32 igb_poll_for_ack(struct e1000_hw *hw, u16 mbx_id) |
164 | { |
165 | struct e1000_mbx_info *mbx = &hw->mbx; |
166 | int countdown = mbx->timeout; |
167 | |
168 | if (!countdown || !mbx->ops.check_for_ack) |
169 | goto out; |
170 | |
171 | while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) { |
172 | countdown--; |
173 | if (!countdown) |
174 | break; |
175 | udelay(mbx->usec_delay); |
176 | } |
177 | |
178 | /* if we failed, all future posted messages fail until reset */ |
179 | if (!countdown) |
180 | mbx->timeout = 0; |
181 | out: |
182 | return countdown ? 0 : -E1000_ERR_MBX; |
183 | } |
184 | |
185 | /** |
186 | * igb_read_posted_mbx - Wait for message notification and receive message |
187 | * @hw: pointer to the HW structure |
188 | * @msg: The message buffer |
189 | * @size: Length of buffer |
190 | * @mbx_id: id of mailbox to write |
191 | * |
192 | * returns SUCCESS if it successfully received a message notification and |
193 | * copied it into the receive buffer. |
194 | **/ |
195 | static s32 igb_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, |
196 | u16 mbx_id) |
197 | { |
198 | struct e1000_mbx_info *mbx = &hw->mbx; |
199 | s32 ret_val = -E1000_ERR_MBX; |
200 | |
201 | if (!mbx->ops.read) |
202 | goto out; |
203 | |
204 | ret_val = igb_poll_for_msg(hw, mbx_id); |
205 | |
206 | if (!ret_val) |
207 | ret_val = mbx->ops.read(hw, msg, size, mbx_id, true); |
208 | out: |
209 | return ret_val; |
210 | } |
211 | |
212 | /** |
213 | * igb_write_posted_mbx - Write a message to the mailbox, wait for ack |
214 | * @hw: pointer to the HW structure |
215 | * @msg: The message buffer |
216 | * @size: Length of buffer |
217 | * @mbx_id: id of mailbox to write |
218 | * |
219 | * returns SUCCESS if it successfully copied message into the buffer and |
220 | * received an ack to that message within delay * timeout period |
221 | **/ |
222 | static s32 igb_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, |
223 | u16 mbx_id) |
224 | { |
225 | struct e1000_mbx_info *mbx = &hw->mbx; |
226 | s32 ret_val = -E1000_ERR_MBX; |
227 | |
228 | /* exit if either we can't write or there isn't a defined timeout */ |
229 | if (!mbx->ops.write || !mbx->timeout) |
230 | goto out; |
231 | |
232 | /* send msg */ |
233 | ret_val = mbx->ops.write(hw, msg, size, mbx_id); |
234 | |
235 | /* if msg sent wait until we receive an ack */ |
236 | if (!ret_val) |
237 | ret_val = igb_poll_for_ack(hw, mbx_id); |
238 | out: |
239 | return ret_val; |
240 | } |
241 | |
242 | static s32 igb_check_for_bit_pf(struct e1000_hw *hw, u32 mask) |
243 | { |
244 | u32 mbvficr = rd32(E1000_MBVFICR); |
245 | s32 ret_val = -E1000_ERR_MBX; |
246 | |
247 | if (mbvficr & mask) { |
248 | ret_val = 0; |
249 | wr32(E1000_MBVFICR, mask); |
250 | } |
251 | |
252 | return ret_val; |
253 | } |
254 | |
255 | /** |
256 | * igb_check_for_msg_pf - checks to see if the VF has sent mail |
257 | * @hw: pointer to the HW structure |
258 | * @vf_number: the VF index |
259 | * |
260 | * returns SUCCESS if the VF has set the Status bit or else ERR_MBX |
261 | **/ |
262 | static s32 igb_check_for_msg_pf(struct e1000_hw *hw, u16 vf_number) |
263 | { |
264 | s32 ret_val = -E1000_ERR_MBX; |
265 | |
266 | if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFREQ_VF1 << vf_number)) { |
267 | ret_val = 0; |
268 | hw->mbx.stats.reqs++; |
269 | } |
270 | |
271 | return ret_val; |
272 | } |
273 | |
274 | /** |
275 | * igb_check_for_ack_pf - checks to see if the VF has ACKed |
276 | * @hw: pointer to the HW structure |
277 | * @vf_number: the VF index |
278 | * |
279 | * returns SUCCESS if the VF has set the Status bit or else ERR_MBX |
280 | **/ |
281 | static s32 igb_check_for_ack_pf(struct e1000_hw *hw, u16 vf_number) |
282 | { |
283 | s32 ret_val = -E1000_ERR_MBX; |
284 | |
285 | if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFACK_VF1 << vf_number)) { |
286 | ret_val = 0; |
287 | hw->mbx.stats.acks++; |
288 | } |
289 | |
290 | return ret_val; |
291 | } |
292 | |
293 | /** |
294 | * igb_check_for_rst_pf - checks to see if the VF has reset |
295 | * @hw: pointer to the HW structure |
296 | * @vf_number: the VF index |
297 | * |
298 | * returns SUCCESS if the VF has set the Status bit or else ERR_MBX |
299 | **/ |
300 | static s32 igb_check_for_rst_pf(struct e1000_hw *hw, u16 vf_number) |
301 | { |
302 | u32 vflre = rd32(E1000_VFLRE); |
303 | s32 ret_val = -E1000_ERR_MBX; |
304 | |
305 | if (vflre & BIT(vf_number)) { |
306 | ret_val = 0; |
307 | wr32(E1000_VFLRE, BIT(vf_number)); |
308 | hw->mbx.stats.rsts++; |
309 | } |
310 | |
311 | return ret_val; |
312 | } |
313 | |
314 | /** |
315 | * igb_obtain_mbx_lock_pf - obtain mailbox lock |
316 | * @hw: pointer to the HW structure |
317 | * @vf_number: the VF index |
318 | * |
319 | * return SUCCESS if we obtained the mailbox lock |
320 | **/ |
321 | static s32 igb_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number) |
322 | { |
323 | s32 ret_val = -E1000_ERR_MBX; |
324 | u32 p2v_mailbox; |
325 | int count = 10; |
326 | |
327 | do { |
328 | /* Take ownership of the buffer */ |
329 | wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU); |
330 | |
331 | /* reserve mailbox for vf use */ |
332 | p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number)); |
333 | if (p2v_mailbox & E1000_P2VMAILBOX_PFU) { |
334 | ret_val = 0; |
335 | break; |
336 | } |
337 | udelay(1000); |
338 | } while (count-- > 0); |
339 | |
340 | return ret_val; |
341 | } |
342 | |
343 | /** |
344 | * igb_release_mbx_lock_pf - release mailbox lock |
345 | * @hw: pointer to the HW structure |
346 | * @vf_number: the VF index |
347 | * |
348 | * return SUCCESS if we released the mailbox lock |
349 | **/ |
350 | static s32 igb_release_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number) |
351 | { |
352 | u32 p2v_mailbox; |
353 | |
354 | /* drop PF lock of mailbox, if set */ |
355 | p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number)); |
356 | if (p2v_mailbox & E1000_P2VMAILBOX_PFU) |
357 | wr32(E1000_P2VMAILBOX(vf_number), |
358 | p2v_mailbox & ~E1000_P2VMAILBOX_PFU); |
359 | |
360 | return 0; |
361 | } |
362 | |
363 | /** |
364 | * igb_write_mbx_pf - Places a message in the mailbox |
365 | * @hw: pointer to the HW structure |
366 | * @msg: The message buffer |
367 | * @size: Length of buffer |
368 | * @vf_number: the VF index |
369 | * |
370 | * returns SUCCESS if it successfully copied message into the buffer |
371 | **/ |
372 | static s32 igb_write_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, |
373 | u16 vf_number) |
374 | { |
375 | s32 ret_val; |
376 | u16 i; |
377 | |
378 | /* lock the mailbox to prevent pf/vf race condition */ |
379 | ret_val = igb_obtain_mbx_lock_pf(hw, vf_number); |
380 | if (ret_val) |
381 | goto out_no_write; |
382 | |
383 | /* flush msg and acks as we are overwriting the message buffer */ |
384 | igb_check_for_msg_pf(hw, vf_number); |
385 | igb_check_for_ack_pf(hw, vf_number); |
386 | |
387 | /* copy the caller specified message to the mailbox memory buffer */ |
388 | for (i = 0; i < size; i++) |
389 | array_wr32(E1000_VMBMEM(vf_number), i, msg[i]); |
390 | |
391 | /* Interrupt VF to tell it a message has been sent and release buffer*/ |
392 | wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_STS); |
393 | |
394 | /* update stats */ |
395 | hw->mbx.stats.msgs_tx++; |
396 | |
397 | out_no_write: |
398 | return ret_val; |
399 | |
400 | } |
401 | |
402 | /** |
403 | * igb_read_mbx_pf - Read a message from the mailbox |
404 | * @hw: pointer to the HW structure |
405 | * @msg: The message buffer |
406 | * @size: Length of buffer |
407 | * @vf_number: the VF index |
408 | * @unlock: unlock the mailbox when done? |
409 | * |
410 | * This function copies a message from the mailbox buffer to the caller's |
411 | * memory buffer. The presumption is that the caller knows that there was |
412 | * a message due to a VF request so no polling for message is needed. |
413 | **/ |
414 | static s32 igb_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, |
415 | u16 vf_number, bool unlock) |
416 | { |
417 | s32 ret_val; |
418 | u16 i; |
419 | |
420 | /* lock the mailbox to prevent pf/vf race condition */ |
421 | ret_val = igb_obtain_mbx_lock_pf(hw, vf_number); |
422 | if (ret_val) |
423 | goto out_no_read; |
424 | |
425 | /* copy the message to the mailbox memory buffer */ |
426 | for (i = 0; i < size; i++) |
427 | msg[i] = array_rd32(E1000_VMBMEM(vf_number), i); |
428 | |
429 | /* Acknowledge the message and release mailbox lock (or not) */ |
430 | if (unlock) |
431 | wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_ACK); |
432 | else |
433 | wr32(E1000_P2VMAILBOX(vf_number), |
434 | E1000_P2VMAILBOX_ACK | E1000_P2VMAILBOX_PFU); |
435 | |
436 | /* update stats */ |
437 | hw->mbx.stats.msgs_rx++; |
438 | |
439 | out_no_read: |
440 | return ret_val; |
441 | } |
442 | |
443 | /** |
444 | * igb_init_mbx_params_pf - set initial values for pf mailbox |
445 | * @hw: pointer to the HW structure |
446 | * |
447 | * Initializes the hw->mbx struct to correct values for pf mailbox |
448 | */ |
449 | s32 igb_init_mbx_params_pf(struct e1000_hw *hw) |
450 | { |
451 | struct e1000_mbx_info *mbx = &hw->mbx; |
452 | |
453 | mbx->timeout = 0; |
454 | mbx->usec_delay = 0; |
455 | |
456 | mbx->size = E1000_VFMAILBOX_SIZE; |
457 | |
458 | mbx->ops.read = igb_read_mbx_pf; |
459 | mbx->ops.write = igb_write_mbx_pf; |
460 | mbx->ops.read_posted = igb_read_posted_mbx; |
461 | mbx->ops.write_posted = igb_write_posted_mbx; |
462 | mbx->ops.check_for_msg = igb_check_for_msg_pf; |
463 | mbx->ops.check_for_ack = igb_check_for_ack_pf; |
464 | mbx->ops.check_for_rst = igb_check_for_rst_pf; |
465 | mbx->ops.unlock = igb_release_mbx_lock_pf; |
466 | |
467 | mbx->stats.msgs_tx = 0; |
468 | mbx->stats.msgs_rx = 0; |
469 | mbx->stats.reqs = 0; |
470 | mbx->stats.acks = 0; |
471 | mbx->stats.rsts = 0; |
472 | |
473 | return 0; |
474 | } |
475 | |
476 | |