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 | ||
cfec0cbc RM |
609 | /* Get MPI firmware version. This will be used for |
610 | * driver banner and for ethtool info. | |
611 | * Returns zero on success. | |
612 | */ | |
613 | int ql_mb_about_fw(struct ql_adapter *qdev) | |
614 | { | |
615 | struct mbox_params mbc; | |
616 | struct mbox_params *mbcp = &mbc; | |
617 | int status = 0; | |
618 | ||
619 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
620 | ||
621 | mbcp->in_count = 1; | |
622 | mbcp->out_count = 3; | |
623 | ||
624 | mbcp->mbox_in[0] = MB_CMD_ABOUT_FW; | |
625 | ||
626 | status = ql_mailbox_command(qdev, mbcp); | |
627 | if (status) | |
628 | return status; | |
629 | ||
630 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
ae9540f7 JP |
631 | netif_err(qdev, drv, qdev->ndev, |
632 | "Failed about firmware command\n"); | |
cfec0cbc RM |
633 | status = -EIO; |
634 | } | |
635 | ||
636 | /* Store the firmware version */ | |
637 | qdev->fw_rev_id = mbcp->mbox_out[1]; | |
638 | ||
639 | return status; | |
640 | } | |
641 | ||
ca0413b6 RM |
642 | /* Get functional state for MPI firmware. |
643 | * Returns zero on success. | |
644 | */ | |
645 | int ql_mb_get_fw_state(struct ql_adapter *qdev) | |
646 | { | |
647 | struct mbox_params mbc; | |
648 | struct mbox_params *mbcp = &mbc; | |
649 | int status = 0; | |
650 | ||
651 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
652 | ||
653 | mbcp->in_count = 1; | |
654 | mbcp->out_count = 2; | |
655 | ||
656 | mbcp->mbox_in[0] = MB_CMD_GET_FW_STATE; | |
657 | ||
658 | status = ql_mailbox_command(qdev, mbcp); | |
659 | if (status) | |
660 | return status; | |
661 | ||
662 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
ae9540f7 JP |
663 | netif_err(qdev, drv, qdev->ndev, |
664 | "Failed Get Firmware State.\n"); | |
ca0413b6 RM |
665 | status = -EIO; |
666 | } | |
667 | ||
668 | /* If bit zero is set in mbx 1 then the firmware is | |
669 | * running, but not initialized. This should never | |
670 | * happen. | |
671 | */ | |
672 | if (mbcp->mbox_out[1] & 1) { | |
ae9540f7 JP |
673 | netif_err(qdev, drv, qdev->ndev, |
674 | "Firmware waiting for initialization.\n"); | |
ca0413b6 RM |
675 | status = -EIO; |
676 | } | |
677 | ||
678 | return status; | |
679 | } | |
680 | ||
2ee1e272 RM |
681 | /* Send and ACK mailbox command to the firmware to |
682 | * let it continue with the change. | |
683 | */ | |
684 | int ql_mb_idc_ack(struct ql_adapter *qdev) | |
685 | { | |
686 | struct mbox_params mbc; | |
687 | struct mbox_params *mbcp = &mbc; | |
688 | int status = 0; | |
689 | ||
690 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
691 | ||
692 | mbcp->in_count = 5; | |
693 | mbcp->out_count = 1; | |
694 | ||
695 | mbcp->mbox_in[0] = MB_CMD_IDC_ACK; | |
696 | mbcp->mbox_in[1] = qdev->idc_mbc.mbox_out[1]; | |
697 | mbcp->mbox_in[2] = qdev->idc_mbc.mbox_out[2]; | |
698 | mbcp->mbox_in[3] = qdev->idc_mbc.mbox_out[3]; | |
699 | mbcp->mbox_in[4] = qdev->idc_mbc.mbox_out[4]; | |
700 | ||
701 | status = ql_mailbox_command(qdev, mbcp); | |
702 | if (status) | |
703 | return status; | |
704 | ||
705 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
ae9540f7 | 706 | netif_err(qdev, drv, qdev->ndev, "Failed IDC ACK send.\n"); |
2ee1e272 RM |
707 | status = -EIO; |
708 | } | |
709 | return status; | |
710 | } | |
711 | ||
bcc2cb3b RM |
712 | /* Get link settings and maximum frame size settings |
713 | * for the current port. | |
714 | * Most likely will block. | |
715 | */ | |
1d30df24 | 716 | int ql_mb_set_port_cfg(struct ql_adapter *qdev) |
bcc2cb3b RM |
717 | { |
718 | struct mbox_params mbc; | |
719 | struct mbox_params *mbcp = &mbc; | |
720 | int status = 0; | |
721 | ||
722 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
723 | ||
724 | mbcp->in_count = 3; | |
725 | mbcp->out_count = 1; | |
726 | ||
727 | mbcp->mbox_in[0] = MB_CMD_SET_PORT_CFG; | |
728 | mbcp->mbox_in[1] = qdev->link_config; | |
729 | mbcp->mbox_in[2] = qdev->max_frame_size; | |
730 | ||
731 | ||
732 | status = ql_mailbox_command(qdev, mbcp); | |
733 | if (status) | |
734 | return status; | |
735 | ||
736 | if (mbcp->mbox_out[0] == MB_CMD_STS_INTRMDT) { | |
ae9540f7 JP |
737 | netif_err(qdev, drv, qdev->ndev, |
738 | "Port Config sent, wait for IDC.\n"); | |
bcc2cb3b | 739 | } else if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { |
ae9540f7 JP |
740 | netif_err(qdev, drv, qdev->ndev, |
741 | "Failed Set Port Configuration.\n"); | |
bcc2cb3b RM |
742 | status = -EIO; |
743 | } | |
744 | return status; | |
745 | } | |
746 | ||
2c1f73c3 RM |
747 | int ql_mb_dump_ram(struct ql_adapter *qdev, u64 req_dma, u32 addr, |
748 | u32 size) | |
749 | { | |
750 | int status = 0; | |
751 | struct mbox_params mbc; | |
752 | struct mbox_params *mbcp = &mbc; | |
753 | ||
754 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
755 | ||
756 | mbcp->in_count = 9; | |
757 | mbcp->out_count = 1; | |
758 | ||
759 | mbcp->mbox_in[0] = MB_CMD_DUMP_RISC_RAM; | |
760 | mbcp->mbox_in[1] = LSW(addr); | |
761 | mbcp->mbox_in[2] = MSW(req_dma); | |
762 | mbcp->mbox_in[3] = LSW(req_dma); | |
763 | mbcp->mbox_in[4] = MSW(size); | |
764 | mbcp->mbox_in[5] = LSW(size); | |
765 | mbcp->mbox_in[6] = MSW(MSD(req_dma)); | |
766 | mbcp->mbox_in[7] = LSW(MSD(req_dma)); | |
767 | mbcp->mbox_in[8] = MSW(addr); | |
768 | ||
769 | ||
770 | status = ql_mailbox_command(qdev, mbcp); | |
771 | if (status) | |
772 | return status; | |
773 | ||
774 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
ae9540f7 | 775 | netif_err(qdev, drv, qdev->ndev, "Failed to dump risc RAM.\n"); |
2c1f73c3 RM |
776 | status = -EIO; |
777 | } | |
778 | return status; | |
779 | } | |
780 | ||
781 | /* Issue a mailbox command to dump RISC RAM. */ | |
782 | int ql_dump_risc_ram_area(struct ql_adapter *qdev, void *buf, | |
783 | u32 ram_addr, int word_count) | |
784 | { | |
785 | int status; | |
786 | char *my_buf; | |
787 | dma_addr_t buf_dma; | |
788 | ||
789 | my_buf = pci_alloc_consistent(qdev->pdev, word_count * sizeof(u32), | |
790 | &buf_dma); | |
791 | if (!my_buf) | |
792 | return -EIO; | |
793 | ||
794 | status = ql_mb_dump_ram(qdev, buf_dma, ram_addr, word_count); | |
795 | if (!status) | |
796 | memcpy(buf, my_buf, word_count * sizeof(u32)); | |
797 | ||
798 | pci_free_consistent(qdev->pdev, word_count * sizeof(u32), my_buf, | |
799 | buf_dma); | |
800 | return status; | |
801 | } | |
802 | ||
bcc2cb3b RM |
803 | /* Get link settings and maximum frame size settings |
804 | * for the current port. | |
805 | * Most likely will block. | |
806 | */ | |
1d30df24 | 807 | int ql_mb_get_port_cfg(struct ql_adapter *qdev) |
bcc2cb3b RM |
808 | { |
809 | struct mbox_params mbc; | |
810 | struct mbox_params *mbcp = &mbc; | |
811 | int status = 0; | |
812 | ||
813 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
814 | ||
815 | mbcp->in_count = 1; | |
816 | mbcp->out_count = 3; | |
817 | ||
818 | mbcp->mbox_in[0] = MB_CMD_GET_PORT_CFG; | |
819 | ||
820 | status = ql_mailbox_command(qdev, mbcp); | |
821 | if (status) | |
822 | return status; | |
823 | ||
824 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
ae9540f7 JP |
825 | netif_err(qdev, drv, qdev->ndev, |
826 | "Failed Get Port Configuration.\n"); | |
bcc2cb3b RM |
827 | status = -EIO; |
828 | } else { | |
ae9540f7 JP |
829 | netif_printk(qdev, drv, KERN_DEBUG, qdev->ndev, |
830 | "Passed Get Port Configuration.\n"); | |
bcc2cb3b RM |
831 | qdev->link_config = mbcp->mbox_out[1]; |
832 | qdev->max_frame_size = mbcp->mbox_out[2]; | |
833 | } | |
834 | return status; | |
835 | } | |
836 | ||
bc083ce9 RM |
837 | int ql_mb_wol_mode(struct ql_adapter *qdev, u32 wol) |
838 | { | |
839 | struct mbox_params mbc; | |
840 | struct mbox_params *mbcp = &mbc; | |
841 | int status; | |
842 | ||
843 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
844 | ||
845 | mbcp->in_count = 2; | |
846 | mbcp->out_count = 1; | |
847 | ||
848 | mbcp->mbox_in[0] = MB_CMD_SET_WOL_MODE; | |
849 | mbcp->mbox_in[1] = wol; | |
850 | ||
851 | ||
852 | status = ql_mailbox_command(qdev, mbcp); | |
853 | if (status) | |
854 | return status; | |
855 | ||
856 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
ae9540f7 | 857 | netif_err(qdev, drv, qdev->ndev, "Failed to set WOL mode.\n"); |
bc083ce9 RM |
858 | status = -EIO; |
859 | } | |
860 | return status; | |
861 | } | |
862 | ||
863 | int ql_mb_wol_set_magic(struct ql_adapter *qdev, u32 enable_wol) | |
864 | { | |
865 | struct mbox_params mbc; | |
866 | struct mbox_params *mbcp = &mbc; | |
867 | int status; | |
868 | u8 *addr = qdev->ndev->dev_addr; | |
869 | ||
870 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
871 | ||
872 | mbcp->in_count = 8; | |
873 | mbcp->out_count = 1; | |
874 | ||
875 | mbcp->mbox_in[0] = MB_CMD_SET_WOL_MAGIC; | |
876 | if (enable_wol) { | |
877 | mbcp->mbox_in[1] = (u32)addr[0]; | |
878 | mbcp->mbox_in[2] = (u32)addr[1]; | |
879 | mbcp->mbox_in[3] = (u32)addr[2]; | |
880 | mbcp->mbox_in[4] = (u32)addr[3]; | |
881 | mbcp->mbox_in[5] = (u32)addr[4]; | |
882 | mbcp->mbox_in[6] = (u32)addr[5]; | |
883 | mbcp->mbox_in[7] = 0; | |
884 | } else { | |
885 | mbcp->mbox_in[1] = 0; | |
886 | mbcp->mbox_in[2] = 1; | |
887 | mbcp->mbox_in[3] = 1; | |
888 | mbcp->mbox_in[4] = 1; | |
889 | mbcp->mbox_in[5] = 1; | |
890 | mbcp->mbox_in[6] = 1; | |
891 | mbcp->mbox_in[7] = 0; | |
892 | } | |
893 | ||
894 | status = ql_mailbox_command(qdev, mbcp); | |
895 | if (status) | |
896 | return status; | |
897 | ||
898 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
ae9540f7 | 899 | netif_err(qdev, drv, qdev->ndev, "Failed to set WOL mode.\n"); |
bc083ce9 RM |
900 | status = -EIO; |
901 | } | |
902 | return status; | |
903 | } | |
904 | ||
bcc2cb3b RM |
905 | /* IDC - Inter Device Communication... |
906 | * Some firmware commands require consent of adjacent FCOE | |
907 | * function. This function waits for the OK, or a | |
908 | * counter-request for a little more time.i | |
909 | * The firmware will complete the request if the other | |
910 | * function doesn't respond. | |
911 | */ | |
912 | static int ql_idc_wait(struct ql_adapter *qdev) | |
913 | { | |
914 | int status = -ETIMEDOUT; | |
915 | long wait_time = 1 * HZ; | |
916 | struct mbox_params *mbcp = &qdev->idc_mbc; | |
917 | do { | |
918 | /* Wait here for the command to complete | |
919 | * via the IDC process. | |
920 | */ | |
921 | wait_time = | |
922 | wait_for_completion_timeout(&qdev->ide_completion, | |
923 | wait_time); | |
924 | if (!wait_time) { | |
ae9540f7 | 925 | netif_err(qdev, drv, qdev->ndev, "IDC Timeout.\n"); |
bcc2cb3b RM |
926 | break; |
927 | } | |
928 | /* Now examine the response from the IDC process. | |
929 | * We might have a good completion or a request for | |
930 | * more wait time. | |
931 | */ | |
932 | if (mbcp->mbox_out[0] == AEN_IDC_EXT) { | |
ae9540f7 JP |
933 | netif_err(qdev, drv, qdev->ndev, |
934 | "IDC Time Extension from function.\n"); | |
bcc2cb3b RM |
935 | wait_time += (mbcp->mbox_out[1] >> 8) & 0x0000000f; |
936 | } else if (mbcp->mbox_out[0] == AEN_IDC_CMPLT) { | |
ae9540f7 | 937 | netif_err(qdev, drv, qdev->ndev, "IDC Success.\n"); |
bcc2cb3b RM |
938 | status = 0; |
939 | break; | |
940 | } else { | |
ae9540f7 JP |
941 | netif_err(qdev, drv, qdev->ndev, |
942 | "IDC: Invalid State 0x%.04x.\n", | |
943 | mbcp->mbox_out[0]); | |
bcc2cb3b RM |
944 | status = -EIO; |
945 | break; | |
946 | } | |
947 | } while (wait_time); | |
948 | ||
949 | return status; | |
950 | } | |
951 | ||
d8eb59dc RM |
952 | int ql_mb_set_led_cfg(struct ql_adapter *qdev, u32 led_config) |
953 | { | |
954 | struct mbox_params mbc; | |
955 | struct mbox_params *mbcp = &mbc; | |
956 | int status; | |
957 | ||
958 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
959 | ||
960 | mbcp->in_count = 2; | |
961 | mbcp->out_count = 1; | |
962 | ||
963 | mbcp->mbox_in[0] = MB_CMD_SET_LED_CFG; | |
964 | mbcp->mbox_in[1] = led_config; | |
965 | ||
966 | ||
967 | status = ql_mailbox_command(qdev, mbcp); | |
968 | if (status) | |
969 | return status; | |
970 | ||
971 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
ae9540f7 JP |
972 | netif_err(qdev, drv, qdev->ndev, |
973 | "Failed to set LED Configuration.\n"); | |
d8eb59dc RM |
974 | status = -EIO; |
975 | } | |
976 | ||
977 | return status; | |
978 | } | |
979 | ||
980 | int ql_mb_get_led_cfg(struct ql_adapter *qdev) | |
981 | { | |
982 | struct mbox_params mbc; | |
983 | struct mbox_params *mbcp = &mbc; | |
984 | int status; | |
985 | ||
986 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
987 | ||
988 | mbcp->in_count = 1; | |
989 | mbcp->out_count = 2; | |
990 | ||
991 | mbcp->mbox_in[0] = MB_CMD_GET_LED_CFG; | |
992 | ||
993 | status = ql_mailbox_command(qdev, mbcp); | |
994 | if (status) | |
995 | return status; | |
996 | ||
997 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | |
ae9540f7 JP |
998 | netif_err(qdev, drv, qdev->ndev, |
999 | "Failed to get LED Configuration.\n"); | |
d8eb59dc RM |
1000 | status = -EIO; |
1001 | } else | |
1002 | qdev->led_config = mbcp->mbox_out[1]; | |
1003 | ||
1004 | return status; | |
1005 | } | |
1006 | ||
84087f4d RM |
1007 | int ql_mb_set_mgmnt_traffic_ctl(struct ql_adapter *qdev, u32 control) |
1008 | { | |
1009 | struct mbox_params mbc; | |
1010 | struct mbox_params *mbcp = &mbc; | |
1011 | int status; | |
1012 | ||
1013 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
1014 | ||
1015 | mbcp->in_count = 1; | |
1016 | mbcp->out_count = 2; | |
1017 | ||
1018 | mbcp->mbox_in[0] = MB_CMD_SET_MGMNT_TFK_CTL; | |
1019 | mbcp->mbox_in[1] = control; | |
1020 | ||
1021 | status = ql_mailbox_command(qdev, mbcp); | |
1022 | if (status) | |
1023 | return status; | |
1024 | ||
1025 | if (mbcp->mbox_out[0] == MB_CMD_STS_GOOD) | |
1026 | return status; | |
1027 | ||
1028 | if (mbcp->mbox_out[0] == MB_CMD_STS_INVLD_CMD) { | |
ae9540f7 JP |
1029 | netif_err(qdev, drv, qdev->ndev, |
1030 | "Command not supported by firmware.\n"); | |
84087f4d RM |
1031 | status = -EINVAL; |
1032 | } else if (mbcp->mbox_out[0] == MB_CMD_STS_ERR) { | |
1033 | /* This indicates that the firmware is | |
1034 | * already in the state we are trying to | |
1035 | * change it to. | |
1036 | */ | |
ae9540f7 JP |
1037 | netif_err(qdev, drv, qdev->ndev, |
1038 | "Command parameters make no change.\n"); | |
84087f4d RM |
1039 | } |
1040 | return status; | |
1041 | } | |
1042 | ||
1043 | /* Returns a negative error code or the mailbox command status. */ | |
1044 | static int ql_mb_get_mgmnt_traffic_ctl(struct ql_adapter *qdev, u32 *control) | |
1045 | { | |
1046 | struct mbox_params mbc; | |
1047 | struct mbox_params *mbcp = &mbc; | |
1048 | int status; | |
1049 | ||
1050 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
1051 | *control = 0; | |
1052 | ||
1053 | mbcp->in_count = 1; | |
1054 | mbcp->out_count = 1; | |
1055 | ||
1056 | mbcp->mbox_in[0] = MB_CMD_GET_MGMNT_TFK_CTL; | |
1057 | ||
1058 | status = ql_mailbox_command(qdev, mbcp); | |
1059 | if (status) | |
1060 | return status; | |
1061 | ||
1062 | if (mbcp->mbox_out[0] == MB_CMD_STS_GOOD) { | |
1063 | *control = mbcp->mbox_in[1]; | |
1064 | return status; | |
1065 | } | |
1066 | ||
1067 | if (mbcp->mbox_out[0] == MB_CMD_STS_INVLD_CMD) { | |
ae9540f7 JP |
1068 | netif_err(qdev, drv, qdev->ndev, |
1069 | "Command not supported by firmware.\n"); | |
84087f4d RM |
1070 | status = -EINVAL; |
1071 | } else if (mbcp->mbox_out[0] == MB_CMD_STS_ERR) { | |
ae9540f7 JP |
1072 | netif_err(qdev, drv, qdev->ndev, |
1073 | "Failed to get MPI traffic control.\n"); | |
84087f4d RM |
1074 | status = -EIO; |
1075 | } | |
1076 | return status; | |
1077 | } | |
1078 | ||
1079 | int ql_wait_fifo_empty(struct ql_adapter *qdev) | |
1080 | { | |
1081 | int count = 5; | |
1082 | u32 mgmnt_fifo_empty; | |
1083 | u32 nic_fifo_empty; | |
1084 | ||
1085 | do { | |
1086 | nic_fifo_empty = ql_read32(qdev, STS) & STS_NFE; | |
1087 | ql_mb_get_mgmnt_traffic_ctl(qdev, &mgmnt_fifo_empty); | |
1088 | mgmnt_fifo_empty &= MB_GET_MPI_TFK_FIFO_EMPTY; | |
1089 | if (nic_fifo_empty && mgmnt_fifo_empty) | |
1090 | return 0; | |
1091 | msleep(100); | |
1092 | } while (count-- > 0); | |
1093 | return -ETIMEDOUT; | |
1094 | } | |
1095 | ||
bcc2cb3b RM |
1096 | /* API called in work thread context to set new TX/RX |
1097 | * maximum frame size values to match MTU. | |
1098 | */ | |
1099 | static int ql_set_port_cfg(struct ql_adapter *qdev) | |
1100 | { | |
1101 | int status; | |
86aaf9ad | 1102 | rtnl_lock(); |
bcc2cb3b | 1103 | status = ql_mb_set_port_cfg(qdev); |
86aaf9ad | 1104 | rtnl_unlock(); |
bcc2cb3b RM |
1105 | if (status) |
1106 | return status; | |
1107 | status = ql_idc_wait(qdev); | |
1108 | return status; | |
1109 | } | |
1110 | ||
1111 | /* The following routines are worker threads that process | |
1112 | * events that may sleep waiting for completion. | |
1113 | */ | |
1114 | ||
1115 | /* This thread gets the maximum TX and RX frame size values | |
1116 | * from the firmware and, if necessary, changes them to match | |
1117 | * the MTU setting. | |
1118 | */ | |
1119 | void ql_mpi_port_cfg_work(struct work_struct *work) | |
1120 | { | |
1121 | struct ql_adapter *qdev = | |
1122 | container_of(work, struct ql_adapter, mpi_port_cfg_work.work); | |
bcc2cb3b RM |
1123 | int status; |
1124 | ||
86aaf9ad | 1125 | rtnl_lock(); |
bcc2cb3b | 1126 | status = ql_mb_get_port_cfg(qdev); |
86aaf9ad | 1127 | rtnl_unlock(); |
bcc2cb3b | 1128 | if (status) { |
ae9540f7 JP |
1129 | netif_err(qdev, drv, qdev->ndev, |
1130 | "Bug: Failed to get port config data.\n"); | |
bcc2cb3b RM |
1131 | goto err; |
1132 | } | |
1133 | ||
c8269b21 | 1134 | if (qdev->link_config & CFG_JUMBO_FRAME_SIZE && |
bcc2cb3b RM |
1135 | qdev->max_frame_size == |
1136 | CFG_DEFAULT_MAX_FRAME_SIZE) | |
1137 | goto end; | |
1138 | ||
1139 | qdev->link_config |= CFG_JUMBO_FRAME_SIZE; | |
1140 | qdev->max_frame_size = CFG_DEFAULT_MAX_FRAME_SIZE; | |
1141 | status = ql_set_port_cfg(qdev); | |
1142 | if (status) { | |
ae9540f7 JP |
1143 | netif_err(qdev, drv, qdev->ndev, |
1144 | "Bug: Failed to set port config data.\n"); | |
bcc2cb3b RM |
1145 | goto err; |
1146 | } | |
1147 | end: | |
1148 | clear_bit(QL_PORT_CFG, &qdev->flags); | |
1149 | return; | |
1150 | err: | |
1151 | ql_queue_fw_error(qdev); | |
1152 | goto end; | |
1153 | } | |
1154 | ||
2ee1e272 RM |
1155 | /* Process an inter-device request. This is issues by |
1156 | * the firmware in response to another function requesting | |
1157 | * a change to the port. We set a flag to indicate a change | |
1158 | * has been made and then send a mailbox command ACKing | |
1159 | * the change request. | |
1160 | */ | |
1161 | void ql_mpi_idc_work(struct work_struct *work) | |
1162 | { | |
1163 | struct ql_adapter *qdev = | |
1164 | container_of(work, struct ql_adapter, mpi_idc_work.work); | |
1165 | int status; | |
1166 | struct mbox_params *mbcp = &qdev->idc_mbc; | |
1167 | u32 aen; | |
1e34e307 | 1168 | int timeout; |
2ee1e272 | 1169 | |
1e34e307 | 1170 | rtnl_lock(); |
2ee1e272 | 1171 | aen = mbcp->mbox_out[1] >> 16; |
1e34e307 | 1172 | timeout = (mbcp->mbox_out[1] >> 8) & 0xf; |
2ee1e272 RM |
1173 | |
1174 | switch (aen) { | |
1175 | default: | |
ae9540f7 JP |
1176 | netif_err(qdev, drv, qdev->ndev, |
1177 | "Bug: Unhandled IDC action.\n"); | |
2ee1e272 RM |
1178 | break; |
1179 | case MB_CMD_PORT_RESET: | |
2ee1e272 | 1180 | case MB_CMD_STOP_FW: |
6a473308 | 1181 | ql_link_off(qdev); |
1e34e307 | 1182 | case MB_CMD_SET_PORT_CFG: |
2ee1e272 RM |
1183 | /* Signal the resulting link up AEN |
1184 | * that the frame routing and mac addr | |
1185 | * needs to be set. | |
1186 | * */ | |
1187 | set_bit(QL_CAM_RT_SET, &qdev->flags); | |
1e34e307 RM |
1188 | /* Do ACK if required */ |
1189 | if (timeout) { | |
1190 | status = ql_mb_idc_ack(qdev); | |
1191 | if (status) | |
ae9540f7 JP |
1192 | netif_err(qdev, drv, qdev->ndev, |
1193 | "Bug: No pending IDC!\n"); | |
1e34e307 | 1194 | } else { |
ae9540f7 JP |
1195 | netif_printk(qdev, drv, KERN_DEBUG, qdev->ndev, |
1196 | "IDC ACK not required\n"); | |
1e34e307 RM |
1197 | status = 0; /* success */ |
1198 | } | |
1199 | break; | |
1200 | ||
1201 | /* These sub-commands issued by another (FCoE) | |
1202 | * function are requesting to do an operation | |
1203 | * on the shared resource (MPI environment). | |
1204 | * We currently don't issue these so we just | |
1205 | * ACK the request. | |
1206 | */ | |
1207 | case MB_CMD_IOP_RESTART_MPI: | |
1208 | case MB_CMD_IOP_PREP_LINK_DOWN: | |
1209 | /* Drop the link, reload the routing | |
1210 | * table when link comes up. | |
1211 | */ | |
1212 | ql_link_off(qdev); | |
1213 | set_bit(QL_CAM_RT_SET, &qdev->flags); | |
1214 | /* Fall through. */ | |
1215 | case MB_CMD_IOP_DVR_START: | |
1216 | case MB_CMD_IOP_FLASH_ACC: | |
1217 | case MB_CMD_IOP_CORE_DUMP_MPI: | |
1218 | case MB_CMD_IOP_PREP_UPDATE_MPI: | |
1219 | case MB_CMD_IOP_COMP_UPDATE_MPI: | |
1220 | case MB_CMD_IOP_NONE: /* an IDC without params */ | |
1221 | /* Do ACK if required */ | |
1222 | if (timeout) { | |
1223 | status = ql_mb_idc_ack(qdev); | |
1224 | if (status) | |
ae9540f7 JP |
1225 | netif_err(qdev, drv, qdev->ndev, |
1226 | "Bug: No pending IDC!\n"); | |
1e34e307 | 1227 | } else { |
ae9540f7 JP |
1228 | netif_printk(qdev, drv, KERN_DEBUG, qdev->ndev, |
1229 | "IDC ACK not required\n"); | |
1e34e307 | 1230 | status = 0; /* success */ |
2ee1e272 | 1231 | } |
1e34e307 | 1232 | break; |
2ee1e272 | 1233 | } |
1e34e307 | 1234 | rtnl_unlock(); |
2ee1e272 RM |
1235 | } |
1236 | ||
c4e84bde RM |
1237 | void ql_mpi_work(struct work_struct *work) |
1238 | { | |
1239 | struct ql_adapter *qdev = | |
1240 | container_of(work, struct ql_adapter, mpi_work.work); | |
1241 | struct mbox_params mbc; | |
1242 | struct mbox_params *mbcp = &mbc; | |
d6f58c2e | 1243 | int err = 0; |
c4e84bde | 1244 | |
86aaf9ad | 1245 | rtnl_lock(); |
efd7d261 RM |
1246 | /* Begin polled mode for MPI */ |
1247 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); | |
c4e84bde | 1248 | |
125844ea RM |
1249 | while (ql_read32(qdev, STS) & STS_PI) { |
1250 | memset(mbcp, 0, sizeof(struct mbox_params)); | |
1251 | mbcp->out_count = 1; | |
d6f58c2e RM |
1252 | /* Don't continue if an async event |
1253 | * did not complete properly. | |
1254 | */ | |
1255 | err = ql_mpi_handler(qdev, mbcp); | |
1256 | if (err) | |
1257 | break; | |
c4e84bde | 1258 | } |
125844ea | 1259 | |
efd7d261 RM |
1260 | /* End polled mode for MPI */ |
1261 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI); | |
86aaf9ad | 1262 | rtnl_unlock(); |
c4e84bde RM |
1263 | ql_enable_completion_interrupt(qdev, 0); |
1264 | } | |
1265 | ||
1266 | void ql_mpi_reset_work(struct work_struct *work) | |
1267 | { | |
1268 | struct ql_adapter *qdev = | |
1269 | container_of(work, struct ql_adapter, mpi_reset_work.work); | |
bcc2cb3b RM |
1270 | cancel_delayed_work_sync(&qdev->mpi_work); |
1271 | cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); | |
2ee1e272 | 1272 | cancel_delayed_work_sync(&qdev->mpi_idc_work); |
8aae2600 RM |
1273 | /* If we're not the dominant NIC function, |
1274 | * then there is nothing to do. | |
1275 | */ | |
1276 | if (!ql_own_firmware(qdev)) { | |
ae9540f7 | 1277 | netif_err(qdev, drv, qdev->ndev, "Don't own firmware!\n"); |
8aae2600 RM |
1278 | return; |
1279 | } | |
1280 | ||
1281 | if (!ql_core_dump(qdev, qdev->mpi_coredump)) { | |
ae9540f7 | 1282 | netif_err(qdev, drv, qdev->ndev, "Core is dumped!\n"); |
8aae2600 RM |
1283 | qdev->core_is_dumped = 1; |
1284 | queue_delayed_work(qdev->workqueue, | |
1285 | &qdev->mpi_core_to_log, 5 * HZ); | |
1286 | } | |
a2e809bb | 1287 | ql_soft_reset_mpi_risc(qdev); |
c4e84bde | 1288 | } |