diff options
author | Alexander Duyck <alexander.h.duyck@intel.com> | 2009-02-19 23:40:07 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-02-20 03:22:54 -0500 |
commit | 4ae196dfd61d06b061c069edcdd7c73121e60a21 (patch) | |
tree | 68111629e73751b6200cc9bdd8b769246fe0d540 /drivers/net/igb/e1000_mbx.c | |
parent | e173952257d7a3d3c64de3039d9fc02d1fbf49c3 (diff) |
igb: Add support for enabling VFs to PF driver.
This patch adds the support to handle requests from the VF to perform
operations such as completing resets, setting/reading mac address, adding
vlans, adding multicast addresses, setting rlpml, and general
communications between the PF and all VFs.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/igb/e1000_mbx.c')
-rw-r--r-- | drivers/net/igb/e1000_mbx.c | 447 |
1 files changed, 447 insertions, 0 deletions
diff --git a/drivers/net/igb/e1000_mbx.c b/drivers/net/igb/e1000_mbx.c new file mode 100644 index 000000000000..fe71c7ddaa05 --- /dev/null +++ b/drivers/net/igb/e1000_mbx.c | |||
@@ -0,0 +1,447 @@ | |||
1 | /******************************************************************************* | ||
2 | |||
3 | Intel(R) Gigabit Ethernet Linux driver | ||
4 | Copyright(c) 2007-2009 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 "e1000_mbx.h" | ||
29 | |||
30 | /** | ||
31 | * igb_read_mbx - Reads a message from the mailbox | ||
32 | * @hw: pointer to the HW structure | ||
33 | * @msg: The message buffer | ||
34 | * @size: Length of buffer | ||
35 | * @mbx_id: id of mailbox to read | ||
36 | * | ||
37 | * returns SUCCESS if it successfuly read message from buffer | ||
38 | **/ | ||
39 | s32 igb_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) | ||
40 | { | ||
41 | struct e1000_mbx_info *mbx = &hw->mbx; | ||
42 | s32 ret_val = -E1000_ERR_MBX; | ||
43 | |||
44 | /* limit read to size of mailbox */ | ||
45 | if (size > mbx->size) | ||
46 | size = mbx->size; | ||
47 | |||
48 | if (mbx->ops.read) | ||
49 | ret_val = mbx->ops.read(hw, msg, size, mbx_id); | ||
50 | |||
51 | return ret_val; | ||
52 | } | ||
53 | |||
54 | /** | ||
55 | * igb_write_mbx - Write a message to the mailbox | ||
56 | * @hw: pointer to the HW structure | ||
57 | * @msg: The message buffer | ||
58 | * @size: Length of buffer | ||
59 | * @mbx_id: id of mailbox to write | ||
60 | * | ||
61 | * returns SUCCESS if it successfully copied message into the buffer | ||
62 | **/ | ||
63 | s32 igb_write_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) | ||
64 | { | ||
65 | struct e1000_mbx_info *mbx = &hw->mbx; | ||
66 | s32 ret_val = 0; | ||
67 | |||
68 | if (size > mbx->size) | ||
69 | ret_val = -E1000_ERR_MBX; | ||
70 | |||
71 | else if (mbx->ops.write) | ||
72 | ret_val = mbx->ops.write(hw, msg, size, mbx_id); | ||
73 | |||
74 | return ret_val; | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * igb_check_for_msg - checks to see if someone sent us mail | ||
79 | * @hw: pointer to the HW structure | ||
80 | * @mbx_id: id of mailbox to check | ||
81 | * | ||
82 | * returns SUCCESS if the Status bit was found or else ERR_MBX | ||
83 | **/ | ||
84 | s32 igb_check_for_msg(struct e1000_hw *hw, u16 mbx_id) | ||
85 | { | ||
86 | struct e1000_mbx_info *mbx = &hw->mbx; | ||
87 | s32 ret_val = -E1000_ERR_MBX; | ||
88 | |||
89 | if (mbx->ops.check_for_msg) | ||
90 | ret_val = mbx->ops.check_for_msg(hw, mbx_id); | ||
91 | |||
92 | return ret_val; | ||
93 | } | ||
94 | |||
95 | /** | ||
96 | * igb_check_for_ack - checks to see if someone sent us ACK | ||
97 | * @hw: pointer to the HW structure | ||
98 | * @mbx_id: id of mailbox to check | ||
99 | * | ||
100 | * returns SUCCESS if the Status bit was found or else ERR_MBX | ||
101 | **/ | ||
102 | s32 igb_check_for_ack(struct e1000_hw *hw, u16 mbx_id) | ||
103 | { | ||
104 | struct e1000_mbx_info *mbx = &hw->mbx; | ||
105 | s32 ret_val = -E1000_ERR_MBX; | ||
106 | |||
107 | if (mbx->ops.check_for_ack) | ||
108 | ret_val = mbx->ops.check_for_ack(hw, mbx_id); | ||
109 | |||
110 | return ret_val; | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * igb_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 igb_check_for_rst(struct e1000_hw *hw, u16 mbx_id) | ||
121 | { | ||
122 | struct e1000_mbx_info *mbx = &hw->mbx; | ||
123 | s32 ret_val = -E1000_ERR_MBX; | ||
124 | |||
125 | if (mbx->ops.check_for_rst) | ||
126 | ret_val = mbx->ops.check_for_rst(hw, mbx_id); | ||
127 | |||
128 | return ret_val; | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * igb_poll_for_msg - Wait for message notification | ||
133 | * @hw: pointer to the HW structure | ||
134 | * @mbx_id: id of mailbox to write | ||
135 | * | ||
136 | * returns SUCCESS if it successfully received a message notification | ||
137 | **/ | ||
138 | static s32 igb_poll_for_msg(struct e1000_hw *hw, u16 mbx_id) | ||
139 | { | ||
140 | struct e1000_mbx_info *mbx = &hw->mbx; | ||
141 | int countdown = mbx->timeout; | ||
142 | |||
143 | if (!mbx->ops.check_for_msg) | ||
144 | goto out; | ||
145 | |||
146 | while (mbx->ops.check_for_msg(hw, mbx_id)) { | ||
147 | if (!countdown) | ||
148 | break; | ||
149 | countdown--; | ||
150 | udelay(mbx->usec_delay); | ||
151 | } | ||
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 (!mbx->ops.check_for_ack) | ||
169 | goto out; | ||
170 | |||
171 | while (mbx->ops.check_for_ack(hw, mbx_id)) { | ||
172 | if (!countdown) | ||
173 | break; | ||
174 | countdown--; | ||
175 | udelay(mbx->usec_delay); | ||
176 | } | ||
177 | out: | ||
178 | return countdown ? 0 : -E1000_ERR_MBX; | ||
179 | } | ||
180 | |||
181 | /** | ||
182 | * igb_read_posted_mbx - Wait for message notification and receive message | ||
183 | * @hw: pointer to the HW structure | ||
184 | * @msg: The message buffer | ||
185 | * @size: Length of buffer | ||
186 | * @mbx_id: id of mailbox to write | ||
187 | * | ||
188 | * returns SUCCESS if it successfully received a message notification and | ||
189 | * copied it into the receive buffer. | ||
190 | **/ | ||
191 | s32 igb_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) | ||
192 | { | ||
193 | struct e1000_mbx_info *mbx = &hw->mbx; | ||
194 | s32 ret_val = -E1000_ERR_MBX; | ||
195 | |||
196 | if (!mbx->ops.read) | ||
197 | goto out; | ||
198 | |||
199 | ret_val = igb_poll_for_msg(hw, mbx_id); | ||
200 | |||
201 | if (!ret_val) | ||
202 | ret_val = mbx->ops.read(hw, msg, size, mbx_id); | ||
203 | out: | ||
204 | return ret_val; | ||
205 | } | ||
206 | |||
207 | /** | ||
208 | * igb_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 | **/ | ||
217 | s32 igb_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) | ||
218 | { | ||
219 | struct e1000_mbx_info *mbx = &hw->mbx; | ||
220 | s32 ret_val = 0; | ||
221 | |||
222 | if (!mbx->ops.write) | ||
223 | goto out; | ||
224 | |||
225 | /* send msg*/ | ||
226 | ret_val = mbx->ops.write(hw, msg, size, mbx_id); | ||
227 | |||
228 | /* if msg sent wait until we receive an ack */ | ||
229 | if (!ret_val) | ||
230 | ret_val = igb_poll_for_ack(hw, mbx_id); | ||
231 | out: | ||
232 | return ret_val; | ||
233 | } | ||
234 | |||
235 | /** | ||
236 | * e1000_init_mbx_ops_generic - Initialize NVM function pointers | ||
237 | * @hw: pointer to the HW structure | ||
238 | * | ||
239 | * Setups up the function pointers to no-op functions | ||
240 | **/ | ||
241 | void e1000_init_mbx_ops_generic(struct e1000_hw *hw) | ||
242 | { | ||
243 | struct e1000_mbx_info *mbx = &hw->mbx; | ||
244 | mbx->ops.read_posted = igb_read_posted_mbx; | ||
245 | mbx->ops.write_posted = igb_write_posted_mbx; | ||
246 | } | ||
247 | |||
248 | static s32 igb_check_for_bit_pf(struct e1000_hw *hw, u32 mask) | ||
249 | { | ||
250 | u32 mbvficr = rd32(E1000_MBVFICR); | ||
251 | s32 ret_val = -E1000_ERR_MBX; | ||
252 | |||
253 | if (mbvficr & mask) { | ||
254 | ret_val = 0; | ||
255 | wr32(E1000_MBVFICR, mask); | ||
256 | } | ||
257 | |||
258 | return ret_val; | ||
259 | } | ||
260 | |||
261 | /** | ||
262 | * igb_check_for_msg_pf - checks to see if the VF has sent mail | ||
263 | * @hw: pointer to the HW structure | ||
264 | * @vf_number: the VF index | ||
265 | * | ||
266 | * returns SUCCESS if the VF has set the Status bit or else ERR_MBX | ||
267 | **/ | ||
268 | static s32 igb_check_for_msg_pf(struct e1000_hw *hw, u16 vf_number) | ||
269 | { | ||
270 | s32 ret_val = -E1000_ERR_MBX; | ||
271 | |||
272 | if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFREQ_VF1 << vf_number)) { | ||
273 | ret_val = 0; | ||
274 | hw->mbx.stats.reqs++; | ||
275 | } | ||
276 | |||
277 | return ret_val; | ||
278 | } | ||
279 | |||
280 | /** | ||
281 | * igb_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 igb_check_for_ack_pf(struct e1000_hw *hw, u16 vf_number) | ||
288 | { | ||
289 | s32 ret_val = -E1000_ERR_MBX; | ||
290 | |||
291 | if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFACK_VF1 << vf_number)) { | ||
292 | ret_val = 0; | ||
293 | hw->mbx.stats.acks++; | ||
294 | } | ||
295 | |||
296 | return ret_val; | ||
297 | } | ||
298 | |||
299 | /** | ||
300 | * igb_check_for_rst_pf - checks to see if the VF has reset | ||
301 | * @hw: pointer to the HW structure | ||
302 | * @vf_number: the VF index | ||
303 | * | ||
304 | * returns SUCCESS if the VF has set the Status bit or else ERR_MBX | ||
305 | **/ | ||
306 | static s32 igb_check_for_rst_pf(struct e1000_hw *hw, u16 vf_number) | ||
307 | { | ||
308 | u32 vflre = rd32(E1000_VFLRE); | ||
309 | s32 ret_val = -E1000_ERR_MBX; | ||
310 | |||
311 | if (vflre & (1 << vf_number)) { | ||
312 | ret_val = 0; | ||
313 | wr32(E1000_VFLRE, (1 << vf_number)); | ||
314 | hw->mbx.stats.rsts++; | ||
315 | } | ||
316 | |||
317 | return ret_val; | ||
318 | } | ||
319 | |||
320 | /** | ||
321 | * igb_write_mbx_pf - Places a message in the mailbox | ||
322 | * @hw: pointer to the HW structure | ||
323 | * @msg: The message buffer | ||
324 | * @size: Length of buffer | ||
325 | * @vf_number: the VF index | ||
326 | * | ||
327 | * returns SUCCESS if it successfully copied message into the buffer | ||
328 | **/ | ||
329 | static s32 igb_write_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, | ||
330 | u16 vf_number) | ||
331 | { | ||
332 | u32 p2v_mailbox; | ||
333 | s32 ret_val = 0; | ||
334 | u16 i; | ||
335 | |||
336 | /* Take ownership of the buffer */ | ||
337 | wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU); | ||
338 | |||
339 | /* Make sure we have ownership now... */ | ||
340 | p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number)); | ||
341 | if (!(p2v_mailbox & E1000_P2VMAILBOX_PFU)) { | ||
342 | /* failed to grab ownership */ | ||
343 | ret_val = -E1000_ERR_MBX; | ||
344 | goto out_no_write; | ||
345 | } | ||
346 | |||
347 | /* | ||
348 | * flush any ack or msg which may already be in the queue | ||
349 | * as they are likely the result of an error | ||
350 | */ | ||
351 | igb_check_for_ack_pf(hw, vf_number); | ||
352 | igb_check_for_msg_pf(hw, vf_number); | ||
353 | |||
354 | /* copy the caller specified message to the mailbox memory buffer */ | ||
355 | for (i = 0; i < size; i++) | ||
356 | array_wr32(E1000_VMBMEM(vf_number), i, msg[i]); | ||
357 | |||
358 | /* Interrupt VF to tell it a message has been sent and release buffer*/ | ||
359 | wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_STS); | ||
360 | |||
361 | /* update stats */ | ||
362 | hw->mbx.stats.msgs_tx++; | ||
363 | |||
364 | out_no_write: | ||
365 | return ret_val; | ||
366 | |||
367 | } | ||
368 | |||
369 | /** | ||
370 | * igb_read_mbx_pf - Read a message from the mailbox | ||
371 | * @hw: pointer to the HW structure | ||
372 | * @msg: The message buffer | ||
373 | * @size: Length of buffer | ||
374 | * @vf_number: the VF index | ||
375 | * | ||
376 | * This function copies a message from the mailbox buffer to the caller's | ||
377 | * memory buffer. The presumption is that the caller knows that there was | ||
378 | * a message due to a VF request so no polling for message is needed. | ||
379 | **/ | ||
380 | static s32 igb_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, | ||
381 | u16 vf_number) | ||
382 | { | ||
383 | u32 p2v_mailbox; | ||
384 | s32 ret_val = 0; | ||
385 | u16 i; | ||
386 | |||
387 | /* Take ownership of the buffer */ | ||
388 | wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU); | ||
389 | |||
390 | /* Make sure we have ownership now... */ | ||
391 | p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number)); | ||
392 | if (!(p2v_mailbox & E1000_P2VMAILBOX_PFU)) { | ||
393 | /* failed to grab ownership */ | ||
394 | ret_val = -E1000_ERR_MBX; | ||
395 | goto out_no_read; | ||
396 | } | ||
397 | |||
398 | /* copy the message to the mailbox memory buffer */ | ||
399 | for (i = 0; i < size; i++) | ||
400 | msg[i] = array_rd32(E1000_VMBMEM(vf_number), i); | ||
401 | |||
402 | /* Acknowledge the message and release buffer */ | ||
403 | wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_ACK); | ||
404 | |||
405 | /* update stats */ | ||
406 | hw->mbx.stats.msgs_rx++; | ||
407 | |||
408 | ret_val = 0; | ||
409 | |||
410 | out_no_read: | ||
411 | return ret_val; | ||
412 | } | ||
413 | |||
414 | /** | ||
415 | * e1000_init_mbx_params_pf - set initial values for pf mailbox | ||
416 | * @hw: pointer to the HW structure | ||
417 | * | ||
418 | * Initializes the hw->mbx struct to correct values for pf mailbox | ||
419 | */ | ||
420 | s32 igb_init_mbx_params_pf(struct e1000_hw *hw) | ||
421 | { | ||
422 | struct e1000_mbx_info *mbx = &hw->mbx; | ||
423 | |||
424 | if (hw->mac.type == e1000_82576) { | ||
425 | mbx->timeout = 0; | ||
426 | mbx->usec_delay = 0; | ||
427 | |||
428 | mbx->size = E1000_VFMAILBOX_SIZE; | ||
429 | |||
430 | mbx->ops.read = igb_read_mbx_pf; | ||
431 | mbx->ops.write = igb_write_mbx_pf; | ||
432 | mbx->ops.read_posted = igb_read_posted_mbx; | ||
433 | mbx->ops.write_posted = igb_write_posted_mbx; | ||
434 | mbx->ops.check_for_msg = igb_check_for_msg_pf; | ||
435 | mbx->ops.check_for_ack = igb_check_for_ack_pf; | ||
436 | mbx->ops.check_for_rst = igb_check_for_rst_pf; | ||
437 | |||
438 | mbx->stats.msgs_tx = 0; | ||
439 | mbx->stats.msgs_rx = 0; | ||
440 | mbx->stats.reqs = 0; | ||
441 | mbx->stats.acks = 0; | ||
442 | mbx->stats.rsts = 0; | ||
443 | } | ||
444 | |||
445 | return 0; | ||
446 | } | ||
447 | |||