]>
Commit | Line | Data |
---|---|---|
10ca132c GR |
1 | /******************************************************************************* |
2 | ||
3 | Intel 10 Gigabit PCI Express Linux driver | |
37689010 | 4 | Copyright(c) 1999 - 2016 Intel Corporation. |
10ca132c GR |
5 | |
6 | This program is free software; you can redistribute it and/or modify it | |
7 | under the terms and conditions of the GNU General Public License, | |
8 | version 2, as published by the Free Software Foundation. | |
9 | ||
10 | This program is distributed in the hope it will be useful, but WITHOUT | |
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
12 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
13 | more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License along with | |
16 | this program; if not, write to the Free Software Foundation, Inc., | |
17 | 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | |
18 | ||
19 | The full GNU General Public License is included in this distribution in | |
20 | the file called "COPYING". | |
21 | ||
22 | Contact Information: | |
b89aae71 | 23 | Linux NICS <linux.nics@intel.com> |
10ca132c GR |
24 | e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> |
25 | Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | |
26 | ||
27 | *******************************************************************************/ | |
28 | ||
29 | #include <linux/pci.h> | |
30 | #include <linux/delay.h> | |
b12babd4 | 31 | #include "ixgbe.h" |
10ca132c GR |
32 | #include "ixgbe_mbx.h" |
33 | ||
34 | /** | |
35 | * ixgbe_read_mbx - Reads a message from the mailbox | |
36 | * @hw: pointer to the HW structure | |
37 | * @msg: The message buffer | |
38 | * @size: Length of buffer | |
39 | * @mbx_id: id of mailbox to read | |
40 | * | |
bfb9035c | 41 | * returns SUCCESS if it successfully read message from buffer |
10ca132c GR |
42 | **/ |
43 | s32 ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) | |
44 | { | |
45 | struct ixgbe_mbx_info *mbx = &hw->mbx; | |
10ca132c GR |
46 | |
47 | /* limit read to size of mailbox */ | |
48 | if (size > mbx->size) | |
49 | size = mbx->size; | |
50 | ||
37689010 | 51 | if (!mbx->ops) |
e90dd264 | 52 | return IXGBE_ERR_MBX; |
10ca132c | 53 | |
37689010 | 54 | return mbx->ops->read(hw, msg, size, mbx_id); |
10ca132c GR |
55 | } |
56 | ||
57 | /** | |
58 | * ixgbe_write_mbx - Write a message to the mailbox | |
59 | * @hw: pointer to the HW structure | |
60 | * @msg: The message buffer | |
61 | * @size: Length of buffer | |
62 | * @mbx_id: id of mailbox to write | |
63 | * | |
64 | * returns SUCCESS if it successfully copied message into the buffer | |
65 | **/ | |
66 | s32 ixgbe_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) | |
67 | { | |
68 | struct ixgbe_mbx_info *mbx = &hw->mbx; | |
10ca132c GR |
69 | |
70 | if (size > mbx->size) | |
4e86281b | 71 | return IXGBE_ERR_MBX; |
10ca132c | 72 | |
37689010 | 73 | if (!mbx->ops) |
4e86281b | 74 | return IXGBE_ERR_MBX; |
10ca132c | 75 | |
37689010 | 76 | return mbx->ops->write(hw, msg, size, mbx_id); |
10ca132c GR |
77 | } |
78 | ||
79 | /** | |
80 | * ixgbe_check_for_msg - checks to see if someone sent us mail | |
81 | * @hw: pointer to the HW structure | |
82 | * @mbx_id: id of mailbox to check | |
83 | * | |
84 | * returns SUCCESS if the Status bit was found or else ERR_MBX | |
85 | **/ | |
86 | s32 ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id) | |
87 | { | |
88 | struct ixgbe_mbx_info *mbx = &hw->mbx; | |
10ca132c | 89 | |
37689010 | 90 | if (!mbx->ops) |
e90dd264 | 91 | return IXGBE_ERR_MBX; |
10ca132c | 92 | |
37689010 | 93 | return mbx->ops->check_for_msg(hw, mbx_id); |
10ca132c GR |
94 | } |
95 | ||
96 | /** | |
97 | * ixgbe_check_for_ack - checks to see if someone sent us ACK | |
98 | * @hw: pointer to the HW structure | |
99 | * @mbx_id: id of mailbox to check | |
100 | * | |
101 | * returns SUCCESS if the Status bit was found or else ERR_MBX | |
102 | **/ | |
103 | s32 ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id) | |
104 | { | |
105 | struct ixgbe_mbx_info *mbx = &hw->mbx; | |
10ca132c | 106 | |
37689010 | 107 | if (!mbx->ops) |
e90dd264 | 108 | return IXGBE_ERR_MBX; |
10ca132c | 109 | |
37689010 | 110 | return mbx->ops->check_for_ack(hw, mbx_id); |
10ca132c GR |
111 | } |
112 | ||
113 | /** | |
114 | * ixgbe_check_for_rst - checks to see if other side has reset | |
115 | * @hw: pointer to the HW structure | |
116 | * @mbx_id: id of mailbox to check | |
117 | * | |
118 | * returns SUCCESS if the Status bit was found or else ERR_MBX | |
119 | **/ | |
120 | s32 ixgbe_check_for_rst(struct ixgbe_hw *hw, u16 mbx_id) | |
121 | { | |
122 | struct ixgbe_mbx_info *mbx = &hw->mbx; | |
10ca132c | 123 | |
37689010 | 124 | if (!mbx->ops) |
e90dd264 | 125 | return IXGBE_ERR_MBX; |
10ca132c | 126 | |
37689010 | 127 | return mbx->ops->check_for_rst(hw, mbx_id); |
10ca132c GR |
128 | } |
129 | ||
130 | /** | |
131 | * ixgbe_poll_for_msg - Wait for message notification | |
132 | * @hw: pointer to the HW structure | |
133 | * @mbx_id: id of mailbox to write | |
134 | * | |
135 | * returns SUCCESS if it successfully received a message notification | |
136 | **/ | |
137 | static s32 ixgbe_poll_for_msg(struct ixgbe_hw *hw, u16 mbx_id) | |
138 | { | |
139 | struct ixgbe_mbx_info *mbx = &hw->mbx; | |
140 | int countdown = mbx->timeout; | |
141 | ||
37689010 | 142 | if (!countdown || !mbx->ops) |
e90dd264 | 143 | return IXGBE_ERR_MBX; |
10ca132c | 144 | |
37689010 | 145 | while (mbx->ops->check_for_msg(hw, mbx_id)) { |
10ca132c GR |
146 | countdown--; |
147 | if (!countdown) | |
e90dd264 | 148 | return IXGBE_ERR_MBX; |
10ca132c GR |
149 | udelay(mbx->usec_delay); |
150 | } | |
151 | ||
e90dd264 | 152 | return 0; |
10ca132c GR |
153 | } |
154 | ||
155 | /** | |
156 | * ixgbe_poll_for_ack - Wait for message acknowledgement | |
157 | * @hw: pointer to the HW structure | |
158 | * @mbx_id: id of mailbox to write | |
159 | * | |
160 | * returns SUCCESS if it successfully received a message acknowledgement | |
161 | **/ | |
162 | static s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id) | |
163 | { | |
164 | struct ixgbe_mbx_info *mbx = &hw->mbx; | |
165 | int countdown = mbx->timeout; | |
166 | ||
37689010 | 167 | if (!countdown || !mbx->ops) |
e90dd264 | 168 | return IXGBE_ERR_MBX; |
10ca132c | 169 | |
37689010 | 170 | while (mbx->ops->check_for_ack(hw, mbx_id)) { |
10ca132c GR |
171 | countdown--; |
172 | if (!countdown) | |
e90dd264 | 173 | return IXGBE_ERR_MBX; |
10ca132c GR |
174 | udelay(mbx->usec_delay); |
175 | } | |
176 | ||
e90dd264 | 177 | return 0; |
10ca132c GR |
178 | } |
179 | ||
180 | /** | |
181 | * ixgbe_read_posted_mbx - Wait for message notification and receive message | |
182 | * @hw: pointer to the HW structure | |
183 | * @msg: The message buffer | |
184 | * @size: Length of buffer | |
185 | * @mbx_id: id of mailbox to write | |
186 | * | |
187 | * returns SUCCESS if it successfully received a message notification and | |
188 | * copied it into the receive buffer. | |
189 | **/ | |
5d5b7c39 ET |
190 | static s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, |
191 | u16 mbx_id) | |
10ca132c GR |
192 | { |
193 | struct ixgbe_mbx_info *mbx = &hw->mbx; | |
e90dd264 | 194 | s32 ret_val; |
10ca132c | 195 | |
37689010 | 196 | if (!mbx->ops) |
e90dd264 | 197 | return IXGBE_ERR_MBX; |
10ca132c GR |
198 | |
199 | ret_val = ixgbe_poll_for_msg(hw, mbx_id); | |
e90dd264 MR |
200 | if (ret_val) |
201 | return ret_val; | |
10ca132c | 202 | |
e90dd264 | 203 | /* if ack received read message */ |
37689010 | 204 | return mbx->ops->read(hw, msg, size, mbx_id); |
10ca132c GR |
205 | } |
206 | ||
207 | /** | |
208 | * ixgbe_write_posted_mbx - Write a message to the mailbox, wait for ack | |
209 | * @hw: pointer to the HW structure | |
210 | * @msg: The message buffer | |
211 | * @size: Length of buffer | |
212 | * @mbx_id: id of mailbox to write | |
213 | * | |
214 | * returns SUCCESS if it successfully copied message into the buffer and | |
215 | * received an ack to that message within delay * timeout period | |
216 | **/ | |
5d5b7c39 | 217 | static s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, |
e7cf745b | 218 | u16 mbx_id) |
10ca132c GR |
219 | { |
220 | struct ixgbe_mbx_info *mbx = &hw->mbx; | |
e90dd264 | 221 | s32 ret_val; |
10ca132c GR |
222 | |
223 | /* exit if either we can't write or there isn't a defined timeout */ | |
37689010 | 224 | if (!mbx->ops || !mbx->timeout) |
e90dd264 | 225 | return IXGBE_ERR_MBX; |
10ca132c GR |
226 | |
227 | /* send msg */ | |
37689010 | 228 | ret_val = mbx->ops->write(hw, msg, size, mbx_id); |
e90dd264 MR |
229 | if (ret_val) |
230 | return ret_val; | |
10ca132c GR |
231 | |
232 | /* if msg sent wait until we receive an ack */ | |
e90dd264 | 233 | return ixgbe_poll_for_ack(hw, mbx_id); |
10ca132c GR |
234 | } |
235 | ||
10ca132c GR |
236 | static s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index) |
237 | { | |
238 | u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index)); | |
10ca132c GR |
239 | |
240 | if (mbvficr & mask) { | |
10ca132c | 241 | IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask); |
e90dd264 | 242 | return 0; |
10ca132c GR |
243 | } |
244 | ||
e90dd264 | 245 | return IXGBE_ERR_MBX; |
10ca132c GR |
246 | } |
247 | ||
248 | /** | |
249 | * ixgbe_check_for_msg_pf - checks to see if the VF has sent mail | |
250 | * @hw: pointer to the HW structure | |
251 | * @vf_number: the VF index | |
252 | * | |
253 | * returns SUCCESS if the VF has set the Status bit or else ERR_MBX | |
254 | **/ | |
255 | static s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number) | |
256 | { | |
10ca132c GR |
257 | s32 index = IXGBE_MBVFICR_INDEX(vf_number); |
258 | u32 vf_bit = vf_number % 16; | |
259 | ||
260 | if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFREQ_VF1 << vf_bit, | |
e7cf745b | 261 | index)) { |
10ca132c | 262 | hw->mbx.stats.reqs++; |
e90dd264 | 263 | return 0; |
10ca132c GR |
264 | } |
265 | ||
e90dd264 | 266 | return IXGBE_ERR_MBX; |
10ca132c GR |
267 | } |
268 | ||
269 | /** | |
270 | * ixgbe_check_for_ack_pf - checks to see if the VF has ACKed | |
271 | * @hw: pointer to the HW structure | |
272 | * @vf_number: the VF index | |
273 | * | |
274 | * returns SUCCESS if the VF has set the Status bit or else ERR_MBX | |
275 | **/ | |
276 | static s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number) | |
277 | { | |
10ca132c GR |
278 | s32 index = IXGBE_MBVFICR_INDEX(vf_number); |
279 | u32 vf_bit = vf_number % 16; | |
280 | ||
281 | if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFACK_VF1 << vf_bit, | |
e7cf745b | 282 | index)) { |
10ca132c | 283 | hw->mbx.stats.acks++; |
e90dd264 | 284 | return 0; |
10ca132c GR |
285 | } |
286 | ||
e90dd264 | 287 | return IXGBE_ERR_MBX; |
10ca132c GR |
288 | } |
289 | ||
290 | /** | |
291 | * ixgbe_check_for_rst_pf - checks to see if the VF has reset | |
292 | * @hw: pointer to the HW structure | |
293 | * @vf_number: the VF index | |
294 | * | |
295 | * returns SUCCESS if the VF has set the Status bit or else ERR_MBX | |
296 | **/ | |
297 | static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number) | |
298 | { | |
299 | u32 reg_offset = (vf_number < 32) ? 0 : 1; | |
300 | u32 vf_shift = vf_number % 32; | |
301 | u32 vflre = 0; | |
10ca132c | 302 | |
b93a2226 DS |
303 | switch (hw->mac.type) { |
304 | case ixgbe_mac_82599EB: | |
10ca132c | 305 | vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset)); |
b93a2226 | 306 | break; |
3377eba7 | 307 | case ixgbe_mac_X540: |
9a75a1ac DS |
308 | case ixgbe_mac_X550: |
309 | case ixgbe_mac_X550EM_x: | |
49425dfc | 310 | case ixgbe_mac_x550em_a: |
3377eba7 GR |
311 | vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset)); |
312 | break; | |
b93a2226 DS |
313 | default: |
314 | break; | |
315 | } | |
10ca132c GR |
316 | |
317 | if (vflre & (1 << vf_shift)) { | |
10ca132c GR |
318 | IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), (1 << vf_shift)); |
319 | hw->mbx.stats.rsts++; | |
e90dd264 | 320 | return 0; |
10ca132c GR |
321 | } |
322 | ||
e90dd264 | 323 | return IXGBE_ERR_MBX; |
10ca132c GR |
324 | } |
325 | ||
326 | /** | |
327 | * ixgbe_obtain_mbx_lock_pf - obtain mailbox lock | |
328 | * @hw: pointer to the HW structure | |
329 | * @vf_number: the VF index | |
330 | * | |
331 | * return SUCCESS if we obtained the mailbox lock | |
332 | **/ | |
333 | static s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number) | |
334 | { | |
10ca132c GR |
335 | u32 p2v_mailbox; |
336 | ||
337 | /* Take ownership of the buffer */ | |
338 | IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_PFU); | |
339 | ||
340 | /* reserve mailbox for vf use */ | |
341 | p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number)); | |
342 | if (p2v_mailbox & IXGBE_PFMAILBOX_PFU) | |
e90dd264 | 343 | return 0; |
10ca132c | 344 | |
e90dd264 | 345 | return IXGBE_ERR_MBX; |
10ca132c GR |
346 | } |
347 | ||
348 | /** | |
349 | * ixgbe_write_mbx_pf - Places a message in the mailbox | |
350 | * @hw: pointer to the HW structure | |
351 | * @msg: The message buffer | |
352 | * @size: Length of buffer | |
353 | * @vf_number: the VF index | |
354 | * | |
355 | * returns SUCCESS if it successfully copied message into the buffer | |
356 | **/ | |
357 | static s32 ixgbe_write_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size, | |
e7cf745b | 358 | u16 vf_number) |
10ca132c GR |
359 | { |
360 | s32 ret_val; | |
361 | u16 i; | |
362 | ||
363 | /* lock the mailbox to prevent pf/vf race condition */ | |
364 | ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number); | |
365 | if (ret_val) | |
e90dd264 | 366 | return ret_val; |
10ca132c GR |
367 | |
368 | /* flush msg and acks as we are overwriting the message buffer */ | |
369 | ixgbe_check_for_msg_pf(hw, vf_number); | |
370 | ixgbe_check_for_ack_pf(hw, vf_number); | |
371 | ||
372 | /* copy the caller specified message to the mailbox memory buffer */ | |
373 | for (i = 0; i < size; i++) | |
374 | IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, msg[i]); | |
375 | ||
376 | /* Interrupt VF to tell it a message has been sent and release buffer*/ | |
377 | IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_STS); | |
378 | ||
379 | /* update stats */ | |
380 | hw->mbx.stats.msgs_tx++; | |
381 | ||
e90dd264 | 382 | return 0; |
10ca132c GR |
383 | } |
384 | ||
385 | /** | |
386 | * ixgbe_read_mbx_pf - Read a message from the mailbox | |
387 | * @hw: pointer to the HW structure | |
388 | * @msg: The message buffer | |
389 | * @size: Length of buffer | |
390 | * @vf_number: the VF index | |
391 | * | |
392 | * This function copies a message from the mailbox buffer to the caller's | |
393 | * memory buffer. The presumption is that the caller knows that there was | |
394 | * a message due to a VF request so no polling for message is needed. | |
395 | **/ | |
396 | static s32 ixgbe_read_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size, | |
e7cf745b | 397 | u16 vf_number) |
10ca132c GR |
398 | { |
399 | s32 ret_val; | |
400 | u16 i; | |
401 | ||
402 | /* lock the mailbox to prevent pf/vf race condition */ | |
403 | ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number); | |
404 | if (ret_val) | |
e90dd264 | 405 | return ret_val; |
10ca132c GR |
406 | |
407 | /* copy the message to the mailbox memory buffer */ | |
408 | for (i = 0; i < size; i++) | |
409 | msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i); | |
410 | ||
411 | /* Acknowledge the message and release buffer */ | |
412 | IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_ACK); | |
413 | ||
414 | /* update stats */ | |
415 | hw->mbx.stats.msgs_rx++; | |
416 | ||
e90dd264 | 417 | return 0; |
10ca132c GR |
418 | } |
419 | ||
8fecce62 | 420 | #ifdef CONFIG_PCI_IOV |
10ca132c GR |
421 | /** |
422 | * ixgbe_init_mbx_params_pf - set initial values for pf mailbox | |
423 | * @hw: pointer to the HW structure | |
424 | * | |
425 | * Initializes the hw->mbx struct to correct values for pf mailbox | |
426 | */ | |
427 | void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw) | |
428 | { | |
429 | struct ixgbe_mbx_info *mbx = &hw->mbx; | |
430 | ||
d7c8a29f | 431 | if (hw->mac.type != ixgbe_mac_82599EB && |
9a75a1ac DS |
432 | hw->mac.type != ixgbe_mac_X550 && |
433 | hw->mac.type != ixgbe_mac_X550EM_x && | |
49425dfc | 434 | hw->mac.type != ixgbe_mac_x550em_a && |
d7c8a29f ET |
435 | hw->mac.type != ixgbe_mac_X540) |
436 | return; | |
b93a2226 | 437 | |
d7c8a29f | 438 | mbx->timeout = 0; |
5217e879 | 439 | mbx->usec_delay = 0; |
b93a2226 | 440 | |
d7c8a29f ET |
441 | mbx->stats.msgs_tx = 0; |
442 | mbx->stats.msgs_rx = 0; | |
443 | mbx->stats.reqs = 0; | |
444 | mbx->stats.acks = 0; | |
445 | mbx->stats.rsts = 0; | |
446 | ||
447 | mbx->size = IXGBE_VFMAILBOX_SIZE; | |
10ca132c | 448 | } |
8fecce62 | 449 | #endif /* CONFIG_PCI_IOV */ |
10ca132c | 450 | |
37689010 | 451 | const struct ixgbe_mbx_operations mbx_ops_generic = { |
10ca132c GR |
452 | .read = ixgbe_read_mbx_pf, |
453 | .write = ixgbe_write_mbx_pf, | |
454 | .read_posted = ixgbe_read_posted_mbx, | |
455 | .write_posted = ixgbe_write_posted_mbx, | |
456 | .check_for_msg = ixgbe_check_for_msg_pf, | |
457 | .check_for_ack = ixgbe_check_for_ack_pf, | |
458 | .check_for_rst = ixgbe_check_for_rst_pf, | |
459 | }; | |
460 |