]>
Commit | Line | Data |
---|---|---|
c4e84bde RM |
1 | #include "qlge.h" |
2 | ||
8aae2600 RM |
3 | int ql_unpause_mpi_risc(struct ql_adapter *qdev) |
4 | { | |
5 | u32 tmp; | |
6 | ||
7 | /* Un-pause the RISC */ | |
8 | tmp = ql_read32(qdev, CSR); | |
9 | if (!(tmp & CSR_RP)) | |
10 | return -EIO; | |
11 | ||
12 | ql_write32(qdev, CSR, CSR_CMD_CLR_PAUSE); | |
13 | return 0; | |
14 | } | |
15 | ||
16 | int ql_pause_mpi_risc(struct ql_adapter *qdev) | |
17 | { | |
18 | u32 tmp; | |
19 | int count = UDELAY_COUNT; | |
20 | ||
21 | /* Pause the RISC */ | |
22 | ql_write32(qdev, CSR, CSR_CMD_SET_PAUSE); | |
23 | do { | |
24 | tmp = ql_read32(qdev, CSR); | |
25 | if (tmp & CSR_RP) | |
26 | break; | |
27 | mdelay(UDELAY_DELAY); | |
28 | count--; | |
29 | } while (count); | |
30 | return (count == 0) ? -ETIMEDOUT : 0; | |
31 | } | |
32 | ||
2c1f73c3 RM |
33 | int ql_hard_reset_mpi_risc(struct ql_adapter *qdev) |
34 | { | |
35 | u32 tmp; | |
36 | int count = UDELAY_COUNT; | |
37 | ||
38 | /* Reset the RISC */ | |
39 | ql_write32(qdev, CSR, CSR_CMD_SET_RST); | |
40 | do { | |
41 | tmp = ql_read32(qdev, CSR); | |
42 | if (tmp & CSR_RR) { | |
43 | ql_write32(qdev, CSR, CSR_CMD_CLR_RST); | |
44 | break; | |
45 | } | |
46 | mdelay(UDELAY_DELAY); | |
47 | count--; | |
48 | } while (count); | |
49 | return (count == 0) ? -ETIMEDOUT : 0; | |
50 | } | |
51 | ||
a2e809bb | 52 | int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data) |
c4e84bde RM |
53 | { |
54 | int status; | |
55 | /* wait for reg to come ready */ | |
56 | status = ql_wait_reg_rdy(qdev, PROC_ADDR, PROC_ADDR_RDY, PROC_ADDR_ERR); | |
57 | if (status) | |
58 | goto exit; | |
59 | /* set up for reg read */ | |
60 | ql_write32(qdev, PROC_ADDR, reg | PROC_ADDR_R); | |
61 | /* wait for reg to come ready */ | |
62 | status = ql_wait_reg_rdy(qdev, PROC_ADDR, PROC_ADDR_RDY, PROC_ADDR_ERR); | |
63 | if (status) | |
64 | goto exit; | |
65 | /* get the data */ | |
66 | *data = ql_read32(qdev, PROC_DATA); | |
67 | exit: | |
68 | return status; | |
69 | } | |
70 | ||
a2e809bb RM |
71 | int ql_write_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 data) |
72 | { | |
73 | int status = 0; | |
74 | /* wait for reg to come ready */ | |
75 | status = ql_wait_reg_rdy(qdev, PROC_ADDR, PROC_ADDR_RDY, PROC_ADDR_ERR); | |
76 | if (status) | |
77 | goto exit; | |
78 | /* write the data to the data reg */ | |
79 | ql_write32(qdev, PROC_DATA, data); | |
80 | /* trigger the write */ | |
81 | ql_write32(qdev, PROC_ADDR, reg); | |
82 | /* wait for reg to come ready */ | |
83 | status = ql_wait_reg_rdy(qdev, PROC_ADDR, PROC_ADDR_RDY, PROC_ADDR_ERR); | |
84 | if (status) | |
85 | goto exit; | |
86 | exit: | |
87 | return status; | |
88 | } | |
89 | ||
90 | int ql_soft_reset_mpi_risc(struct ql_adapter *qdev) | |
91 | { | |
92 | int status; | |
93 | status = ql_write_mpi_reg(qdev, 0x00001010, 1); | |
94 | return status; | |
95 | } | |
96 | ||
8aae2600 RM |
97 | /* Determine if we are in charge of the firwmare. If |
98 | * we are the lower of the 2 NIC pcie functions, or if | |
99 | * we are the higher function and the lower function | |
100 | * is not enabled. | |
101 | */ | |
102 | int ql_own_firmware(struct ql_adapter *qdev) | |
103 | { | |
104 | u32 temp; | |
105 | ||
106 | /* If we are the lower of the 2 NIC functions | |
107 | * on the chip the we are responsible for | |
108 | * core dump and firmware reset after an error. | |
109 | */ | |
110 | if (qdev->func < qdev->alt_func) | |
111 | return 1; | |
112 | ||
113 | /* If we are the higher of the 2 NIC functions | |
114 | * on the chip and the lower function is not | |
115 | * enabled, then we are responsible for | |
116 | * core dump and firmware reset after an error. | |
117 | */ | |
118 | temp = ql_read32(qdev, STS); | |
119 | if (!(temp & (1 << (8 + qdev->alt_func)))) | |
120 | return 1; | |
121 | ||
122 | return 0; | |
123 | ||
124 | } | |
125 | ||
2f22d22e | 126 | static int ql_get_mb_sts(struct ql_adapter *qdev, struct mbox_params *mbcp) |
c4e84bde RM |
127 | { |
128 | int i, status; | |
129 | ||
130 | status = ql_sem_spinlock(qdev, SEM_PROC_REG_MASK); | |
131 | if (status) | |
132 | return -EBUSY; | |
133 | for (i = 0; i < mbcp->out_count; i++) { | |
134 | status = | |
a2e809bb | 135 | ql_read_mpi_reg(qdev, qdev->mailbox_out + i, |
c4e84bde RM |
136 | &mbcp->mbox_out[i]); |
137 | if (status) { | |
ae9540f7 | 138 | netif_err(qdev, drv, qdev->ndev, "Failed mailbox read.\n"); |
c4e84bde RM |
139 | break; |
140 | } | |
141 | } | |
142 | ql_sem_unlock(qdev, SEM_PROC_REG_MASK); /* does flush too */ | |
143 | return status; | |
144 | } | |
145 | ||
ca0413b6 RM |
146 | /* Wait for a single mailbox command to complete. |
147 | * Returns zero on success. | |
148 | */ | |
149 | static int ql_wait_mbx_cmd_cmplt(struct ql_adapter *qdev) | |
150 | { | |
365da872 | 151 | int count = 100; |
ca0413b6 RM |
152 | u32 value; |
153 | ||
154 | do { | |
155 | value = ql_read32(qdev, STS); | |
156 | if (value & STS_PI) | |
157 | return 0; | |
365da872 | 158 | mdelay(UDELAY_DELAY); /* 100ms */ |
ca0413b6 RM |
159 | } while (--count); |
160 | return -ETIMEDOUT; | |
161 | } | |
162 | ||
163 | /* Execute a single mailbox command. | |
164 | * Caller must hold PROC_ADDR semaphore. | |
165 | */ | |
166 | static int ql_exec_mb_cmd(struct ql_adapter *qdev, struct mbox_params *mbcp) | |
167 | { | |
168 | int i, status; | |
169 | ||
170 | /* | |
171 | * Make sure there's nothing pending. | |
172 | * This shouldn't happen. | |
173 | */ | |
174 | if (ql_read32(qdev, CSR) & CSR_HRI) | |
175 | return -EIO; | |
176 | ||
177 | status = ql_sem_spinlock(qdev, SEM_PROC_REG_MASK); | |
178 | if (status) | |
179 | return status; | |
180 | ||
181 | /* | |
182 | * Fill the outbound mailboxes. | |
183 | */ | |
184 | for (i = 0; i < mbcp->in_count; i++) { | |
185 | status = ql_write_mpi_reg(qdev, qdev->mailbox_in + i, | |
186 | mbcp->mbox_in[i]); | |
187 | if (status) | |
188 | goto end; | |
189 | } | |
190 | /* | |
191 | * Wake up the MPI firmware. | |
192 | */ | |
193 | ql_write32(qdev, CSR, CSR_CMD_SET_H2R_INT); | |
194 | end: | |
195 | ql_sem_unlock(qdev, SEM_PROC_REG_MASK); | |
196 | return status; | |
197 | } | |
198 | ||
2ee1e272 RM |
199 | /* We are being asked by firmware to accept |
200 | * a change to the port. This is only | |
201 | * a change to max frame sizes (Tx/Rx), pause | |
98a1708d | 202 | * parameters, or loopback mode. We wake up a worker |
2ee1e272 RM |
203 | * to handler processing this since a mailbox command |
204 | * will need to be sent to ACK the request. | |
205 | */ | |
206 | static int ql_idc_req_aen(struct ql_adapter *qdev) | |
207 | { | |
208 | int status; | |
209 | struct mbox_params *mbcp = &qdev->idc_mbc; | |
210 | ||
ae9540f7 | 211 | netif_err(qdev, drv, qdev->ndev, "Enter!\n"); |
2ee1e272 RM |
212 | /* Get the status data and start up a thread to |
213 | * handle the request. | |
214 | */ | |
215 | mbcp = &qdev->idc_mbc; | |
216 | mbcp->out_count = 4; | |
217 | status = ql_get_mb_sts(qdev, mbcp); | |
218 | if (status) { | |
ae9540f7 JP |
219 | netif_err(qdev, drv, qdev->ndev, |
220 | "Could not read MPI, resetting ASIC!\n"); | |
2ee1e272 RM |
221 | ql_queue_asic_error(qdev); |
222 | } else { | |
223 | /* Begin polled mode early so | |
224 | * we don't get another interrupt | |
225 | * when we leave mpi_worker. | |
226 | */ | |
227 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); | |
228 | queue_delayed_work(qdev->workqueue, &qdev->mpi_idc_work, 0); | |
229 | } | |
230 | return status; | |
231 | } | |
232 | ||
bcc2cb3b RM |
233 | /* Process an inter-device event completion. |
234 | * If good, signal the caller's completion. | |
235 | */ | |
236 | static int ql_idc_cmplt_aen(struct ql_adapter *qdev) | |
237 | { | |
238 | int status; | |
239 | struct mbox_params *mbcp = &qdev->idc_mbc; | |
240 | mbcp->out_count = 4; | |
241 | status = ql_get_mb_sts(qdev, mbcp); | |
242 | if (status) { | |
ae9540f7 JP |
243 | netif_err(qdev, drv, qdev->ndev, |
244 | "Could not read MPI, resetting RISC!\n"); | |
bcc2cb3b RM |
245 | ql_queue_fw_error(qdev); |
246 | } else | |
247 | /* Wake up the sleeping mpi_idc_work thread that is | |
248 | * waiting for this event. | |
249 | */ | |
250 | complete(&qdev->ide_completion); | |
251 | ||
252 | return status; | |
253 | } | |
5700abe9 | 254 | |
c4e84bde RM |
255 | static void ql_link_up(struct ql_adapter *qdev, struct mbox_params *mbcp) |
256 | { | |
5700abe9 | 257 | int status; |
c4e84bde RM |
258 | mbcp->out_count = 2; |
259 | ||
5700abe9 RM |
260 | status = ql_get_mb_sts(qdev, mbcp); |
261 | if (status) { | |
ae9540f7 JP |
262 | netif_err(qdev, drv, qdev->ndev, |
263 | "%s: Could not get mailbox status.\n", __func__); | |
5700abe9 RM |
264 | return; |
265 | } | |
c4e84bde RM |
266 | |
267 | qdev->link_status = mbcp->mbox_out[1]; | |
ae9540f7 | 268 | netif_err(qdev, drv, qdev->ndev, "Link Up.\n"); |
5700abe9 | 269 | |
2ee1e272 RM |
270 | /* If we're coming back from an IDC event |
271 | * then set up the CAM and frame routing. | |
272 | */ | |
273 | if (test_bit(QL_CAM_RT_SET, &qdev->flags)) { | |
274 | status = ql_cam_route_initialize(qdev); | |
275 | if (status) { | |
ae9540f7 JP |
276 | netif_err(qdev, ifup, qdev->ndev, |
277 | "Failed to init CAM/Routing tables.\n"); | |
2ee1e272 RM |
278 | return; |
279 | } else | |
280 | clear_bit(QL_CAM_RT_SET, &qdev->flags); | |
281 | } | |
282 | ||
283 | /* Queue up a worker to check the frame | |
284 | * size information, and fix it if it's not | |
285 | * to our liking. | |
286 | */ | |
287 | if (!test_bit(QL_PORT_CFG, &qdev->flags)) { | |
ae9540f7 | 288 | netif_err(qdev, drv, qdev->ndev, "Queue Port Config Worker!\n"); |
2ee1e272 RM |
289 | set_bit(QL_PORT_CFG, &qdev->flags); |
290 | /* Begin polled mode early so | |
291 | * we don't get another interrupt | |
292 | * when we leave mpi_worker dpc. | |
293 | */ | |
294 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); | |
295 | queue_delayed_work(qdev->workqueue, | |
296 | &qdev->mpi_port_cfg_work, 0); | |
297 | } | |
298 | ||
6a473308 | 299 | ql_link_on(qdev); |
c4e84bde RM |
300 | } |
301 | ||
302 | static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp) | |
303 | { | |
11d9fe68 RM |
304 | int status; |
305 | ||
c4e84bde RM |
306 | mbcp->out_count = 3; |
307 | ||
11d9fe68 RM |
308 | status = ql_get_mb_sts(qdev, mbcp); |
309 | if (status) | |
ae9540f7 | 310 | netif_err(qdev, drv, qdev->ndev, "Link down AEN broken!\n"); |
c4e84bde | 311 | |
6a473308 | 312 | ql_link_off(qdev); |
c4e84bde RM |
313 | } |
314 | ||
eae6b58f RM |
315 | static int ql_sfp_in(struct ql_adapter *qdev, struct mbox_params *mbcp) |
316 | { | |
317 | int status; | |
318 | ||
319 | mbcp->out_count = 5; | |
320 | ||
321 | status = ql_get_mb_sts(qdev, mbcp); | |
322 | if (status) | |
ae9540f7 | 323 | netif_err(qdev, drv, qdev->ndev, "SFP in AEN broken!\n"); |
eae6b58f | 324 | else |
ae9540f7 | 325 | netif_err(qdev, drv, qdev->ndev, "SFP insertion detected.\n"); |
eae6b58f RM |
326 | |
327 | return status; | |
328 | } | |
329 | ||
330 | static int ql_sfp_out(struct ql_adapter *qdev, struct mbox_params *mbcp) | |
331 | { | |
332 | int status; | |
333 | ||
334 | mbcp->out_count = 1; | |
335 | ||
336 | status = ql_get_mb_sts(qdev, mbcp); | |
337 | if (status) | |
ae9540f7 | 338 | netif_err(qdev, drv, qdev->ndev, "SFP out AEN broken!\n"); |
eae6b58f | 339 | else |
ae9540f7 | 340 | netif_err(qdev, drv, qdev->ndev, "SFP removal detected.\n"); |
eae6b58f RM |
341 | |
342 | return status; | |
343 | } | |
344 | ||
fc1f9ea5 RM |
345 | static int ql_aen_lost(struct ql_adapter *qdev, struct mbox_params *mbcp) |
346 | { | |
347 | int status; | |
348 | ||
349 | mbcp->out_count = 6; | |
350 | ||
351 | status = ql_get_mb_sts(qdev, mbcp); | |
352 | if (status) | |
ae9540f7 | 353 | netif_err(qdev, drv, qdev->ndev, "Lost AEN broken!\n"); |
fc1f9ea5 RM |
354 | else { |
355 | int i; | |
ae9540f7 | 356 | netif_err(qdev, drv, qdev->ndev, "Lost AEN detected.\n"); |
fc1f9ea5 | 357 | for (i = 0; i < mbcp->out_count; i++) |
ae9540f7 JP |
358 | netif_err(qdev, drv, qdev->ndev, "mbox_out[%d] = 0x%.08x.\n", |
359 | i, mbcp->mbox_out[i]); | |
fc1f9ea5 RM |
360 | |
361 | } | |
362 | ||
363 | return status; | |
364 | } | |
365 | ||
c4e84bde RM |
366 | static void ql_init_fw_done(struct ql_adapter *qdev, struct mbox_params *mbcp) |
367 | { | |
f56b54f5 RM |
368 | int status; |
369 | ||
c4e84bde RM |
370 | mbcp->out_count = 2; |
371 | ||
f56b54f5 RM |
372 | status = ql_get_mb_sts(qdev, mbcp); |
373 | if (status) { | |
ae9540f7 | 374 | netif_err(qdev, drv, qdev->ndev, "Firmware did not initialize!\n"); |
f56b54f5 | 375 | } else { |
ae9540f7 JP |
376 | netif_err(qdev, drv, qdev->ndev, "Firmware Revision = 0x%.08x.\n", |
377 | mbcp->mbox_out[1]); | |
88051b4e | 378 | qdev->fw_rev_id = mbcp->mbox_out[1]; |
f56b54f5 RM |
379 | status = ql_cam_route_initialize(qdev); |
380 | if (status) | |
ae9540f7 JP |
381 | netif_err(qdev, ifup, qdev->ndev, |
382 | "Failed to init CAM/Routing tables.\n"); | |
c4e84bde | 383 | } |
c4e84bde RM |
384 | } |
385 | ||
125844ea RM |
386 | /* Process an async event and clear it unless it's an |
387 | * error condition. | |
388 | * This can get called iteratively from the mpi_work thread | |
389 | * when events arrive via an interrupt. | |
390 | * It also gets called when a mailbox command is polling for | |
391 | * it's completion. */ | |
392 | static int ql_mpi_handler(struct ql_adapter *qdev, struct mbox_params *mbcp) | |
393 | { | |
394 | int status; | |
ca0413b6 | 395 | int orig_count = mbcp->out_count; |
125844ea RM |
396 | |
397 | /* Just get mailbox zero for now. */ | |
398 | mbcp->out_count = 1; | |
399 | status = ql_get_mb_sts(qdev, mbcp); | |
400 | if (status) { | |
ae9540f7 JP |
401 | netif_err(qdev, drv, qdev->ndev, |
402 | "Could not read MPI, resetting ASIC!\n"); | |
125844ea RM |
403 | ql_queue_asic_error(qdev); |
404 | goto end; | |
405 | } | |
406 | ||
407 | switch (mbcp->mbox_out[0]) { | |
408 | ||
ca0413b6 RM |
409 | /* This case is only active when we arrive here |
410 | * as a result of issuing a mailbox command to | |
411 | * the firmware. | |
412 | */ | |
413 | case MB_CMD_STS_INTRMDT: | |
414 | case MB_CMD_STS_GOOD: | |
415 | case MB_CMD_STS_INVLD_CMD: | |
416 | case MB_CMD_STS_XFC_ERR: | |
417 | case MB_CMD_STS_CSUM_ERR: | |
418 | case MB_CMD_STS_ERR: | |
419 | case MB_CMD_STS_PARAM_ERR: | |
420 | /* We can only get mailbox status if we're polling from an | |
421 | * unfinished command. Get the rest of the status data and | |
422 | * return back to the caller. | |
423 | * We only end up here when we're polling for a mailbox | |
424 | * command completion. | |
425 | */ | |
426 | mbcp->out_count = orig_count; | |
427 | status = ql_get_mb_sts(qdev, mbcp); | |
428 | return status; | |
429 | ||
2ee1e272 RM |
430 | /* We are being asked by firmware to accept |
431 | * a change to the port. This is only | |
432 | * a change to max frame sizes (Tx/Rx), pause | |
98a1708d | 433 | * parameters, or loopback mode. |
2ee1e272 RM |
434 | */ |
435 | case AEN_IDC_REQ: | |
436 | status = ql_idc_req_aen(qdev); | |
437 | break; | |
438 | ||
bcc2cb3b RM |
439 | /* Process and inbound IDC event. |
440 | * This will happen when we're trying to | |
441 | * change tx/rx max frame size, change pause | |
98a1708d | 442 | * parameters or loopback mode. |
bcc2cb3b RM |
443 | */ |
444 | case AEN_IDC_CMPLT: | |
445 | case AEN_IDC_EXT: | |
446 | status = ql_idc_cmplt_aen(qdev); | |
447 | break; | |
448 | ||
125844ea RM |
449 | case AEN_LINK_UP: |
450 | ql_link_up(qdev, mbcp); | |
451 | break; | |
452 | ||
453 | case AEN_LINK_DOWN: | |
454 | ql_link_down(qdev, mbcp); | |
455 | break; | |
456 | ||
457 | case AEN_FW_INIT_DONE: | |
f56b54f5 RM |
458 | /* If we're in process on executing the firmware, |
459 | * then convert the status to normal mailbox status. | |
460 | */ | |
461 | if (mbcp->mbox_in[0] == MB_CMD_EX_FW) { | |
462 | mbcp->out_count = orig_count; | |
463 | status = ql_get_mb_sts(qdev, mbcp); | |
464 | mbcp->mbox_out[0] = MB_CMD_STS_GOOD; | |
465 | return status; | |
466 | } | |
125844ea RM |
467 | ql_init_fw_done(qdev, mbcp); |
468 | break; | |
469 | ||
eae6b58f RM |
470 | case AEN_AEN_SFP_IN: |
471 | ql_sfp_in(qdev, mbcp); | |
472 | break; | |
473 | ||
474 | case AEN_AEN_SFP_OUT: | |
475 | ql_sfp_out(qdev, mbcp); | |
476 | break; | |
477 | ||
7c92191c RM |
478 | /* This event can arrive at boot time or after an |
479 | * MPI reset if the firmware failed to initialize. | |
480 | */ | |
125844ea | 481 | case AEN_FW_INIT_FAIL: |
7c92191c RM |
482 | /* If we're in process on executing the firmware, |
483 | * then convert the status to normal mailbox status. | |
484 | */ | |
485 | if (mbcp->mbox_in[0] == MB_CMD_EX_FW) { | |
486 | mbcp->out_count = orig_count; | |
487 | status = ql_get_mb_sts(qdev, mbcp); | |
488 | mbcp->mbox_out[0] = MB_CMD_STS_ERR; | |
489 | return status; | |
490 | } | |
ae9540f7 JP |
491 | netif_err(qdev, drv, qdev->ndev, |
492 | "Firmware initialization failed.\n"); | |
7c92191c RM |
493 | status = -EIO; |
494 | ql_queue_fw_error(qdev); | |
495 | break; | |
496 | ||
125844ea | 497 | case AEN_SYS_ERR: |
ae9540f7 | 498 | netif_err(qdev, drv, qdev->ndev, "System Error.\n"); |
125844ea | 499 | ql_queue_fw_error(qdev); |
bb667670 | 500 | status = -EIO; |
125844ea RM |
501 | break; |
502 | ||
fc1f9ea5 RM |
503 | case AEN_AEN_LOST: |
504 | ql_aen_lost(qdev, mbcp); | |
505 | break; | |
506 | ||
91ced682 RM |
507 | case AEN_DCBX_CHG: |
508 | /* Need to support AEN 8110 */ | |
509 | break; | |
125844ea | 510 | default: |
ae9540f7 JP |
511 | netif_err(qdev, drv, qdev->ndev, |
512 | "Unsupported AE %.08x.\n", mbcp->mbox_out[0]); | |
125844ea RM |
513 | /* Clear the MPI firmware status. */ |
514 | } | |
515 | end: | |
516 | ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT); | |
709ac4f4 RM |
517 | /* Restore the original mailbox count to |
518 | * what the caller asked for. This can get | |
519 | * changed when a mailbox command is waiting | |
520 | * for a response and an AEN arrives and | |
521 | * is handled. | |
522 | * */ | |
523 | mbcp->out_count = orig_count; | |
125844ea RM |
524 | return status; |
525 | } | |
526 | ||
ca0413b6 RM |
527 | /* Execute a single mailbox command. |
528 | * mbcp is a pointer to an array of u32. Each | |
529 | * element in the array contains the value for it's | |
530 | * respective mailbox register. | |
531 | */ | |
532 | static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) | |
533 | { | |
da039451 RM |
534 | int status; |
535 | unsigned long count; | |
ca0413b6 | 536 | |
ca0413b6 RM |
537 | |
538 | /* Begin polled mode for MPI */ | |
539 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); | |
540 | ||
541 | /* Load the mailbox registers and wake up MPI RISC. */ | |
542 | status = ql_exec_mb_cmd(qdev, mbcp); | |
543 | if (status) | |
544 | goto end; | |
545 | ||
546 | ||
547 | /* If we're generating a system error, then there's nothing | |
548 | * to wait for. | |
549 | */ | |
550 | if (mbcp->mbox_in[0] == MB_CMD_MAKE_SYS_ERR) | |
551 | goto end; | |
552 | ||
553 | /* Wait for the command to complete. We loop | |
554 | * here because some AEN might arrive while | |
555 | * we're waiting for the mailbox command to | |
da039451 | 556 | * complete. If more than 5 seconds expire we can |
ca0413b6 | 557 | * assume something is wrong. */ |
da039451 | 558 | count = jiffies + HZ * MAILBOX_TIMEOUT; |
ca0413b6 RM |
559 | do { |
560 | /* Wait for the interrupt to come in. */ | |
561 | status = ql_wait_mbx_cmd_cmplt(qdev); | |
562 | if (status) | |
60fa6c37 | 563 | continue; |
ca0413b6 RM |
564 | |
565 | /* Process the event. If it's an AEN, it | |
566 | * will be handled in-line or a worker | |
567 | * will be spawned. If it's our completion | |
568 | * we will catch it below. | |
569 | */ | |
570 | status = ql_mpi_handler(qdev, mbcp); | |
571 | if (status) | |
572 | goto end; | |
573 | ||
574 | /* It's either the completion for our mailbox | |
575 | * command complete or an AEN. If it's our | |
576 | * completion then get out. | |
577 | */ | |
578 | if (((mbcp->mbox_out[0] & 0x0000f000) == | |
579 | MB_CMD_STS_GOOD) || | |
580 | ((mbcp->mbox_out[0] & 0x0000f000) == | |
581 | MB_CMD_STS_INTRMDT)) | |
da039451 RM |
582 | goto done; |
583 | } while (time_before(jiffies, count)); | |
ca0413b6 | 584 | |
ae9540f7 JP |
585 | netif_err(qdev, drv, qdev->ndev, |
586 | "Timed out waiting for mailbox complete.\n"); | |
da039451 RM |
587 | status = -ETIMEDOUT; |
588 | goto end; | |
589 | ||
590 | done: | |
ca0413b6 RM |
591 | |
592 | /* Now we can clear the interrupt condition | |
593 | * and look at our status. | |
594 | */ | |
595 | ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT); | |
596 | ||
597 | if (((mbcp->mbox_out[0] & 0x0000f000) != | |
598 | MB_CMD_STS_GOOD) && | |
599 | ((mbcp->mbox_out[0] & 0x0000f000) != | |
600 | MB_CMD_STS_INTRMDT)) { | |
ca0413b6 RM |
601 | status = -EIO; |
602 | } | |
603 | end: | |
ca0413b6 RM |
604 | /* End polled mode for MPI */ |
605 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI); | |
606 | return status; | |
607 | } | |
608 | ||
d5c1da56 RM |
609 | int ql_mb_sys_err(struct ql_adapter *qdev) |
610 | { | |
611 | struct mbox_params mbc; | |
612 | struct mbox_params *mbcp = &mbc; | |
613 | int status; | |
614 | ||
615 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
616 | ||
617 | mbcp->in_count = 1; | |
618 | mbcp->out_count = 0; | |
619 | ||
620 | mbcp->mbox_in[0] = MB_CMD_MAKE_SYS_ERR; | |
621 | ||
622 | status = ql_mailbox_command(qdev, mbcp); | |
623 | return status; | |
624 | } | |
cfec0cbc RM |
625 | |
626 | /* Get MPI firmware version. This will be used for | |
627 | * driver banner and for ethtool info. | |
628 | * Returns zero on success. | |
629 | */ | |
630 | int ql_mb_about_fw(struct ql_adapter *qdev) | |
631 | { | |
632 | struct mbox_params mbc; | |
633 | struct mbox_params *mbcp = &mbc; | |
634 | int status = 0; | |
635 | ||
636 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
637 | ||
638 | mbcp->in_count = 1; | |
639 | mbcp->out_count = 3; | |
640 | ||
641 | mbcp->mbox_in[0] = MB_CMD_ABOUT_FW; | |
642 | ||
643 | status = ql_mailbox_command(qdev, mbcp); | |
644 | if (status) | |
645 | return status; | |
646 | ||
647 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
ae9540f7 JP |
648 | netif_err(qdev, drv, qdev->ndev, |
649 | "Failed about firmware command\n"); | |
cfec0cbc RM |
650 | status = -EIO; |
651 | } | |
652 | ||
653 | /* Store the firmware version */ | |
654 | qdev->fw_rev_id = mbcp->mbox_out[1]; | |
655 | ||
656 | return status; | |
657 | } | |
658 | ||
ca0413b6 RM |
659 | /* Get functional state for MPI firmware. |
660 | * Returns zero on success. | |
661 | */ | |
662 | int ql_mb_get_fw_state(struct ql_adapter *qdev) | |
663 | { | |
664 | struct mbox_params mbc; | |
665 | struct mbox_params *mbcp = &mbc; | |
666 | int status = 0; | |
667 | ||
668 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
669 | ||
670 | mbcp->in_count = 1; | |
671 | mbcp->out_count = 2; | |
672 | ||
673 | mbcp->mbox_in[0] = MB_CMD_GET_FW_STATE; | |
674 | ||
675 | status = ql_mailbox_command(qdev, mbcp); | |
676 | if (status) | |
677 | return status; | |
678 | ||
679 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
ae9540f7 JP |
680 | netif_err(qdev, drv, qdev->ndev, |
681 | "Failed Get Firmware State.\n"); | |
ca0413b6 RM |
682 | status = -EIO; |
683 | } | |
684 | ||
685 | /* If bit zero is set in mbx 1 then the firmware is | |
686 | * running, but not initialized. This should never | |
687 | * happen. | |
688 | */ | |
689 | if (mbcp->mbox_out[1] & 1) { | |
ae9540f7 JP |
690 | netif_err(qdev, drv, qdev->ndev, |
691 | "Firmware waiting for initialization.\n"); | |
ca0413b6 RM |
692 | status = -EIO; |
693 | } | |
694 | ||
695 | return status; | |
696 | } | |
697 | ||
2ee1e272 RM |
698 | /* Send and ACK mailbox command to the firmware to |
699 | * let it continue with the change. | |
700 | */ | |
701 | int ql_mb_idc_ack(struct ql_adapter *qdev) | |
702 | { | |
703 | struct mbox_params mbc; | |
704 | struct mbox_params *mbcp = &mbc; | |
705 | int status = 0; | |
706 | ||
707 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
708 | ||
709 | mbcp->in_count = 5; | |
710 | mbcp->out_count = 1; | |
711 | ||
712 | mbcp->mbox_in[0] = MB_CMD_IDC_ACK; | |
713 | mbcp->mbox_in[1] = qdev->idc_mbc.mbox_out[1]; | |
714 | mbcp->mbox_in[2] = qdev->idc_mbc.mbox_out[2]; | |
715 | mbcp->mbox_in[3] = qdev->idc_mbc.mbox_out[3]; | |
716 | mbcp->mbox_in[4] = qdev->idc_mbc.mbox_out[4]; | |
717 | ||
718 | status = ql_mailbox_command(qdev, mbcp); | |
719 | if (status) | |
720 | return status; | |
721 | ||
722 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
ae9540f7 | 723 | netif_err(qdev, drv, qdev->ndev, "Failed IDC ACK send.\n"); |
2ee1e272 RM |
724 | status = -EIO; |
725 | } | |
726 | return status; | |
727 | } | |
728 | ||
bcc2cb3b RM |
729 | /* Get link settings and maximum frame size settings |
730 | * for the current port. | |
731 | * Most likely will block. | |
732 | */ | |
1d30df24 | 733 | int ql_mb_set_port_cfg(struct ql_adapter *qdev) |
bcc2cb3b RM |
734 | { |
735 | struct mbox_params mbc; | |
736 | struct mbox_params *mbcp = &mbc; | |
737 | int status = 0; | |
738 | ||
739 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
740 | ||
741 | mbcp->in_count = 3; | |
742 | mbcp->out_count = 1; | |
743 | ||
744 | mbcp->mbox_in[0] = MB_CMD_SET_PORT_CFG; | |
745 | mbcp->mbox_in[1] = qdev->link_config; | |
746 | mbcp->mbox_in[2] = qdev->max_frame_size; | |
747 | ||
748 | ||
749 | status = ql_mailbox_command(qdev, mbcp); | |
750 | if (status) | |
751 | return status; | |
752 | ||
753 | if (mbcp->mbox_out[0] == MB_CMD_STS_INTRMDT) { | |
ae9540f7 JP |
754 | netif_err(qdev, drv, qdev->ndev, |
755 | "Port Config sent, wait for IDC.\n"); | |
bcc2cb3b | 756 | } else if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { |
ae9540f7 JP |
757 | netif_err(qdev, drv, qdev->ndev, |
758 | "Failed Set Port Configuration.\n"); | |
bcc2cb3b RM |
759 | status = -EIO; |
760 | } | |
761 | return status; | |
762 | } | |
763 | ||
2c1f73c3 RM |
764 | int ql_mb_dump_ram(struct ql_adapter *qdev, u64 req_dma, u32 addr, |
765 | u32 size) | |
766 | { | |
767 | int status = 0; | |
768 | struct mbox_params mbc; | |
769 | struct mbox_params *mbcp = &mbc; | |
770 | ||
771 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
772 | ||
773 | mbcp->in_count = 9; | |
774 | mbcp->out_count = 1; | |
775 | ||
776 | mbcp->mbox_in[0] = MB_CMD_DUMP_RISC_RAM; | |
777 | mbcp->mbox_in[1] = LSW(addr); | |
778 | mbcp->mbox_in[2] = MSW(req_dma); | |
779 | mbcp->mbox_in[3] = LSW(req_dma); | |
780 | mbcp->mbox_in[4] = MSW(size); | |
781 | mbcp->mbox_in[5] = LSW(size); | |
782 | mbcp->mbox_in[6] = MSW(MSD(req_dma)); | |
783 | mbcp->mbox_in[7] = LSW(MSD(req_dma)); | |
784 | mbcp->mbox_in[8] = MSW(addr); | |
785 | ||
786 | ||
787 | status = ql_mailbox_command(qdev, mbcp); | |
788 | if (status) | |
789 | return status; | |
790 | ||
791 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
ae9540f7 | 792 | netif_err(qdev, drv, qdev->ndev, "Failed to dump risc RAM.\n"); |
2c1f73c3 RM |
793 | status = -EIO; |
794 | } | |
795 | return status; | |
796 | } | |
797 | ||
798 | /* Issue a mailbox command to dump RISC RAM. */ | |
799 | int ql_dump_risc_ram_area(struct ql_adapter *qdev, void *buf, | |
800 | u32 ram_addr, int word_count) | |
801 | { | |
802 | int status; | |
803 | char *my_buf; | |
804 | dma_addr_t buf_dma; | |
805 | ||
806 | my_buf = pci_alloc_consistent(qdev->pdev, word_count * sizeof(u32), | |
807 | &buf_dma); | |
808 | if (!my_buf) | |
809 | return -EIO; | |
810 | ||
811 | status = ql_mb_dump_ram(qdev, buf_dma, ram_addr, word_count); | |
812 | if (!status) | |
813 | memcpy(buf, my_buf, word_count * sizeof(u32)); | |
814 | ||
815 | pci_free_consistent(qdev->pdev, word_count * sizeof(u32), my_buf, | |
816 | buf_dma); | |
817 | return status; | |
818 | } | |
819 | ||
bcc2cb3b RM |
820 | /* Get link settings and maximum frame size settings |
821 | * for the current port. | |
822 | * Most likely will block. | |
823 | */ | |
1d30df24 | 824 | int ql_mb_get_port_cfg(struct ql_adapter *qdev) |
bcc2cb3b RM |
825 | { |
826 | struct mbox_params mbc; | |
827 | struct mbox_params *mbcp = &mbc; | |
828 | int status = 0; | |
829 | ||
830 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
831 | ||
832 | mbcp->in_count = 1; | |
833 | mbcp->out_count = 3; | |
834 | ||
835 | mbcp->mbox_in[0] = MB_CMD_GET_PORT_CFG; | |
836 | ||
837 | status = ql_mailbox_command(qdev, mbcp); | |
838 | if (status) | |
839 | return status; | |
840 | ||
841 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
ae9540f7 JP |
842 | netif_err(qdev, drv, qdev->ndev, |
843 | "Failed Get Port Configuration.\n"); | |
bcc2cb3b RM |
844 | status = -EIO; |
845 | } else { | |
ae9540f7 JP |
846 | netif_printk(qdev, drv, KERN_DEBUG, qdev->ndev, |
847 | "Passed Get Port Configuration.\n"); | |
bcc2cb3b RM |
848 | qdev->link_config = mbcp->mbox_out[1]; |
849 | qdev->max_frame_size = mbcp->mbox_out[2]; | |
850 | } | |
851 | return status; | |
852 | } | |
853 | ||
bc083ce9 RM |
854 | int ql_mb_wol_mode(struct ql_adapter *qdev, u32 wol) |
855 | { | |
856 | struct mbox_params mbc; | |
857 | struct mbox_params *mbcp = &mbc; | |
858 | int status; | |
859 | ||
860 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
861 | ||
862 | mbcp->in_count = 2; | |
863 | mbcp->out_count = 1; | |
864 | ||
865 | mbcp->mbox_in[0] = MB_CMD_SET_WOL_MODE; | |
866 | mbcp->mbox_in[1] = wol; | |
867 | ||
868 | ||
869 | status = ql_mailbox_command(qdev, mbcp); | |
870 | if (status) | |
871 | return status; | |
872 | ||
873 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
ae9540f7 | 874 | netif_err(qdev, drv, qdev->ndev, "Failed to set WOL mode.\n"); |
bc083ce9 RM |
875 | status = -EIO; |
876 | } | |
877 | return status; | |
878 | } | |
879 | ||
880 | int ql_mb_wol_set_magic(struct ql_adapter *qdev, u32 enable_wol) | |
881 | { | |
882 | struct mbox_params mbc; | |
883 | struct mbox_params *mbcp = &mbc; | |
884 | int status; | |
885 | u8 *addr = qdev->ndev->dev_addr; | |
886 | ||
887 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
888 | ||
889 | mbcp->in_count = 8; | |
890 | mbcp->out_count = 1; | |
891 | ||
892 | mbcp->mbox_in[0] = MB_CMD_SET_WOL_MAGIC; | |
893 | if (enable_wol) { | |
894 | mbcp->mbox_in[1] = (u32)addr[0]; | |
895 | mbcp->mbox_in[2] = (u32)addr[1]; | |
896 | mbcp->mbox_in[3] = (u32)addr[2]; | |
897 | mbcp->mbox_in[4] = (u32)addr[3]; | |
898 | mbcp->mbox_in[5] = (u32)addr[4]; | |
899 | mbcp->mbox_in[6] = (u32)addr[5]; | |
900 | mbcp->mbox_in[7] = 0; | |
901 | } else { | |
902 | mbcp->mbox_in[1] = 0; | |
903 | mbcp->mbox_in[2] = 1; | |
904 | mbcp->mbox_in[3] = 1; | |
905 | mbcp->mbox_in[4] = 1; | |
906 | mbcp->mbox_in[5] = 1; | |
907 | mbcp->mbox_in[6] = 1; | |
908 | mbcp->mbox_in[7] = 0; | |
909 | } | |
910 | ||
911 | status = ql_mailbox_command(qdev, mbcp); | |
912 | if (status) | |
913 | return status; | |
914 | ||
915 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
ae9540f7 | 916 | netif_err(qdev, drv, qdev->ndev, "Failed to set WOL mode.\n"); |
bc083ce9 RM |
917 | status = -EIO; |
918 | } | |
919 | return status; | |
920 | } | |
921 | ||
bcc2cb3b RM |
922 | /* IDC - Inter Device Communication... |
923 | * Some firmware commands require consent of adjacent FCOE | |
924 | * function. This function waits for the OK, or a | |
925 | * counter-request for a little more time.i | |
926 | * The firmware will complete the request if the other | |
927 | * function doesn't respond. | |
928 | */ | |
929 | static int ql_idc_wait(struct ql_adapter *qdev) | |
930 | { | |
931 | int status = -ETIMEDOUT; | |
932 | long wait_time = 1 * HZ; | |
933 | struct mbox_params *mbcp = &qdev->idc_mbc; | |
934 | do { | |
935 | /* Wait here for the command to complete | |
936 | * via the IDC process. | |
937 | */ | |
938 | wait_time = | |
939 | wait_for_completion_timeout(&qdev->ide_completion, | |
940 | wait_time); | |
941 | if (!wait_time) { | |
ae9540f7 | 942 | netif_err(qdev, drv, qdev->ndev, "IDC Timeout.\n"); |
bcc2cb3b RM |
943 | break; |
944 | } | |
945 | /* Now examine the response from the IDC process. | |
946 | * We might have a good completion or a request for | |
947 | * more wait time. | |
948 | */ | |
949 | if (mbcp->mbox_out[0] == AEN_IDC_EXT) { | |
ae9540f7 JP |
950 | netif_err(qdev, drv, qdev->ndev, |
951 | "IDC Time Extension from function.\n"); | |
bcc2cb3b RM |
952 | wait_time += (mbcp->mbox_out[1] >> 8) & 0x0000000f; |
953 | } else if (mbcp->mbox_out[0] == AEN_IDC_CMPLT) { | |
ae9540f7 | 954 | netif_err(qdev, drv, qdev->ndev, "IDC Success.\n"); |
bcc2cb3b RM |
955 | status = 0; |
956 | break; | |
957 | } else { | |
ae9540f7 JP |
958 | netif_err(qdev, drv, qdev->ndev, |
959 | "IDC: Invalid State 0x%.04x.\n", | |
960 | mbcp->mbox_out[0]); | |
bcc2cb3b RM |
961 | status = -EIO; |
962 | break; | |
963 | } | |
964 | } while (wait_time); | |
965 | ||
966 | return status; | |
967 | } | |
968 | ||
d8eb59dc RM |
969 | int ql_mb_set_led_cfg(struct ql_adapter *qdev, u32 led_config) |
970 | { | |
971 | struct mbox_params mbc; | |
972 | struct mbox_params *mbcp = &mbc; | |
973 | int status; | |
974 | ||
975 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
976 | ||
977 | mbcp->in_count = 2; | |
978 | mbcp->out_count = 1; | |
979 | ||
980 | mbcp->mbox_in[0] = MB_CMD_SET_LED_CFG; | |
981 | mbcp->mbox_in[1] = led_config; | |
982 | ||
983 | ||
984 | status = ql_mailbox_command(qdev, mbcp); | |
985 | if (status) | |
986 | return status; | |
987 | ||
988 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
ae9540f7 JP |
989 | netif_err(qdev, drv, qdev->ndev, |
990 | "Failed to set LED Configuration.\n"); | |
d8eb59dc RM |
991 | status = -EIO; |
992 | } | |
993 | ||
994 | return status; | |
995 | } | |
996 | ||
997 | int ql_mb_get_led_cfg(struct ql_adapter *qdev) | |
998 | { | |
999 | struct mbox_params mbc; | |
1000 | struct mbox_params *mbcp = &mbc; | |
1001 | int status; | |
1002 | ||
1003 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
1004 | ||
1005 | mbcp->in_count = 1; | |
1006 | mbcp->out_count = 2; | |
1007 | ||
1008 | mbcp->mbox_in[0] = MB_CMD_GET_LED_CFG; | |
1009 | ||
1010 | status = ql_mailbox_command(qdev, mbcp); | |
1011 | if (status) | |
1012 | return status; | |
1013 | ||
1014 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
ae9540f7 JP |
1015 | netif_err(qdev, drv, qdev->ndev, |
1016 | "Failed to get LED Configuration.\n"); | |
d8eb59dc RM |
1017 | status = -EIO; |
1018 | } else | |
1019 | qdev->led_config = mbcp->mbox_out[1]; | |
1020 | ||
1021 | return status; | |
1022 | } | |
1023 | ||
84087f4d RM |
1024 | int ql_mb_set_mgmnt_traffic_ctl(struct ql_adapter *qdev, u32 control) |
1025 | { | |
1026 | struct mbox_params mbc; | |
1027 | struct mbox_params *mbcp = &mbc; | |
1028 | int status; | |
1029 | ||
1030 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
1031 | ||
1032 | mbcp->in_count = 1; | |
1033 | mbcp->out_count = 2; | |
1034 | ||
1035 | mbcp->mbox_in[0] = MB_CMD_SET_MGMNT_TFK_CTL; | |
1036 | mbcp->mbox_in[1] = control; | |
1037 | ||
1038 | status = ql_mailbox_command(qdev, mbcp); | |
1039 | if (status) | |
1040 | return status; | |
1041 | ||
1042 | if (mbcp->mbox_out[0] == MB_CMD_STS_GOOD) | |
1043 | return status; | |
1044 | ||
1045 | if (mbcp->mbox_out[0] == MB_CMD_STS_INVLD_CMD) { | |
ae9540f7 JP |
1046 | netif_err(qdev, drv, qdev->ndev, |
1047 | "Command not supported by firmware.\n"); | |
84087f4d RM |
1048 | status = -EINVAL; |
1049 | } else if (mbcp->mbox_out[0] == MB_CMD_STS_ERR) { | |
1050 | /* This indicates that the firmware is | |
1051 | * already in the state we are trying to | |
1052 | * change it to. | |
1053 | */ | |
ae9540f7 JP |
1054 | netif_err(qdev, drv, qdev->ndev, |
1055 | "Command parameters make no change.\n"); | |
84087f4d RM |
1056 | } |
1057 | return status; | |
1058 | } | |
1059 | ||
1060 | /* Returns a negative error code or the mailbox command status. */ | |
1061 | static int ql_mb_get_mgmnt_traffic_ctl(struct ql_adapter *qdev, u32 *control) | |
1062 | { | |
1063 | struct mbox_params mbc; | |
1064 | struct mbox_params *mbcp = &mbc; | |
1065 | int status; | |
1066 | ||
1067 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
1068 | *control = 0; | |
1069 | ||
1070 | mbcp->in_count = 1; | |
1071 | mbcp->out_count = 1; | |
1072 | ||
1073 | mbcp->mbox_in[0] = MB_CMD_GET_MGMNT_TFK_CTL; | |
1074 | ||
1075 | status = ql_mailbox_command(qdev, mbcp); | |
1076 | if (status) | |
1077 | return status; | |
1078 | ||
1079 | if (mbcp->mbox_out[0] == MB_CMD_STS_GOOD) { | |
1080 | *control = mbcp->mbox_in[1]; | |
1081 | return status; | |
1082 | } | |
1083 | ||
1084 | if (mbcp->mbox_out[0] == MB_CMD_STS_INVLD_CMD) { | |
ae9540f7 JP |
1085 | netif_err(qdev, drv, qdev->ndev, |
1086 | "Command not supported by firmware.\n"); | |
84087f4d RM |
1087 | status = -EINVAL; |
1088 | } else if (mbcp->mbox_out[0] == MB_CMD_STS_ERR) { | |
ae9540f7 JP |
1089 | netif_err(qdev, drv, qdev->ndev, |
1090 | "Failed to get MPI traffic control.\n"); | |
84087f4d RM |
1091 | status = -EIO; |
1092 | } | |
1093 | return status; | |
1094 | } | |
1095 | ||
1096 | int ql_wait_fifo_empty(struct ql_adapter *qdev) | |
1097 | { | |
1098 | int count = 5; | |
1099 | u32 mgmnt_fifo_empty; | |
1100 | u32 nic_fifo_empty; | |
1101 | ||
1102 | do { | |
1103 | nic_fifo_empty = ql_read32(qdev, STS) & STS_NFE; | |
1104 | ql_mb_get_mgmnt_traffic_ctl(qdev, &mgmnt_fifo_empty); | |
1105 | mgmnt_fifo_empty &= MB_GET_MPI_TFK_FIFO_EMPTY; | |
1106 | if (nic_fifo_empty && mgmnt_fifo_empty) | |
1107 | return 0; | |
1108 | msleep(100); | |
1109 | } while (count-- > 0); | |
1110 | return -ETIMEDOUT; | |
1111 | } | |
1112 | ||
bcc2cb3b RM |
1113 | /* API called in work thread context to set new TX/RX |
1114 | * maximum frame size values to match MTU. | |
1115 | */ | |
1116 | static int ql_set_port_cfg(struct ql_adapter *qdev) | |
1117 | { | |
1118 | int status; | |
86aaf9ad | 1119 | rtnl_lock(); |
bcc2cb3b | 1120 | status = ql_mb_set_port_cfg(qdev); |
86aaf9ad | 1121 | rtnl_unlock(); |
bcc2cb3b RM |
1122 | if (status) |
1123 | return status; | |
1124 | status = ql_idc_wait(qdev); | |
1125 | return status; | |
1126 | } | |
1127 | ||
1128 | /* The following routines are worker threads that process | |
1129 | * events that may sleep waiting for completion. | |
1130 | */ | |
1131 | ||
1132 | /* This thread gets the maximum TX and RX frame size values | |
1133 | * from the firmware and, if necessary, changes them to match | |
1134 | * the MTU setting. | |
1135 | */ | |
1136 | void ql_mpi_port_cfg_work(struct work_struct *work) | |
1137 | { | |
1138 | struct ql_adapter *qdev = | |
1139 | container_of(work, struct ql_adapter, mpi_port_cfg_work.work); | |
bcc2cb3b RM |
1140 | int status; |
1141 | ||
86aaf9ad | 1142 | rtnl_lock(); |
bcc2cb3b | 1143 | status = ql_mb_get_port_cfg(qdev); |
86aaf9ad | 1144 | rtnl_unlock(); |
bcc2cb3b | 1145 | if (status) { |
ae9540f7 JP |
1146 | netif_err(qdev, drv, qdev->ndev, |
1147 | "Bug: Failed to get port config data.\n"); | |
bcc2cb3b RM |
1148 | goto err; |
1149 | } | |
1150 | ||
c8269b21 | 1151 | if (qdev->link_config & CFG_JUMBO_FRAME_SIZE && |
bcc2cb3b RM |
1152 | qdev->max_frame_size == |
1153 | CFG_DEFAULT_MAX_FRAME_SIZE) | |
1154 | goto end; | |
1155 | ||
1156 | qdev->link_config |= CFG_JUMBO_FRAME_SIZE; | |
1157 | qdev->max_frame_size = CFG_DEFAULT_MAX_FRAME_SIZE; | |
1158 | status = ql_set_port_cfg(qdev); | |
1159 | if (status) { | |
ae9540f7 JP |
1160 | netif_err(qdev, drv, qdev->ndev, |
1161 | "Bug: Failed to set port config data.\n"); | |
bcc2cb3b RM |
1162 | goto err; |
1163 | } | |
1164 | end: | |
1165 | clear_bit(QL_PORT_CFG, &qdev->flags); | |
1166 | return; | |
1167 | err: | |
1168 | ql_queue_fw_error(qdev); | |
1169 | goto end; | |
1170 | } | |
1171 | ||
2ee1e272 RM |
1172 | /* Process an inter-device request. This is issues by |
1173 | * the firmware in response to another function requesting | |
1174 | * a change to the port. We set a flag to indicate a change | |
1175 | * has been made and then send a mailbox command ACKing | |
1176 | * the change request. | |
1177 | */ | |
1178 | void ql_mpi_idc_work(struct work_struct *work) | |
1179 | { | |
1180 | struct ql_adapter *qdev = | |
1181 | container_of(work, struct ql_adapter, mpi_idc_work.work); | |
1182 | int status; | |
1183 | struct mbox_params *mbcp = &qdev->idc_mbc; | |
1184 | u32 aen; | |
1e34e307 | 1185 | int timeout; |
2ee1e272 | 1186 | |
1e34e307 | 1187 | rtnl_lock(); |
2ee1e272 | 1188 | aen = mbcp->mbox_out[1] >> 16; |
1e34e307 | 1189 | timeout = (mbcp->mbox_out[1] >> 8) & 0xf; |
2ee1e272 RM |
1190 | |
1191 | switch (aen) { | |
1192 | default: | |
ae9540f7 JP |
1193 | netif_err(qdev, drv, qdev->ndev, |
1194 | "Bug: Unhandled IDC action.\n"); | |
2ee1e272 RM |
1195 | break; |
1196 | case MB_CMD_PORT_RESET: | |
2ee1e272 | 1197 | case MB_CMD_STOP_FW: |
6a473308 | 1198 | ql_link_off(qdev); |
1e34e307 | 1199 | case MB_CMD_SET_PORT_CFG: |
2ee1e272 RM |
1200 | /* Signal the resulting link up AEN |
1201 | * that the frame routing and mac addr | |
1202 | * needs to be set. | |
1203 | * */ | |
1204 | set_bit(QL_CAM_RT_SET, &qdev->flags); | |
1e34e307 RM |
1205 | /* Do ACK if required */ |
1206 | if (timeout) { | |
1207 | status = ql_mb_idc_ack(qdev); | |
1208 | if (status) | |
ae9540f7 JP |
1209 | netif_err(qdev, drv, qdev->ndev, |
1210 | "Bug: No pending IDC!\n"); | |
1e34e307 | 1211 | } else { |
ae9540f7 JP |
1212 | netif_printk(qdev, drv, KERN_DEBUG, qdev->ndev, |
1213 | "IDC ACK not required\n"); | |
1e34e307 RM |
1214 | status = 0; /* success */ |
1215 | } | |
1216 | break; | |
1217 | ||
1218 | /* These sub-commands issued by another (FCoE) | |
1219 | * function are requesting to do an operation | |
1220 | * on the shared resource (MPI environment). | |
1221 | * We currently don't issue these so we just | |
1222 | * ACK the request. | |
1223 | */ | |
1224 | case MB_CMD_IOP_RESTART_MPI: | |
1225 | case MB_CMD_IOP_PREP_LINK_DOWN: | |
1226 | /* Drop the link, reload the routing | |
1227 | * table when link comes up. | |
1228 | */ | |
1229 | ql_link_off(qdev); | |
1230 | set_bit(QL_CAM_RT_SET, &qdev->flags); | |
1231 | /* Fall through. */ | |
1232 | case MB_CMD_IOP_DVR_START: | |
1233 | case MB_CMD_IOP_FLASH_ACC: | |
1234 | case MB_CMD_IOP_CORE_DUMP_MPI: | |
1235 | case MB_CMD_IOP_PREP_UPDATE_MPI: | |
1236 | case MB_CMD_IOP_COMP_UPDATE_MPI: | |
1237 | case MB_CMD_IOP_NONE: /* an IDC without params */ | |
1238 | /* Do ACK if required */ | |
1239 | if (timeout) { | |
1240 | status = ql_mb_idc_ack(qdev); | |
1241 | if (status) | |
ae9540f7 JP |
1242 | netif_err(qdev, drv, qdev->ndev, |
1243 | "Bug: No pending IDC!\n"); | |
1e34e307 | 1244 | } else { |
ae9540f7 JP |
1245 | netif_printk(qdev, drv, KERN_DEBUG, qdev->ndev, |
1246 | "IDC ACK not required\n"); | |
1e34e307 | 1247 | status = 0; /* success */ |
2ee1e272 | 1248 | } |
1e34e307 | 1249 | break; |
2ee1e272 | 1250 | } |
1e34e307 | 1251 | rtnl_unlock(); |
2ee1e272 RM |
1252 | } |
1253 | ||
c4e84bde RM |
1254 | void ql_mpi_work(struct work_struct *work) |
1255 | { | |
1256 | struct ql_adapter *qdev = | |
1257 | container_of(work, struct ql_adapter, mpi_work.work); | |
1258 | struct mbox_params mbc; | |
1259 | struct mbox_params *mbcp = &mbc; | |
d6f58c2e | 1260 | int err = 0; |
c4e84bde | 1261 | |
86aaf9ad | 1262 | rtnl_lock(); |
efd7d261 RM |
1263 | /* Begin polled mode for MPI */ |
1264 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); | |
c4e84bde | 1265 | |
125844ea RM |
1266 | while (ql_read32(qdev, STS) & STS_PI) { |
1267 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
1268 | mbcp->out_count = 1; | |
d6f58c2e RM |
1269 | /* Don't continue if an async event |
1270 | * did not complete properly. | |
1271 | */ | |
1272 | err = ql_mpi_handler(qdev, mbcp); | |
1273 | if (err) | |
1274 | break; | |
c4e84bde | 1275 | } |
125844ea | 1276 | |
efd7d261 RM |
1277 | /* End polled mode for MPI */ |
1278 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI); | |
86aaf9ad | 1279 | rtnl_unlock(); |
c4e84bde RM |
1280 | ql_enable_completion_interrupt(qdev, 0); |
1281 | } | |
1282 | ||
1283 | void ql_mpi_reset_work(struct work_struct *work) | |
1284 | { | |
1285 | struct ql_adapter *qdev = | |
1286 | container_of(work, struct ql_adapter, mpi_reset_work.work); | |
bcc2cb3b RM |
1287 | cancel_delayed_work_sync(&qdev->mpi_work); |
1288 | cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); | |
2ee1e272 | 1289 | cancel_delayed_work_sync(&qdev->mpi_idc_work); |
8aae2600 RM |
1290 | /* If we're not the dominant NIC function, |
1291 | * then there is nothing to do. | |
1292 | */ | |
1293 | if (!ql_own_firmware(qdev)) { | |
ae9540f7 | 1294 | netif_err(qdev, drv, qdev->ndev, "Don't own firmware!\n"); |
8aae2600 RM |
1295 | return; |
1296 | } | |
1297 | ||
1298 | if (!ql_core_dump(qdev, qdev->mpi_coredump)) { | |
ae9540f7 | 1299 | netif_err(qdev, drv, qdev->ndev, "Core is dumped!\n"); |
8aae2600 RM |
1300 | qdev->core_is_dumped = 1; |
1301 | queue_delayed_work(qdev->workqueue, | |
1302 | &qdev->mpi_core_to_log, 5 * HZ); | |
1303 | } | |
a2e809bb | 1304 | ql_soft_reset_mpi_risc(qdev); |
c4e84bde | 1305 | } |