diff options
author | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-04-07 10:42:33 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-08-10 23:03:27 -0400 |
commit | dee1ad47f2ee75f5146d83ca757c1b7861c34c3b (patch) | |
tree | 47cbdefe3d0f9b729724e378ad6a96eaddfd5fbc /drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c | |
parent | f7917c009c28c941ba151ee66f04dc7f6a2e1e0b (diff) |
intel: Move the Intel wired LAN drivers
Moves the Intel wired LAN drivers into drivers/net/ethernet/intel/ and
the necessary Kconfig and Makefile changes.
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c')
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c | 471 |
1 files changed, 471 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c new file mode 100644 index 000000000000..1ff0eefcfd0a --- /dev/null +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c | |||
@@ -0,0 +1,471 @@ | |||
1 | /******************************************************************************* | ||
2 | |||
3 | Intel 10 Gigabit PCI Express Linux driver | ||
4 | Copyright(c) 1999 - 2011 Intel Corporation. | ||
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: | ||
23 | e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> | ||
24 | Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
25 | |||
26 | *******************************************************************************/ | ||
27 | |||
28 | #include <linux/pci.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include "ixgbe_type.h" | ||
31 | #include "ixgbe_common.h" | ||
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 | * | ||
41 | * returns SUCCESS if it successfuly read message from buffer | ||
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; | ||
46 | s32 ret_val = IXGBE_ERR_MBX; | ||
47 | |||
48 | /* limit read to size of mailbox */ | ||
49 | if (size > mbx->size) | ||
50 | size = mbx->size; | ||
51 | |||
52 | if (mbx->ops.read) | ||
53 | ret_val = mbx->ops.read(hw, msg, size, mbx_id); | ||
54 | |||
55 | return ret_val; | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * ixgbe_write_mbx - Write a message to the mailbox | ||
60 | * @hw: pointer to the HW structure | ||
61 | * @msg: The message buffer | ||
62 | * @size: Length of buffer | ||
63 | * @mbx_id: id of mailbox to write | ||
64 | * | ||
65 | * returns SUCCESS if it successfully copied message into the buffer | ||
66 | **/ | ||
67 | s32 ixgbe_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) | ||
68 | { | ||
69 | struct ixgbe_mbx_info *mbx = &hw->mbx; | ||
70 | s32 ret_val = 0; | ||
71 | |||
72 | if (size > mbx->size) | ||
73 | ret_val = IXGBE_ERR_MBX; | ||
74 | |||
75 | else if (mbx->ops.write) | ||
76 | ret_val = mbx->ops.write(hw, msg, size, mbx_id); | ||
77 | |||
78 | return ret_val; | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * ixgbe_check_for_msg - checks to see if someone sent us mail | ||
83 | * @hw: pointer to the HW structure | ||
84 | * @mbx_id: id of mailbox to check | ||
85 | * | ||
86 | * returns SUCCESS if the Status bit was found or else ERR_MBX | ||
87 | **/ | ||
88 | s32 ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id) | ||
89 | { | ||
90 | struct ixgbe_mbx_info *mbx = &hw->mbx; | ||
91 | s32 ret_val = IXGBE_ERR_MBX; | ||
92 | |||
93 | if (mbx->ops.check_for_msg) | ||
94 | ret_val = mbx->ops.check_for_msg(hw, mbx_id); | ||
95 | |||
96 | return ret_val; | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * ixgbe_check_for_ack - checks to see if someone sent us ACK | ||
101 | * @hw: pointer to the HW structure | ||
102 | * @mbx_id: id of mailbox to check | ||
103 | * | ||
104 | * returns SUCCESS if the Status bit was found or else ERR_MBX | ||
105 | **/ | ||
106 | s32 ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id) | ||
107 | { | ||
108 | struct ixgbe_mbx_info *mbx = &hw->mbx; | ||
109 | s32 ret_val = IXGBE_ERR_MBX; | ||
110 | |||
111 | if (mbx->ops.check_for_ack) | ||
112 | ret_val = mbx->ops.check_for_ack(hw, mbx_id); | ||
113 | |||
114 | return ret_val; | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * ixgbe_check_for_rst - checks to see if other side has reset | ||
119 | * @hw: pointer to the HW structure | ||
120 | * @mbx_id: id of mailbox to check | ||
121 | * | ||
122 | * returns SUCCESS if the Status bit was found or else ERR_MBX | ||
123 | **/ | ||
124 | s32 ixgbe_check_for_rst(struct ixgbe_hw *hw, u16 mbx_id) | ||
125 | { | ||
126 | struct ixgbe_mbx_info *mbx = &hw->mbx; | ||
127 | s32 ret_val = IXGBE_ERR_MBX; | ||
128 | |||
129 | if (mbx->ops.check_for_rst) | ||
130 | ret_val = mbx->ops.check_for_rst(hw, mbx_id); | ||
131 | |||
132 | return ret_val; | ||
133 | } | ||
134 | |||
135 | /** | ||
136 | * ixgbe_poll_for_msg - Wait for message notification | ||
137 | * @hw: pointer to the HW structure | ||
138 | * @mbx_id: id of mailbox to write | ||
139 | * | ||
140 | * returns SUCCESS if it successfully received a message notification | ||
141 | **/ | ||
142 | static s32 ixgbe_poll_for_msg(struct ixgbe_hw *hw, u16 mbx_id) | ||
143 | { | ||
144 | struct ixgbe_mbx_info *mbx = &hw->mbx; | ||
145 | int countdown = mbx->timeout; | ||
146 | |||
147 | if (!countdown || !mbx->ops.check_for_msg) | ||
148 | goto out; | ||
149 | |||
150 | while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) { | ||
151 | countdown--; | ||
152 | if (!countdown) | ||
153 | break; | ||
154 | udelay(mbx->usec_delay); | ||
155 | } | ||
156 | |||
157 | out: | ||
158 | return countdown ? 0 : IXGBE_ERR_MBX; | ||
159 | } | ||
160 | |||
161 | /** | ||
162 | * ixgbe_poll_for_ack - Wait for message acknowledgement | ||
163 | * @hw: pointer to the HW structure | ||
164 | * @mbx_id: id of mailbox to write | ||
165 | * | ||
166 | * returns SUCCESS if it successfully received a message acknowledgement | ||
167 | **/ | ||
168 | static s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id) | ||
169 | { | ||
170 | struct ixgbe_mbx_info *mbx = &hw->mbx; | ||
171 | int countdown = mbx->timeout; | ||
172 | |||
173 | if (!countdown || !mbx->ops.check_for_ack) | ||
174 | goto out; | ||
175 | |||
176 | while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) { | ||
177 | countdown--; | ||
178 | if (!countdown) | ||
179 | break; | ||
180 | udelay(mbx->usec_delay); | ||
181 | } | ||
182 | |||
183 | out: | ||
184 | return countdown ? 0 : IXGBE_ERR_MBX; | ||
185 | } | ||
186 | |||
187 | /** | ||
188 | * ixgbe_read_posted_mbx - Wait for message notification and receive message | ||
189 | * @hw: pointer to the HW structure | ||
190 | * @msg: The message buffer | ||
191 | * @size: Length of buffer | ||
192 | * @mbx_id: id of mailbox to write | ||
193 | * | ||
194 | * returns SUCCESS if it successfully received a message notification and | ||
195 | * copied it into the receive buffer. | ||
196 | **/ | ||
197 | static s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, | ||
198 | u16 mbx_id) | ||
199 | { | ||
200 | struct ixgbe_mbx_info *mbx = &hw->mbx; | ||
201 | s32 ret_val = IXGBE_ERR_MBX; | ||
202 | |||
203 | if (!mbx->ops.read) | ||
204 | goto out; | ||
205 | |||
206 | ret_val = ixgbe_poll_for_msg(hw, mbx_id); | ||
207 | |||
208 | /* if ack received read message, otherwise we timed out */ | ||
209 | if (!ret_val) | ||
210 | ret_val = mbx->ops.read(hw, msg, size, mbx_id); | ||
211 | out: | ||
212 | return ret_val; | ||
213 | } | ||
214 | |||
215 | /** | ||
216 | * ixgbe_write_posted_mbx - Write a message to the mailbox, wait for ack | ||
217 | * @hw: pointer to the HW structure | ||
218 | * @msg: The message buffer | ||
219 | * @size: Length of buffer | ||
220 | * @mbx_id: id of mailbox to write | ||
221 | * | ||
222 | * returns SUCCESS if it successfully copied message into the buffer and | ||
223 | * received an ack to that message within delay * timeout period | ||
224 | **/ | ||
225 | static s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, | ||
226 | u16 mbx_id) | ||
227 | { | ||
228 | struct ixgbe_mbx_info *mbx = &hw->mbx; | ||
229 | s32 ret_val = IXGBE_ERR_MBX; | ||
230 | |||
231 | /* exit if either we can't write or there isn't a defined timeout */ | ||
232 | if (!mbx->ops.write || !mbx->timeout) | ||
233 | goto out; | ||
234 | |||
235 | /* send msg */ | ||
236 | ret_val = mbx->ops.write(hw, msg, size, mbx_id); | ||
237 | |||
238 | /* if msg sent wait until we receive an ack */ | ||
239 | if (!ret_val) | ||
240 | ret_val = ixgbe_poll_for_ack(hw, mbx_id); | ||
241 | out: | ||
242 | return ret_val; | ||
243 | } | ||
244 | |||
245 | static s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index) | ||
246 | { | ||
247 | u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index)); | ||
248 | s32 ret_val = IXGBE_ERR_MBX; | ||
249 | |||
250 | if (mbvficr & mask) { | ||
251 | ret_val = 0; | ||
252 | IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask); | ||
253 | } | ||
254 | |||
255 | return ret_val; | ||
256 | } | ||
257 | |||
258 | /** | ||
259 | * ixgbe_check_for_msg_pf - checks to see if the VF has sent mail | ||
260 | * @hw: pointer to the HW structure | ||
261 | * @vf_number: the VF index | ||
262 | * | ||
263 | * returns SUCCESS if the VF has set the Status bit or else ERR_MBX | ||
264 | **/ | ||
265 | static s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number) | ||
266 | { | ||
267 | s32 ret_val = IXGBE_ERR_MBX; | ||
268 | s32 index = IXGBE_MBVFICR_INDEX(vf_number); | ||
269 | u32 vf_bit = vf_number % 16; | ||
270 | |||
271 | if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFREQ_VF1 << vf_bit, | ||
272 | index)) { | ||
273 | ret_val = 0; | ||
274 | hw->mbx.stats.reqs++; | ||
275 | } | ||
276 | |||
277 | return ret_val; | ||
278 | } | ||
279 | |||
280 | /** | ||
281 | * ixgbe_check_for_ack_pf - checks to see if the VF has ACKed | ||
282 | * @hw: pointer to the HW structure | ||
283 | * @vf_number: the VF index | ||
284 | * | ||
285 | * returns SUCCESS if the VF has set the Status bit or else ERR_MBX | ||
286 | **/ | ||
287 | static s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number) | ||
288 | { | ||
289 | s32 ret_val = IXGBE_ERR_MBX; | ||
290 | s32 index = IXGBE_MBVFICR_INDEX(vf_number); | ||
291 | u32 vf_bit = vf_number % 16; | ||
292 | |||
293 | if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFACK_VF1 << vf_bit, | ||
294 | index)) { | ||
295 | ret_val = 0; | ||
296 | hw->mbx.stats.acks++; | ||
297 | } | ||
298 | |||
299 | return ret_val; | ||
300 | } | ||
301 | |||
302 | /** | ||
303 | * ixgbe_check_for_rst_pf - checks to see if the VF has reset | ||
304 | * @hw: pointer to the HW structure | ||
305 | * @vf_number: the VF index | ||
306 | * | ||
307 | * returns SUCCESS if the VF has set the Status bit or else ERR_MBX | ||
308 | **/ | ||
309 | static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number) | ||
310 | { | ||
311 | u32 reg_offset = (vf_number < 32) ? 0 : 1; | ||
312 | u32 vf_shift = vf_number % 32; | ||
313 | u32 vflre = 0; | ||
314 | s32 ret_val = IXGBE_ERR_MBX; | ||
315 | |||
316 | switch (hw->mac.type) { | ||
317 | case ixgbe_mac_82599EB: | ||
318 | vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset)); | ||
319 | break; | ||
320 | case ixgbe_mac_X540: | ||
321 | vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset)); | ||
322 | break; | ||
323 | default: | ||
324 | break; | ||
325 | } | ||
326 | |||
327 | if (vflre & (1 << vf_shift)) { | ||
328 | ret_val = 0; | ||
329 | IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), (1 << vf_shift)); | ||
330 | hw->mbx.stats.rsts++; | ||
331 | } | ||
332 | |||
333 | return ret_val; | ||
334 | } | ||
335 | |||
336 | /** | ||
337 | * ixgbe_obtain_mbx_lock_pf - obtain mailbox lock | ||
338 | * @hw: pointer to the HW structure | ||
339 | * @vf_number: the VF index | ||
340 | * | ||
341 | * return SUCCESS if we obtained the mailbox lock | ||
342 | **/ | ||
343 | static s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number) | ||
344 | { | ||
345 | s32 ret_val = IXGBE_ERR_MBX; | ||
346 | u32 p2v_mailbox; | ||
347 | |||
348 | /* Take ownership of the buffer */ | ||
349 | IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_PFU); | ||
350 | |||
351 | /* reserve mailbox for vf use */ | ||
352 | p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number)); | ||
353 | if (p2v_mailbox & IXGBE_PFMAILBOX_PFU) | ||
354 | ret_val = 0; | ||
355 | |||
356 | return ret_val; | ||
357 | } | ||
358 | |||
359 | /** | ||
360 | * ixgbe_write_mbx_pf - Places a message in the mailbox | ||
361 | * @hw: pointer to the HW structure | ||
362 | * @msg: The message buffer | ||
363 | * @size: Length of buffer | ||
364 | * @vf_number: the VF index | ||
365 | * | ||
366 | * returns SUCCESS if it successfully copied message into the buffer | ||
367 | **/ | ||
368 | static s32 ixgbe_write_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size, | ||
369 | u16 vf_number) | ||
370 | { | ||
371 | s32 ret_val; | ||
372 | u16 i; | ||
373 | |||
374 | /* lock the mailbox to prevent pf/vf race condition */ | ||
375 | ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number); | ||
376 | if (ret_val) | ||
377 | goto out_no_write; | ||
378 | |||
379 | /* flush msg and acks as we are overwriting the message buffer */ | ||
380 | ixgbe_check_for_msg_pf(hw, vf_number); | ||
381 | ixgbe_check_for_ack_pf(hw, vf_number); | ||
382 | |||
383 | /* copy the caller specified message to the mailbox memory buffer */ | ||
384 | for (i = 0; i < size; i++) | ||
385 | IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, msg[i]); | ||
386 | |||
387 | /* Interrupt VF to tell it a message has been sent and release buffer*/ | ||
388 | IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_STS); | ||
389 | |||
390 | /* update stats */ | ||
391 | hw->mbx.stats.msgs_tx++; | ||
392 | |||
393 | out_no_write: | ||
394 | return ret_val; | ||
395 | |||
396 | } | ||
397 | |||
398 | /** | ||
399 | * ixgbe_read_mbx_pf - Read a message from the mailbox | ||
400 | * @hw: pointer to the HW structure | ||
401 | * @msg: The message buffer | ||
402 | * @size: Length of buffer | ||
403 | * @vf_number: the VF index | ||
404 | * | ||
405 | * This function copies a message from the mailbox buffer to the caller's | ||
406 | * memory buffer. The presumption is that the caller knows that there was | ||
407 | * a message due to a VF request so no polling for message is needed. | ||
408 | **/ | ||
409 | static s32 ixgbe_read_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size, | ||
410 | u16 vf_number) | ||
411 | { | ||
412 | s32 ret_val; | ||
413 | u16 i; | ||
414 | |||
415 | /* lock the mailbox to prevent pf/vf race condition */ | ||
416 | ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number); | ||
417 | if (ret_val) | ||
418 | goto out_no_read; | ||
419 | |||
420 | /* copy the message to the mailbox memory buffer */ | ||
421 | for (i = 0; i < size; i++) | ||
422 | msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i); | ||
423 | |||
424 | /* Acknowledge the message and release buffer */ | ||
425 | IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_ACK); | ||
426 | |||
427 | /* update stats */ | ||
428 | hw->mbx.stats.msgs_rx++; | ||
429 | |||
430 | out_no_read: | ||
431 | return ret_val; | ||
432 | } | ||
433 | |||
434 | #ifdef CONFIG_PCI_IOV | ||
435 | /** | ||
436 | * ixgbe_init_mbx_params_pf - set initial values for pf mailbox | ||
437 | * @hw: pointer to the HW structure | ||
438 | * | ||
439 | * Initializes the hw->mbx struct to correct values for pf mailbox | ||
440 | */ | ||
441 | void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw) | ||
442 | { | ||
443 | struct ixgbe_mbx_info *mbx = &hw->mbx; | ||
444 | |||
445 | if (hw->mac.type != ixgbe_mac_82599EB && | ||
446 | hw->mac.type != ixgbe_mac_X540) | ||
447 | return; | ||
448 | |||
449 | mbx->timeout = 0; | ||
450 | mbx->usec_delay = 0; | ||
451 | |||
452 | mbx->stats.msgs_tx = 0; | ||
453 | mbx->stats.msgs_rx = 0; | ||
454 | mbx->stats.reqs = 0; | ||
455 | mbx->stats.acks = 0; | ||
456 | mbx->stats.rsts = 0; | ||
457 | |||
458 | mbx->size = IXGBE_VFMAILBOX_SIZE; | ||
459 | } | ||
460 | #endif /* CONFIG_PCI_IOV */ | ||
461 | |||
462 | struct ixgbe_mbx_operations mbx_ops_generic = { | ||
463 | .read = ixgbe_read_mbx_pf, | ||
464 | .write = ixgbe_write_mbx_pf, | ||
465 | .read_posted = ixgbe_read_posted_mbx, | ||
466 | .write_posted = ixgbe_write_posted_mbx, | ||
467 | .check_for_msg = ixgbe_check_for_msg_pf, | ||
468 | .check_for_ack = ixgbe_check_for_ack_pf, | ||
469 | .check_for_rst = ixgbe_check_for_rst_pf, | ||
470 | }; | ||
471 | |||