diff options
Diffstat (limited to 'drivers/net/ixgbevf/mbx.c')
-rw-r--r-- | drivers/net/ixgbevf/mbx.c | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/drivers/net/ixgbevf/mbx.c b/drivers/net/ixgbevf/mbx.c new file mode 100644 index 000000000000..b8143501e6fc --- /dev/null +++ b/drivers/net/ixgbevf/mbx.c | |||
@@ -0,0 +1,341 @@ | |||
1 | /******************************************************************************* | ||
2 | |||
3 | Intel 82599 Virtual Function driver | ||
4 | Copyright(c) 1999 - 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 "mbx.h" | ||
29 | |||
30 | /** | ||
31 | * ixgbevf_poll_for_msg - Wait for message notification | ||
32 | * @hw: pointer to the HW structure | ||
33 | * | ||
34 | * returns 0 if it successfully received a message notification | ||
35 | **/ | ||
36 | static s32 ixgbevf_poll_for_msg(struct ixgbe_hw *hw) | ||
37 | { | ||
38 | struct ixgbe_mbx_info *mbx = &hw->mbx; | ||
39 | int countdown = mbx->timeout; | ||
40 | |||
41 | while (countdown && mbx->ops.check_for_msg(hw)) { | ||
42 | countdown--; | ||
43 | udelay(mbx->udelay); | ||
44 | } | ||
45 | |||
46 | /* if we failed, all future posted messages fail until reset */ | ||
47 | if (!countdown) | ||
48 | mbx->timeout = 0; | ||
49 | |||
50 | return countdown ? 0 : IXGBE_ERR_MBX; | ||
51 | } | ||
52 | |||
53 | /** | ||
54 | * ixgbevf_poll_for_ack - Wait for message acknowledgement | ||
55 | * @hw: pointer to the HW structure | ||
56 | * | ||
57 | * returns 0 if it successfully received a message acknowledgement | ||
58 | **/ | ||
59 | static s32 ixgbevf_poll_for_ack(struct ixgbe_hw *hw) | ||
60 | { | ||
61 | struct ixgbe_mbx_info *mbx = &hw->mbx; | ||
62 | int countdown = mbx->timeout; | ||
63 | |||
64 | while (countdown && mbx->ops.check_for_ack(hw)) { | ||
65 | countdown--; | ||
66 | udelay(mbx->udelay); | ||
67 | } | ||
68 | |||
69 | /* if we failed, all future posted messages fail until reset */ | ||
70 | if (!countdown) | ||
71 | mbx->timeout = 0; | ||
72 | |||
73 | return countdown ? 0 : IXGBE_ERR_MBX; | ||
74 | } | ||
75 | |||
76 | /** | ||
77 | * ixgbevf_read_posted_mbx - Wait for message notification and receive message | ||
78 | * @hw: pointer to the HW structure | ||
79 | * @msg: The message buffer | ||
80 | * @size: Length of buffer | ||
81 | * | ||
82 | * returns 0 if it successfully received a message notification and | ||
83 | * copied it into the receive buffer. | ||
84 | **/ | ||
85 | static s32 ixgbevf_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size) | ||
86 | { | ||
87 | struct ixgbe_mbx_info *mbx = &hw->mbx; | ||
88 | s32 ret_val = IXGBE_ERR_MBX; | ||
89 | |||
90 | ret_val = ixgbevf_poll_for_msg(hw); | ||
91 | |||
92 | /* if ack received read message, otherwise we timed out */ | ||
93 | if (!ret_val) | ||
94 | ret_val = mbx->ops.read(hw, msg, size); | ||
95 | |||
96 | return ret_val; | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * ixgbevf_write_posted_mbx - Write a message to the mailbox, wait for ack | ||
101 | * @hw: pointer to the HW structure | ||
102 | * @msg: The message buffer | ||
103 | * @size: Length of buffer | ||
104 | * | ||
105 | * returns 0 if it successfully copied message into the buffer and | ||
106 | * received an ack to that message within delay * timeout period | ||
107 | **/ | ||
108 | static s32 ixgbevf_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size) | ||
109 | { | ||
110 | struct ixgbe_mbx_info *mbx = &hw->mbx; | ||
111 | s32 ret_val; | ||
112 | |||
113 | /* send msg */ | ||
114 | ret_val = mbx->ops.write(hw, msg, size); | ||
115 | |||
116 | /* if msg sent wait until we receive an ack */ | ||
117 | if (!ret_val) | ||
118 | ret_val = ixgbevf_poll_for_ack(hw); | ||
119 | |||
120 | return ret_val; | ||
121 | } | ||
122 | |||
123 | /** | ||
124 | * ixgbevf_read_v2p_mailbox - read v2p mailbox | ||
125 | * @hw: pointer to the HW structure | ||
126 | * | ||
127 | * This function is used to read the v2p mailbox without losing the read to | ||
128 | * clear status bits. | ||
129 | **/ | ||
130 | static u32 ixgbevf_read_v2p_mailbox(struct ixgbe_hw *hw) | ||
131 | { | ||
132 | u32 v2p_mailbox = IXGBE_READ_REG(hw, IXGBE_VFMAILBOX); | ||
133 | |||
134 | v2p_mailbox |= hw->mbx.v2p_mailbox; | ||
135 | hw->mbx.v2p_mailbox |= v2p_mailbox & IXGBE_VFMAILBOX_R2C_BITS; | ||
136 | |||
137 | return v2p_mailbox; | ||
138 | } | ||
139 | |||
140 | /** | ||
141 | * ixgbevf_check_for_bit_vf - Determine if a status bit was set | ||
142 | * @hw: pointer to the HW structure | ||
143 | * @mask: bitmask for bits to be tested and cleared | ||
144 | * | ||
145 | * This function is used to check for the read to clear bits within | ||
146 | * the V2P mailbox. | ||
147 | **/ | ||
148 | static s32 ixgbevf_check_for_bit_vf(struct ixgbe_hw *hw, u32 mask) | ||
149 | { | ||
150 | u32 v2p_mailbox = ixgbevf_read_v2p_mailbox(hw); | ||
151 | s32 ret_val = IXGBE_ERR_MBX; | ||
152 | |||
153 | if (v2p_mailbox & mask) | ||
154 | ret_val = 0; | ||
155 | |||
156 | hw->mbx.v2p_mailbox &= ~mask; | ||
157 | |||
158 | return ret_val; | ||
159 | } | ||
160 | |||
161 | /** | ||
162 | * ixgbevf_check_for_msg_vf - checks to see if the PF has sent mail | ||
163 | * @hw: pointer to the HW structure | ||
164 | * | ||
165 | * returns 0 if the PF has set the Status bit or else ERR_MBX | ||
166 | **/ | ||
167 | static s32 ixgbevf_check_for_msg_vf(struct ixgbe_hw *hw) | ||
168 | { | ||
169 | s32 ret_val = IXGBE_ERR_MBX; | ||
170 | |||
171 | if (!ixgbevf_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFSTS)) { | ||
172 | ret_val = 0; | ||
173 | hw->mbx.stats.reqs++; | ||
174 | } | ||
175 | |||
176 | return ret_val; | ||
177 | } | ||
178 | |||
179 | /** | ||
180 | * ixgbevf_check_for_ack_vf - checks to see if the PF has ACK'd | ||
181 | * @hw: pointer to the HW structure | ||
182 | * | ||
183 | * returns 0 if the PF has set the ACK bit or else ERR_MBX | ||
184 | **/ | ||
185 | static s32 ixgbevf_check_for_ack_vf(struct ixgbe_hw *hw) | ||
186 | { | ||
187 | s32 ret_val = IXGBE_ERR_MBX; | ||
188 | |||
189 | if (!ixgbevf_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFACK)) { | ||
190 | ret_val = 0; | ||
191 | hw->mbx.stats.acks++; | ||
192 | } | ||
193 | |||
194 | return ret_val; | ||
195 | } | ||
196 | |||
197 | /** | ||
198 | * ixgbevf_check_for_rst_vf - checks to see if the PF has reset | ||
199 | * @hw: pointer to the HW structure | ||
200 | * | ||
201 | * returns true if the PF has set the reset done bit or else false | ||
202 | **/ | ||
203 | static s32 ixgbevf_check_for_rst_vf(struct ixgbe_hw *hw) | ||
204 | { | ||
205 | s32 ret_val = IXGBE_ERR_MBX; | ||
206 | |||
207 | if (!ixgbevf_check_for_bit_vf(hw, (IXGBE_VFMAILBOX_RSTD | | ||
208 | IXGBE_VFMAILBOX_RSTI))) { | ||
209 | ret_val = 0; | ||
210 | hw->mbx.stats.rsts++; | ||
211 | } | ||
212 | |||
213 | return ret_val; | ||
214 | } | ||
215 | |||
216 | /** | ||
217 | * ixgbevf_obtain_mbx_lock_vf - obtain mailbox lock | ||
218 | * @hw: pointer to the HW structure | ||
219 | * | ||
220 | * return 0 if we obtained the mailbox lock | ||
221 | **/ | ||
222 | static s32 ixgbevf_obtain_mbx_lock_vf(struct ixgbe_hw *hw) | ||
223 | { | ||
224 | s32 ret_val = IXGBE_ERR_MBX; | ||
225 | |||
226 | /* Take ownership of the buffer */ | ||
227 | IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_VFU); | ||
228 | |||
229 | /* reserve mailbox for vf use */ | ||
230 | if (ixgbevf_read_v2p_mailbox(hw) & IXGBE_VFMAILBOX_VFU) | ||
231 | ret_val = 0; | ||
232 | |||
233 | return ret_val; | ||
234 | } | ||
235 | |||
236 | /** | ||
237 | * ixgbevf_write_mbx_vf - Write a message to the mailbox | ||
238 | * @hw: pointer to the HW structure | ||
239 | * @msg: The message buffer | ||
240 | * @size: Length of buffer | ||
241 | * | ||
242 | * returns 0 if it successfully copied message into the buffer | ||
243 | **/ | ||
244 | static s32 ixgbevf_write_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size) | ||
245 | { | ||
246 | s32 ret_val; | ||
247 | u16 i; | ||
248 | |||
249 | |||
250 | /* lock the mailbox to prevent pf/vf race condition */ | ||
251 | ret_val = ixgbevf_obtain_mbx_lock_vf(hw); | ||
252 | if (ret_val) | ||
253 | goto out_no_write; | ||
254 | |||
255 | /* flush msg and acks as we are overwriting the message buffer */ | ||
256 | ixgbevf_check_for_msg_vf(hw); | ||
257 | ixgbevf_check_for_ack_vf(hw); | ||
258 | |||
259 | /* copy the caller specified message to the mailbox memory buffer */ | ||
260 | for (i = 0; i < size; i++) | ||
261 | IXGBE_WRITE_REG_ARRAY(hw, IXGBE_VFMBMEM, i, msg[i]); | ||
262 | |||
263 | /* update stats */ | ||
264 | hw->mbx.stats.msgs_tx++; | ||
265 | |||
266 | /* Drop VFU and interrupt the PF to tell it a message has been sent */ | ||
267 | IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_REQ); | ||
268 | |||
269 | out_no_write: | ||
270 | return ret_val; | ||
271 | } | ||
272 | |||
273 | /** | ||
274 | * ixgbevf_read_mbx_vf - Reads a message from the inbox intended for vf | ||
275 | * @hw: pointer to the HW structure | ||
276 | * @msg: The message buffer | ||
277 | * @size: Length of buffer | ||
278 | * | ||
279 | * returns 0 if it successfuly read message from buffer | ||
280 | **/ | ||
281 | static s32 ixgbevf_read_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size) | ||
282 | { | ||
283 | s32 ret_val = 0; | ||
284 | u16 i; | ||
285 | |||
286 | /* lock the mailbox to prevent pf/vf race condition */ | ||
287 | ret_val = ixgbevf_obtain_mbx_lock_vf(hw); | ||
288 | if (ret_val) | ||
289 | goto out_no_read; | ||
290 | |||
291 | /* copy the message from the mailbox memory buffer */ | ||
292 | for (i = 0; i < size; i++) | ||
293 | msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_VFMBMEM, i); | ||
294 | |||
295 | /* Acknowledge receipt and release mailbox, then we're done */ | ||
296 | IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_ACK); | ||
297 | |||
298 | /* update stats */ | ||
299 | hw->mbx.stats.msgs_rx++; | ||
300 | |||
301 | out_no_read: | ||
302 | return ret_val; | ||
303 | } | ||
304 | |||
305 | /** | ||
306 | * ixgbevf_init_mbx_params_vf - set initial values for vf mailbox | ||
307 | * @hw: pointer to the HW structure | ||
308 | * | ||
309 | * Initializes the hw->mbx struct to correct values for vf mailbox | ||
310 | */ | ||
311 | s32 ixgbevf_init_mbx_params_vf(struct ixgbe_hw *hw) | ||
312 | { | ||
313 | struct ixgbe_mbx_info *mbx = &hw->mbx; | ||
314 | |||
315 | /* start mailbox as timed out and let the reset_hw call set the timeout | ||
316 | * value to begin communications */ | ||
317 | mbx->timeout = 0; | ||
318 | mbx->udelay = IXGBE_VF_MBX_INIT_DELAY; | ||
319 | |||
320 | mbx->size = IXGBE_VFMAILBOX_SIZE; | ||
321 | |||
322 | mbx->stats.msgs_tx = 0; | ||
323 | mbx->stats.msgs_rx = 0; | ||
324 | mbx->stats.reqs = 0; | ||
325 | mbx->stats.acks = 0; | ||
326 | mbx->stats.rsts = 0; | ||
327 | |||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | struct ixgbe_mbx_operations ixgbevf_mbx_ops = { | ||
332 | .init_params = ixgbevf_init_mbx_params_vf, | ||
333 | .read = ixgbevf_read_mbx_vf, | ||
334 | .write = ixgbevf_write_mbx_vf, | ||
335 | .read_posted = ixgbevf_read_posted_mbx, | ||
336 | .write_posted = ixgbevf_write_posted_mbx, | ||
337 | .check_for_msg = ixgbevf_check_for_msg_vf, | ||
338 | .check_for_ack = ixgbevf_check_for_ack_vf, | ||
339 | .check_for_rst = ixgbevf_check_for_rst_vf, | ||
340 | }; | ||
341 | |||