Commit | Line | Data |
---|---|---|
c4e84bde RM |
1 | #include "qlge.h" |
2 | ||
ca0413b6 RM |
3 | static void ql_display_mb_sts(struct ql_adapter *qdev, |
4 | struct mbox_params *mbcp) | |
5 | { | |
6 | int i; | |
7 | static char *err_sts[] = { | |
8 | "Command Complete", | |
9 | "Command Not Supported", | |
10 | "Host Interface Error", | |
11 | "Checksum Error", | |
12 | "Unused Completion Status", | |
13 | "Test Failed", | |
14 | "Command Parameter Error"}; | |
15 | ||
16 | QPRINTK(qdev, DRV, DEBUG, "%s.\n", | |
17 | err_sts[mbcp->mbox_out[0] & 0x0000000f]); | |
18 | for (i = 0; i < mbcp->out_count; i++) | |
19 | QPRINTK(qdev, DRV, DEBUG, "mbox_out[%d] = 0x%.08x.\n", | |
20 | i, mbcp->mbox_out[i]); | |
21 | } | |
22 | ||
a2e809bb | 23 | int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data) |
c4e84bde RM |
24 | { |
25 | int status; | |
26 | /* wait for reg to come ready */ | |
27 | status = ql_wait_reg_rdy(qdev, PROC_ADDR, PROC_ADDR_RDY, PROC_ADDR_ERR); | |
28 | if (status) | |
29 | goto exit; | |
30 | /* set up for reg read */ | |
31 | ql_write32(qdev, PROC_ADDR, reg | PROC_ADDR_R); | |
32 | /* wait for reg to come ready */ | |
33 | status = ql_wait_reg_rdy(qdev, PROC_ADDR, PROC_ADDR_RDY, PROC_ADDR_ERR); | |
34 | if (status) | |
35 | goto exit; | |
36 | /* get the data */ | |
37 | *data = ql_read32(qdev, PROC_DATA); | |
38 | exit: | |
39 | return status; | |
40 | } | |
41 | ||
a2e809bb RM |
42 | int ql_write_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 data) |
43 | { | |
44 | int status = 0; | |
45 | /* wait for reg to come ready */ | |
46 | status = ql_wait_reg_rdy(qdev, PROC_ADDR, PROC_ADDR_RDY, PROC_ADDR_ERR); | |
47 | if (status) | |
48 | goto exit; | |
49 | /* write the data to the data reg */ | |
50 | ql_write32(qdev, PROC_DATA, data); | |
51 | /* trigger the write */ | |
52 | ql_write32(qdev, PROC_ADDR, reg); | |
53 | /* wait for reg to come ready */ | |
54 | status = ql_wait_reg_rdy(qdev, PROC_ADDR, PROC_ADDR_RDY, PROC_ADDR_ERR); | |
55 | if (status) | |
56 | goto exit; | |
57 | exit: | |
58 | return status; | |
59 | } | |
60 | ||
61 | int ql_soft_reset_mpi_risc(struct ql_adapter *qdev) | |
62 | { | |
63 | int status; | |
64 | status = ql_write_mpi_reg(qdev, 0x00001010, 1); | |
65 | return status; | |
66 | } | |
67 | ||
2f22d22e | 68 | static int ql_get_mb_sts(struct ql_adapter *qdev, struct mbox_params *mbcp) |
c4e84bde RM |
69 | { |
70 | int i, status; | |
71 | ||
72 | status = ql_sem_spinlock(qdev, SEM_PROC_REG_MASK); | |
73 | if (status) | |
74 | return -EBUSY; | |
75 | for (i = 0; i < mbcp->out_count; i++) { | |
76 | status = | |
a2e809bb | 77 | ql_read_mpi_reg(qdev, qdev->mailbox_out + i, |
c4e84bde RM |
78 | &mbcp->mbox_out[i]); |
79 | if (status) { | |
80 | QPRINTK(qdev, DRV, ERR, "Failed mailbox read.\n"); | |
81 | break; | |
82 | } | |
83 | } | |
84 | ql_sem_unlock(qdev, SEM_PROC_REG_MASK); /* does flush too */ | |
85 | return status; | |
86 | } | |
87 | ||
ca0413b6 RM |
88 | /* Wait for a single mailbox command to complete. |
89 | * Returns zero on success. | |
90 | */ | |
91 | static int ql_wait_mbx_cmd_cmplt(struct ql_adapter *qdev) | |
92 | { | |
93 | int count = 50; /* TODO: arbitrary for now. */ | |
94 | u32 value; | |
95 | ||
96 | do { | |
97 | value = ql_read32(qdev, STS); | |
98 | if (value & STS_PI) | |
99 | return 0; | |
100 | udelay(UDELAY_DELAY); /* 10us */ | |
101 | } while (--count); | |
102 | return -ETIMEDOUT; | |
103 | } | |
104 | ||
105 | /* Execute a single mailbox command. | |
106 | * Caller must hold PROC_ADDR semaphore. | |
107 | */ | |
108 | static int ql_exec_mb_cmd(struct ql_adapter *qdev, struct mbox_params *mbcp) | |
109 | { | |
110 | int i, status; | |
111 | ||
112 | /* | |
113 | * Make sure there's nothing pending. | |
114 | * This shouldn't happen. | |
115 | */ | |
116 | if (ql_read32(qdev, CSR) & CSR_HRI) | |
117 | return -EIO; | |
118 | ||
119 | status = ql_sem_spinlock(qdev, SEM_PROC_REG_MASK); | |
120 | if (status) | |
121 | return status; | |
122 | ||
123 | /* | |
124 | * Fill the outbound mailboxes. | |
125 | */ | |
126 | for (i = 0; i < mbcp->in_count; i++) { | |
127 | status = ql_write_mpi_reg(qdev, qdev->mailbox_in + i, | |
128 | mbcp->mbox_in[i]); | |
129 | if (status) | |
130 | goto end; | |
131 | } | |
132 | /* | |
133 | * Wake up the MPI firmware. | |
134 | */ | |
135 | ql_write32(qdev, CSR, CSR_CMD_SET_H2R_INT); | |
136 | end: | |
137 | ql_sem_unlock(qdev, SEM_PROC_REG_MASK); | |
138 | return status; | |
139 | } | |
140 | ||
2ee1e272 RM |
141 | /* We are being asked by firmware to accept |
142 | * a change to the port. This is only | |
143 | * a change to max frame sizes (Tx/Rx), pause | |
98a1708d | 144 | * parameters, or loopback mode. We wake up a worker |
2ee1e272 RM |
145 | * to handler processing this since a mailbox command |
146 | * will need to be sent to ACK the request. | |
147 | */ | |
148 | static int ql_idc_req_aen(struct ql_adapter *qdev) | |
149 | { | |
150 | int status; | |
151 | struct mbox_params *mbcp = &qdev->idc_mbc; | |
152 | ||
153 | QPRINTK(qdev, DRV, ERR, "Enter!\n"); | |
154 | /* Get the status data and start up a thread to | |
155 | * handle the request. | |
156 | */ | |
157 | mbcp = &qdev->idc_mbc; | |
158 | mbcp->out_count = 4; | |
159 | status = ql_get_mb_sts(qdev, mbcp); | |
160 | if (status) { | |
161 | QPRINTK(qdev, DRV, ERR, | |
162 | "Could not read MPI, resetting ASIC!\n"); | |
163 | ql_queue_asic_error(qdev); | |
164 | } else { | |
165 | /* Begin polled mode early so | |
166 | * we don't get another interrupt | |
167 | * when we leave mpi_worker. | |
168 | */ | |
169 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); | |
170 | queue_delayed_work(qdev->workqueue, &qdev->mpi_idc_work, 0); | |
171 | } | |
172 | return status; | |
173 | } | |
174 | ||
bcc2cb3b RM |
175 | /* Process an inter-device event completion. |
176 | * If good, signal the caller's completion. | |
177 | */ | |
178 | static int ql_idc_cmplt_aen(struct ql_adapter *qdev) | |
179 | { | |
180 | int status; | |
181 | struct mbox_params *mbcp = &qdev->idc_mbc; | |
182 | mbcp->out_count = 4; | |
183 | status = ql_get_mb_sts(qdev, mbcp); | |
184 | if (status) { | |
185 | QPRINTK(qdev, DRV, ERR, | |
186 | "Could not read MPI, resetting RISC!\n"); | |
187 | ql_queue_fw_error(qdev); | |
188 | } else | |
189 | /* Wake up the sleeping mpi_idc_work thread that is | |
190 | * waiting for this event. | |
191 | */ | |
192 | complete(&qdev->ide_completion); | |
193 | ||
194 | return status; | |
195 | } | |
5700abe9 | 196 | |
c4e84bde RM |
197 | static void ql_link_up(struct ql_adapter *qdev, struct mbox_params *mbcp) |
198 | { | |
5700abe9 | 199 | int status; |
c4e84bde RM |
200 | mbcp->out_count = 2; |
201 | ||
5700abe9 RM |
202 | status = ql_get_mb_sts(qdev, mbcp); |
203 | if (status) { | |
204 | QPRINTK(qdev, DRV, ERR, | |
205 | "%s: Could not get mailbox status.\n", __func__); | |
206 | return; | |
207 | } | |
c4e84bde RM |
208 | |
209 | qdev->link_status = mbcp->mbox_out[1]; | |
210 | QPRINTK(qdev, DRV, ERR, "Link Up.\n"); | |
5700abe9 | 211 | |
2ee1e272 RM |
212 | /* If we're coming back from an IDC event |
213 | * then set up the CAM and frame routing. | |
214 | */ | |
215 | if (test_bit(QL_CAM_RT_SET, &qdev->flags)) { | |
216 | status = ql_cam_route_initialize(qdev); | |
217 | if (status) { | |
218 | QPRINTK(qdev, IFUP, ERR, | |
219 | "Failed to init CAM/Routing tables.\n"); | |
220 | return; | |
221 | } else | |
222 | clear_bit(QL_CAM_RT_SET, &qdev->flags); | |
223 | } | |
224 | ||
225 | /* Queue up a worker to check the frame | |
226 | * size information, and fix it if it's not | |
227 | * to our liking. | |
228 | */ | |
229 | if (!test_bit(QL_PORT_CFG, &qdev->flags)) { | |
230 | QPRINTK(qdev, DRV, ERR, "Queue Port Config Worker!\n"); | |
231 | set_bit(QL_PORT_CFG, &qdev->flags); | |
232 | /* Begin polled mode early so | |
233 | * we don't get another interrupt | |
234 | * when we leave mpi_worker dpc. | |
235 | */ | |
236 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); | |
237 | queue_delayed_work(qdev->workqueue, | |
238 | &qdev->mpi_port_cfg_work, 0); | |
239 | } | |
240 | ||
5700abe9 | 241 | netif_carrier_on(qdev->ndev); |
c4e84bde RM |
242 | } |
243 | ||
244 | static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp) | |
245 | { | |
11d9fe68 RM |
246 | int status; |
247 | ||
c4e84bde RM |
248 | mbcp->out_count = 3; |
249 | ||
11d9fe68 RM |
250 | status = ql_get_mb_sts(qdev, mbcp); |
251 | if (status) | |
252 | QPRINTK(qdev, DRV, ERR, "Link down AEN broken!\n"); | |
c4e84bde | 253 | |
11d9fe68 | 254 | netif_carrier_off(qdev->ndev); |
c4e84bde RM |
255 | } |
256 | ||
eae6b58f RM |
257 | static int ql_sfp_in(struct ql_adapter *qdev, struct mbox_params *mbcp) |
258 | { | |
259 | int status; | |
260 | ||
261 | mbcp->out_count = 5; | |
262 | ||
263 | status = ql_get_mb_sts(qdev, mbcp); | |
264 | if (status) | |
265 | QPRINTK(qdev, DRV, ERR, "SFP in AEN broken!\n"); | |
266 | else | |
267 | QPRINTK(qdev, DRV, ERR, "SFP insertion detected.\n"); | |
268 | ||
269 | return status; | |
270 | } | |
271 | ||
272 | static int ql_sfp_out(struct ql_adapter *qdev, struct mbox_params *mbcp) | |
273 | { | |
274 | int status; | |
275 | ||
276 | mbcp->out_count = 1; | |
277 | ||
278 | status = ql_get_mb_sts(qdev, mbcp); | |
279 | if (status) | |
280 | QPRINTK(qdev, DRV, ERR, "SFP out AEN broken!\n"); | |
281 | else | |
282 | QPRINTK(qdev, DRV, ERR, "SFP removal detected.\n"); | |
283 | ||
284 | return status; | |
285 | } | |
286 | ||
fc1f9ea5 RM |
287 | static int ql_aen_lost(struct ql_adapter *qdev, struct mbox_params *mbcp) |
288 | { | |
289 | int status; | |
290 | ||
291 | mbcp->out_count = 6; | |
292 | ||
293 | status = ql_get_mb_sts(qdev, mbcp); | |
294 | if (status) | |
295 | QPRINTK(qdev, DRV, ERR, "Lost AEN broken!\n"); | |
296 | else { | |
297 | int i; | |
298 | QPRINTK(qdev, DRV, ERR, "Lost AEN detected.\n"); | |
299 | for (i = 0; i < mbcp->out_count; i++) | |
300 | QPRINTK(qdev, DRV, ERR, "mbox_out[%d] = 0x%.08x.\n", | |
301 | i, mbcp->mbox_out[i]); | |
302 | ||
303 | } | |
304 | ||
305 | return status; | |
306 | } | |
307 | ||
c4e84bde RM |
308 | static void ql_init_fw_done(struct ql_adapter *qdev, struct mbox_params *mbcp) |
309 | { | |
f56b54f5 RM |
310 | int status; |
311 | ||
c4e84bde RM |
312 | mbcp->out_count = 2; |
313 | ||
f56b54f5 RM |
314 | status = ql_get_mb_sts(qdev, mbcp); |
315 | if (status) { | |
c4e84bde | 316 | QPRINTK(qdev, DRV, ERR, "Firmware did not initialize!\n"); |
f56b54f5 RM |
317 | } else { |
318 | QPRINTK(qdev, DRV, ERR, "Firmware Revision = 0x%.08x.\n", | |
319 | mbcp->mbox_out[1]); | |
320 | status = ql_cam_route_initialize(qdev); | |
321 | if (status) | |
322 | QPRINTK(qdev, IFUP, ERR, | |
323 | "Failed to init CAM/Routing tables.\n"); | |
c4e84bde | 324 | } |
c4e84bde RM |
325 | } |
326 | ||
125844ea RM |
327 | /* Process an async event and clear it unless it's an |
328 | * error condition. | |
329 | * This can get called iteratively from the mpi_work thread | |
330 | * when events arrive via an interrupt. | |
331 | * It also gets called when a mailbox command is polling for | |
332 | * it's completion. */ | |
333 | static int ql_mpi_handler(struct ql_adapter *qdev, struct mbox_params *mbcp) | |
334 | { | |
335 | int status; | |
ca0413b6 | 336 | int orig_count = mbcp->out_count; |
125844ea RM |
337 | |
338 | /* Just get mailbox zero for now. */ | |
339 | mbcp->out_count = 1; | |
340 | status = ql_get_mb_sts(qdev, mbcp); | |
341 | if (status) { | |
342 | QPRINTK(qdev, DRV, ERR, | |
343 | "Could not read MPI, resetting ASIC!\n"); | |
344 | ql_queue_asic_error(qdev); | |
345 | goto end; | |
346 | } | |
347 | ||
348 | switch (mbcp->mbox_out[0]) { | |
349 | ||
ca0413b6 RM |
350 | /* This case is only active when we arrive here |
351 | * as a result of issuing a mailbox command to | |
352 | * the firmware. | |
353 | */ | |
354 | case MB_CMD_STS_INTRMDT: | |
355 | case MB_CMD_STS_GOOD: | |
356 | case MB_CMD_STS_INVLD_CMD: | |
357 | case MB_CMD_STS_XFC_ERR: | |
358 | case MB_CMD_STS_CSUM_ERR: | |
359 | case MB_CMD_STS_ERR: | |
360 | case MB_CMD_STS_PARAM_ERR: | |
361 | /* We can only get mailbox status if we're polling from an | |
362 | * unfinished command. Get the rest of the status data and | |
363 | * return back to the caller. | |
364 | * We only end up here when we're polling for a mailbox | |
365 | * command completion. | |
366 | */ | |
367 | mbcp->out_count = orig_count; | |
368 | status = ql_get_mb_sts(qdev, mbcp); | |
369 | return status; | |
370 | ||
2ee1e272 RM |
371 | /* We are being asked by firmware to accept |
372 | * a change to the port. This is only | |
373 | * a change to max frame sizes (Tx/Rx), pause | |
98a1708d | 374 | * parameters, or loopback mode. |
2ee1e272 RM |
375 | */ |
376 | case AEN_IDC_REQ: | |
377 | status = ql_idc_req_aen(qdev); | |
378 | break; | |
379 | ||
bcc2cb3b RM |
380 | /* Process and inbound IDC event. |
381 | * This will happen when we're trying to | |
382 | * change tx/rx max frame size, change pause | |
98a1708d | 383 | * parameters or loopback mode. |
bcc2cb3b RM |
384 | */ |
385 | case AEN_IDC_CMPLT: | |
386 | case AEN_IDC_EXT: | |
387 | status = ql_idc_cmplt_aen(qdev); | |
388 | break; | |
389 | ||
125844ea RM |
390 | case AEN_LINK_UP: |
391 | ql_link_up(qdev, mbcp); | |
392 | break; | |
393 | ||
394 | case AEN_LINK_DOWN: | |
395 | ql_link_down(qdev, mbcp); | |
396 | break; | |
397 | ||
398 | case AEN_FW_INIT_DONE: | |
f56b54f5 RM |
399 | /* If we're in process on executing the firmware, |
400 | * then convert the status to normal mailbox status. | |
401 | */ | |
402 | if (mbcp->mbox_in[0] == MB_CMD_EX_FW) { | |
403 | mbcp->out_count = orig_count; | |
404 | status = ql_get_mb_sts(qdev, mbcp); | |
405 | mbcp->mbox_out[0] = MB_CMD_STS_GOOD; | |
406 | return status; | |
407 | } | |
125844ea RM |
408 | ql_init_fw_done(qdev, mbcp); |
409 | break; | |
410 | ||
eae6b58f RM |
411 | case AEN_AEN_SFP_IN: |
412 | ql_sfp_in(qdev, mbcp); | |
413 | break; | |
414 | ||
415 | case AEN_AEN_SFP_OUT: | |
416 | ql_sfp_out(qdev, mbcp); | |
417 | break; | |
418 | ||
7c92191c RM |
419 | /* This event can arrive at boot time or after an |
420 | * MPI reset if the firmware failed to initialize. | |
421 | */ | |
125844ea | 422 | case AEN_FW_INIT_FAIL: |
7c92191c RM |
423 | /* If we're in process on executing the firmware, |
424 | * then convert the status to normal mailbox status. | |
425 | */ | |
426 | if (mbcp->mbox_in[0] == MB_CMD_EX_FW) { | |
427 | mbcp->out_count = orig_count; | |
428 | status = ql_get_mb_sts(qdev, mbcp); | |
429 | mbcp->mbox_out[0] = MB_CMD_STS_ERR; | |
430 | return status; | |
431 | } | |
432 | QPRINTK(qdev, DRV, ERR, | |
433 | "Firmware initialization failed.\n"); | |
434 | status = -EIO; | |
435 | ql_queue_fw_error(qdev); | |
436 | break; | |
437 | ||
125844ea | 438 | case AEN_SYS_ERR: |
bb667670 RM |
439 | QPRINTK(qdev, DRV, ERR, |
440 | "System Error.\n"); | |
125844ea | 441 | ql_queue_fw_error(qdev); |
bb667670 | 442 | status = -EIO; |
125844ea RM |
443 | break; |
444 | ||
fc1f9ea5 RM |
445 | case AEN_AEN_LOST: |
446 | ql_aen_lost(qdev, mbcp); | |
447 | break; | |
448 | ||
125844ea RM |
449 | default: |
450 | QPRINTK(qdev, DRV, ERR, | |
451 | "Unsupported AE %.08x.\n", mbcp->mbox_out[0]); | |
452 | /* Clear the MPI firmware status. */ | |
453 | } | |
454 | end: | |
455 | ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT); | |
456 | return status; | |
457 | } | |
458 | ||
ca0413b6 RM |
459 | /* Execute a single mailbox command. |
460 | * mbcp is a pointer to an array of u32. Each | |
461 | * element in the array contains the value for it's | |
462 | * respective mailbox register. | |
463 | */ | |
464 | static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) | |
465 | { | |
466 | int status, count; | |
467 | ||
468 | mutex_lock(&qdev->mpi_mutex); | |
469 | ||
470 | /* Begin polled mode for MPI */ | |
471 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); | |
472 | ||
473 | /* Load the mailbox registers and wake up MPI RISC. */ | |
474 | status = ql_exec_mb_cmd(qdev, mbcp); | |
475 | if (status) | |
476 | goto end; | |
477 | ||
478 | ||
479 | /* If we're generating a system error, then there's nothing | |
480 | * to wait for. | |
481 | */ | |
482 | if (mbcp->mbox_in[0] == MB_CMD_MAKE_SYS_ERR) | |
483 | goto end; | |
484 | ||
485 | /* Wait for the command to complete. We loop | |
486 | * here because some AEN might arrive while | |
487 | * we're waiting for the mailbox command to | |
488 | * complete. If more than 5 arrive then we can | |
489 | * assume something is wrong. */ | |
490 | count = 5; | |
491 | do { | |
492 | /* Wait for the interrupt to come in. */ | |
493 | status = ql_wait_mbx_cmd_cmplt(qdev); | |
494 | if (status) | |
495 | goto end; | |
496 | ||
497 | /* Process the event. If it's an AEN, it | |
498 | * will be handled in-line or a worker | |
499 | * will be spawned. If it's our completion | |
500 | * we will catch it below. | |
501 | */ | |
502 | status = ql_mpi_handler(qdev, mbcp); | |
503 | if (status) | |
504 | goto end; | |
505 | ||
506 | /* It's either the completion for our mailbox | |
507 | * command complete or an AEN. If it's our | |
508 | * completion then get out. | |
509 | */ | |
510 | if (((mbcp->mbox_out[0] & 0x0000f000) == | |
511 | MB_CMD_STS_GOOD) || | |
512 | ((mbcp->mbox_out[0] & 0x0000f000) == | |
513 | MB_CMD_STS_INTRMDT)) | |
514 | break; | |
515 | } while (--count); | |
516 | ||
517 | if (!count) { | |
518 | QPRINTK(qdev, DRV, ERR, | |
519 | "Timed out waiting for mailbox complete.\n"); | |
520 | status = -ETIMEDOUT; | |
521 | goto end; | |
522 | } | |
523 | ||
524 | /* Now we can clear the interrupt condition | |
525 | * and look at our status. | |
526 | */ | |
527 | ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT); | |
528 | ||
529 | if (((mbcp->mbox_out[0] & 0x0000f000) != | |
530 | MB_CMD_STS_GOOD) && | |
531 | ((mbcp->mbox_out[0] & 0x0000f000) != | |
532 | MB_CMD_STS_INTRMDT)) { | |
533 | ql_display_mb_sts(qdev, mbcp); | |
534 | status = -EIO; | |
535 | } | |
536 | end: | |
537 | mutex_unlock(&qdev->mpi_mutex); | |
538 | /* End polled mode for MPI */ | |
539 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI); | |
540 | return status; | |
541 | } | |
542 | ||
543 | /* Get functional state for MPI firmware. | |
544 | * Returns zero on success. | |
545 | */ | |
546 | int ql_mb_get_fw_state(struct ql_adapter *qdev) | |
547 | { | |
548 | struct mbox_params mbc; | |
549 | struct mbox_params *mbcp = &mbc; | |
550 | int status = 0; | |
551 | ||
552 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
553 | ||
554 | mbcp->in_count = 1; | |
555 | mbcp->out_count = 2; | |
556 | ||
557 | mbcp->mbox_in[0] = MB_CMD_GET_FW_STATE; | |
558 | ||
559 | status = ql_mailbox_command(qdev, mbcp); | |
560 | if (status) | |
561 | return status; | |
562 | ||
563 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
564 | QPRINTK(qdev, DRV, ERR, | |
565 | "Failed Get Firmware State.\n"); | |
566 | status = -EIO; | |
567 | } | |
568 | ||
569 | /* If bit zero is set in mbx 1 then the firmware is | |
570 | * running, but not initialized. This should never | |
571 | * happen. | |
572 | */ | |
573 | if (mbcp->mbox_out[1] & 1) { | |
574 | QPRINTK(qdev, DRV, ERR, | |
575 | "Firmware waiting for initialization.\n"); | |
576 | status = -EIO; | |
577 | } | |
578 | ||
579 | return status; | |
580 | } | |
581 | ||
2ee1e272 RM |
582 | /* Send and ACK mailbox command to the firmware to |
583 | * let it continue with the change. | |
584 | */ | |
585 | int ql_mb_idc_ack(struct ql_adapter *qdev) | |
586 | { | |
587 | struct mbox_params mbc; | |
588 | struct mbox_params *mbcp = &mbc; | |
589 | int status = 0; | |
590 | ||
591 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
592 | ||
593 | mbcp->in_count = 5; | |
594 | mbcp->out_count = 1; | |
595 | ||
596 | mbcp->mbox_in[0] = MB_CMD_IDC_ACK; | |
597 | mbcp->mbox_in[1] = qdev->idc_mbc.mbox_out[1]; | |
598 | mbcp->mbox_in[2] = qdev->idc_mbc.mbox_out[2]; | |
599 | mbcp->mbox_in[3] = qdev->idc_mbc.mbox_out[3]; | |
600 | mbcp->mbox_in[4] = qdev->idc_mbc.mbox_out[4]; | |
601 | ||
602 | status = ql_mailbox_command(qdev, mbcp); | |
603 | if (status) | |
604 | return status; | |
605 | ||
606 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
607 | QPRINTK(qdev, DRV, ERR, | |
608 | "Failed IDC ACK send.\n"); | |
609 | status = -EIO; | |
610 | } | |
611 | return status; | |
612 | } | |
613 | ||
bcc2cb3b RM |
614 | /* Get link settings and maximum frame size settings |
615 | * for the current port. | |
616 | * Most likely will block. | |
617 | */ | |
618 | static int ql_mb_set_port_cfg(struct ql_adapter *qdev) | |
619 | { | |
620 | struct mbox_params mbc; | |
621 | struct mbox_params *mbcp = &mbc; | |
622 | int status = 0; | |
623 | ||
624 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
625 | ||
626 | mbcp->in_count = 3; | |
627 | mbcp->out_count = 1; | |
628 | ||
629 | mbcp->mbox_in[0] = MB_CMD_SET_PORT_CFG; | |
630 | mbcp->mbox_in[1] = qdev->link_config; | |
631 | mbcp->mbox_in[2] = qdev->max_frame_size; | |
632 | ||
633 | ||
634 | status = ql_mailbox_command(qdev, mbcp); | |
635 | if (status) | |
636 | return status; | |
637 | ||
638 | if (mbcp->mbox_out[0] == MB_CMD_STS_INTRMDT) { | |
639 | QPRINTK(qdev, DRV, ERR, | |
640 | "Port Config sent, wait for IDC.\n"); | |
641 | } else if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
642 | QPRINTK(qdev, DRV, ERR, | |
643 | "Failed Set Port Configuration.\n"); | |
644 | status = -EIO; | |
645 | } | |
646 | return status; | |
647 | } | |
648 | ||
649 | /* Get link settings and maximum frame size settings | |
650 | * for the current port. | |
651 | * Most likely will block. | |
652 | */ | |
653 | static int ql_mb_get_port_cfg(struct ql_adapter *qdev) | |
654 | { | |
655 | struct mbox_params mbc; | |
656 | struct mbox_params *mbcp = &mbc; | |
657 | int status = 0; | |
658 | ||
659 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
660 | ||
661 | mbcp->in_count = 1; | |
662 | mbcp->out_count = 3; | |
663 | ||
664 | mbcp->mbox_in[0] = MB_CMD_GET_PORT_CFG; | |
665 | ||
666 | status = ql_mailbox_command(qdev, mbcp); | |
667 | if (status) | |
668 | return status; | |
669 | ||
670 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
671 | QPRINTK(qdev, DRV, ERR, | |
672 | "Failed Get Port Configuration.\n"); | |
673 | status = -EIO; | |
674 | } else { | |
675 | QPRINTK(qdev, DRV, DEBUG, | |
676 | "Passed Get Port Configuration.\n"); | |
677 | qdev->link_config = mbcp->mbox_out[1]; | |
678 | qdev->max_frame_size = mbcp->mbox_out[2]; | |
679 | } | |
680 | return status; | |
681 | } | |
682 | ||
683 | /* IDC - Inter Device Communication... | |
684 | * Some firmware commands require consent of adjacent FCOE | |
685 | * function. This function waits for the OK, or a | |
686 | * counter-request for a little more time.i | |
687 | * The firmware will complete the request if the other | |
688 | * function doesn't respond. | |
689 | */ | |
690 | static int ql_idc_wait(struct ql_adapter *qdev) | |
691 | { | |
692 | int status = -ETIMEDOUT; | |
693 | long wait_time = 1 * HZ; | |
694 | struct mbox_params *mbcp = &qdev->idc_mbc; | |
695 | do { | |
696 | /* Wait here for the command to complete | |
697 | * via the IDC process. | |
698 | */ | |
699 | wait_time = | |
700 | wait_for_completion_timeout(&qdev->ide_completion, | |
701 | wait_time); | |
702 | if (!wait_time) { | |
703 | QPRINTK(qdev, DRV, ERR, | |
704 | "IDC Timeout.\n"); | |
705 | break; | |
706 | } | |
707 | /* Now examine the response from the IDC process. | |
708 | * We might have a good completion or a request for | |
709 | * more wait time. | |
710 | */ | |
711 | if (mbcp->mbox_out[0] == AEN_IDC_EXT) { | |
712 | QPRINTK(qdev, DRV, ERR, | |
713 | "IDC Time Extension from function.\n"); | |
714 | wait_time += (mbcp->mbox_out[1] >> 8) & 0x0000000f; | |
715 | } else if (mbcp->mbox_out[0] == AEN_IDC_CMPLT) { | |
716 | QPRINTK(qdev, DRV, ERR, | |
717 | "IDC Success.\n"); | |
718 | status = 0; | |
719 | break; | |
720 | } else { | |
721 | QPRINTK(qdev, DRV, ERR, | |
722 | "IDC: Invalid State 0x%.04x.\n", | |
723 | mbcp->mbox_out[0]); | |
724 | status = -EIO; | |
725 | break; | |
726 | } | |
727 | } while (wait_time); | |
728 | ||
729 | return status; | |
730 | } | |
731 | ||
732 | /* API called in work thread context to set new TX/RX | |
733 | * maximum frame size values to match MTU. | |
734 | */ | |
735 | static int ql_set_port_cfg(struct ql_adapter *qdev) | |
736 | { | |
737 | int status; | |
738 | status = ql_mb_set_port_cfg(qdev); | |
739 | if (status) | |
740 | return status; | |
741 | status = ql_idc_wait(qdev); | |
742 | return status; | |
743 | } | |
744 | ||
745 | /* The following routines are worker threads that process | |
746 | * events that may sleep waiting for completion. | |
747 | */ | |
748 | ||
749 | /* This thread gets the maximum TX and RX frame size values | |
750 | * from the firmware and, if necessary, changes them to match | |
751 | * the MTU setting. | |
752 | */ | |
753 | void ql_mpi_port_cfg_work(struct work_struct *work) | |
754 | { | |
755 | struct ql_adapter *qdev = | |
756 | container_of(work, struct ql_adapter, mpi_port_cfg_work.work); | |
757 | struct net_device *ndev = qdev->ndev; | |
758 | int status; | |
759 | ||
760 | status = ql_mb_get_port_cfg(qdev); | |
761 | if (status) { | |
762 | QPRINTK(qdev, DRV, ERR, | |
763 | "Bug: Failed to get port config data.\n"); | |
764 | goto err; | |
765 | } | |
766 | ||
767 | if (ndev->mtu <= 2500) | |
768 | goto end; | |
769 | else if (qdev->link_config & CFG_JUMBO_FRAME_SIZE && | |
770 | qdev->max_frame_size == | |
771 | CFG_DEFAULT_MAX_FRAME_SIZE) | |
772 | goto end; | |
773 | ||
774 | qdev->link_config |= CFG_JUMBO_FRAME_SIZE; | |
775 | qdev->max_frame_size = CFG_DEFAULT_MAX_FRAME_SIZE; | |
776 | status = ql_set_port_cfg(qdev); | |
777 | if (status) { | |
778 | QPRINTK(qdev, DRV, ERR, | |
779 | "Bug: Failed to set port config data.\n"); | |
780 | goto err; | |
781 | } | |
782 | end: | |
783 | clear_bit(QL_PORT_CFG, &qdev->flags); | |
784 | return; | |
785 | err: | |
786 | ql_queue_fw_error(qdev); | |
787 | goto end; | |
788 | } | |
789 | ||
2ee1e272 RM |
790 | /* Process an inter-device request. This is issues by |
791 | * the firmware in response to another function requesting | |
792 | * a change to the port. We set a flag to indicate a change | |
793 | * has been made and then send a mailbox command ACKing | |
794 | * the change request. | |
795 | */ | |
796 | void ql_mpi_idc_work(struct work_struct *work) | |
797 | { | |
798 | struct ql_adapter *qdev = | |
799 | container_of(work, struct ql_adapter, mpi_idc_work.work); | |
800 | int status; | |
801 | struct mbox_params *mbcp = &qdev->idc_mbc; | |
802 | u32 aen; | |
803 | ||
804 | aen = mbcp->mbox_out[1] >> 16; | |
805 | ||
806 | switch (aen) { | |
807 | default: | |
808 | QPRINTK(qdev, DRV, ERR, | |
809 | "Bug: Unhandled IDC action.\n"); | |
810 | break; | |
811 | case MB_CMD_PORT_RESET: | |
812 | case MB_CMD_SET_PORT_CFG: | |
813 | case MB_CMD_STOP_FW: | |
814 | netif_carrier_off(qdev->ndev); | |
815 | /* Signal the resulting link up AEN | |
816 | * that the frame routing and mac addr | |
817 | * needs to be set. | |
818 | * */ | |
819 | set_bit(QL_CAM_RT_SET, &qdev->flags); | |
820 | status = ql_mb_idc_ack(qdev); | |
821 | if (status) { | |
822 | QPRINTK(qdev, DRV, ERR, | |
823 | "Bug: No pending IDC!\n"); | |
824 | } | |
825 | } | |
826 | } | |
827 | ||
c4e84bde RM |
828 | void ql_mpi_work(struct work_struct *work) |
829 | { | |
830 | struct ql_adapter *qdev = | |
831 | container_of(work, struct ql_adapter, mpi_work.work); | |
832 | struct mbox_params mbc; | |
833 | struct mbox_params *mbcp = &mbc; | |
c4e84bde | 834 | |
125844ea | 835 | mutex_lock(&qdev->mpi_mutex); |
c4e84bde | 836 | |
125844ea RM |
837 | while (ql_read32(qdev, STS) & STS_PI) { |
838 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
839 | mbcp->out_count = 1; | |
840 | ql_mpi_handler(qdev, mbcp); | |
c4e84bde | 841 | } |
125844ea RM |
842 | |
843 | mutex_unlock(&qdev->mpi_mutex); | |
c4e84bde RM |
844 | ql_enable_completion_interrupt(qdev, 0); |
845 | } | |
846 | ||
847 | void ql_mpi_reset_work(struct work_struct *work) | |
848 | { | |
849 | struct ql_adapter *qdev = | |
850 | container_of(work, struct ql_adapter, mpi_reset_work.work); | |
bcc2cb3b RM |
851 | cancel_delayed_work_sync(&qdev->mpi_work); |
852 | cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); | |
2ee1e272 | 853 | cancel_delayed_work_sync(&qdev->mpi_idc_work); |
a2e809bb | 854 | ql_soft_reset_mpi_risc(qdev); |
c4e84bde | 855 | } |