diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_init.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 426 |
1 files changed, 369 insertions, 57 deletions
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index e7e5f4facf7f..38aeb54cd9d8 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -271,56 +271,46 @@ done: | |||
271 | } | 271 | } |
272 | 272 | ||
273 | static void | 273 | static void |
274 | qla2x00_async_tm_cmd_done(void *data, void *ptr, int res) | 274 | qla2x00_tmf_iocb_timeout(void *data) |
275 | { | 275 | { |
276 | srb_t *sp = (srb_t *)ptr; | 276 | srb_t *sp = (srb_t *)data; |
277 | struct srb_iocb *iocb = &sp->u.iocb_cmd; | 277 | struct srb_iocb *tmf = &sp->u.iocb_cmd; |
278 | struct scsi_qla_host *vha = (scsi_qla_host_t *)data; | ||
279 | uint32_t flags; | ||
280 | uint16_t lun; | ||
281 | int rval; | ||
282 | |||
283 | if (!test_bit(UNLOADING, &vha->dpc_flags)) { | ||
284 | flags = iocb->u.tmf.flags; | ||
285 | lun = (uint16_t)iocb->u.tmf.lun; | ||
286 | 278 | ||
287 | /* Issue Marker IOCB */ | 279 | tmf->u.tmf.comp_status = CS_TIMEOUT; |
288 | rval = qla2x00_marker(vha, vha->hw->req_q_map[0], | 280 | complete(&tmf->u.tmf.comp); |
289 | vha->hw->rsp_q_map[0], sp->fcport->loop_id, lun, | 281 | } |
290 | flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID); | ||
291 | 282 | ||
292 | if ((rval != QLA_SUCCESS) || iocb->u.tmf.data) { | 283 | static void |
293 | ql_dbg(ql_dbg_taskm, vha, 0x8030, | 284 | qla2x00_tmf_sp_done(void *data, void *ptr, int res) |
294 | "TM IOCB failed (%x).\n", rval); | 285 | { |
295 | } | 286 | srb_t *sp = (srb_t *)ptr; |
296 | } | 287 | struct srb_iocb *tmf = &sp->u.iocb_cmd; |
297 | sp->free(sp->fcport->vha, sp); | 288 | complete(&tmf->u.tmf.comp); |
298 | } | 289 | } |
299 | 290 | ||
300 | int | 291 | int |
301 | qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t tm_flags, uint32_t lun, | 292 | qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, |
302 | uint32_t tag) | 293 | uint32_t tag) |
303 | { | 294 | { |
304 | struct scsi_qla_host *vha = fcport->vha; | 295 | struct scsi_qla_host *vha = fcport->vha; |
296 | struct srb_iocb *tm_iocb; | ||
305 | srb_t *sp; | 297 | srb_t *sp; |
306 | struct srb_iocb *tcf; | 298 | int rval = QLA_FUNCTION_FAILED; |
307 | int rval; | ||
308 | 299 | ||
309 | rval = QLA_FUNCTION_FAILED; | ||
310 | sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); | 300 | sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); |
311 | if (!sp) | 301 | if (!sp) |
312 | goto done; | 302 | goto done; |
313 | 303 | ||
304 | tm_iocb = &sp->u.iocb_cmd; | ||
314 | sp->type = SRB_TM_CMD; | 305 | sp->type = SRB_TM_CMD; |
315 | sp->name = "tmf"; | 306 | sp->name = "tmf"; |
316 | qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2); | 307 | qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha)); |
317 | 308 | tm_iocb->u.tmf.flags = flags; | |
318 | tcf = &sp->u.iocb_cmd; | 309 | tm_iocb->u.tmf.lun = lun; |
319 | tcf->u.tmf.flags = tm_flags; | 310 | tm_iocb->u.tmf.data = tag; |
320 | tcf->u.tmf.lun = lun; | 311 | sp->done = qla2x00_tmf_sp_done; |
321 | tcf->u.tmf.data = tag; | 312 | tm_iocb->timeout = qla2x00_tmf_iocb_timeout; |
322 | tcf->timeout = qla2x00_async_iocb_timeout; | 313 | init_completion(&tm_iocb->u.tmf.comp); |
323 | sp->done = qla2x00_async_tm_cmd_done; | ||
324 | 314 | ||
325 | rval = qla2x00_start_sp(sp); | 315 | rval = qla2x00_start_sp(sp); |
326 | if (rval != QLA_SUCCESS) | 316 | if (rval != QLA_SUCCESS) |
@@ -330,14 +320,121 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t tm_flags, uint32_t lun, | |||
330 | "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x.\n", | 320 | "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x.\n", |
331 | sp->handle, fcport->loop_id, fcport->d_id.b.domain, | 321 | sp->handle, fcport->loop_id, fcport->d_id.b.domain, |
332 | fcport->d_id.b.area, fcport->d_id.b.al_pa); | 322 | fcport->d_id.b.area, fcport->d_id.b.al_pa); |
323 | |||
324 | wait_for_completion(&tm_iocb->u.tmf.comp); | ||
325 | |||
326 | rval = tm_iocb->u.tmf.comp_status == CS_COMPLETE ? | ||
327 | QLA_SUCCESS : QLA_FUNCTION_FAILED; | ||
328 | |||
329 | if ((rval != QLA_SUCCESS) || tm_iocb->u.tmf.data) { | ||
330 | ql_dbg(ql_dbg_taskm, vha, 0x8030, | ||
331 | "TM IOCB failed (%x).\n", rval); | ||
332 | } | ||
333 | |||
334 | if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) { | ||
335 | flags = tm_iocb->u.tmf.flags; | ||
336 | lun = (uint16_t)tm_iocb->u.tmf.lun; | ||
337 | |||
338 | /* Issue Marker IOCB */ | ||
339 | qla2x00_marker(vha, vha->hw->req_q_map[0], | ||
340 | vha->hw->rsp_q_map[0], sp->fcport->loop_id, lun, | ||
341 | flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID); | ||
342 | } | ||
343 | |||
344 | done_free_sp: | ||
345 | sp->free(vha, sp); | ||
346 | done: | ||
333 | return rval; | 347 | return rval; |
348 | } | ||
349 | |||
350 | static void | ||
351 | qla24xx_abort_iocb_timeout(void *data) | ||
352 | { | ||
353 | srb_t *sp = (srb_t *)data; | ||
354 | struct srb_iocb *abt = &sp->u.iocb_cmd; | ||
355 | |||
356 | abt->u.abt.comp_status = CS_TIMEOUT; | ||
357 | complete(&abt->u.abt.comp); | ||
358 | } | ||
359 | |||
360 | static void | ||
361 | qla24xx_abort_sp_done(void *data, void *ptr, int res) | ||
362 | { | ||
363 | srb_t *sp = (srb_t *)ptr; | ||
364 | struct srb_iocb *abt = &sp->u.iocb_cmd; | ||
365 | |||
366 | complete(&abt->u.abt.comp); | ||
367 | } | ||
368 | |||
369 | static int | ||
370 | qla24xx_async_abort_cmd(srb_t *cmd_sp) | ||
371 | { | ||
372 | scsi_qla_host_t *vha = cmd_sp->fcport->vha; | ||
373 | fc_port_t *fcport = cmd_sp->fcport; | ||
374 | struct srb_iocb *abt_iocb; | ||
375 | srb_t *sp; | ||
376 | int rval = QLA_FUNCTION_FAILED; | ||
377 | |||
378 | sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); | ||
379 | if (!sp) | ||
380 | goto done; | ||
381 | |||
382 | abt_iocb = &sp->u.iocb_cmd; | ||
383 | sp->type = SRB_ABT_CMD; | ||
384 | sp->name = "abort"; | ||
385 | qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha)); | ||
386 | abt_iocb->u.abt.cmd_hndl = cmd_sp->handle; | ||
387 | sp->done = qla24xx_abort_sp_done; | ||
388 | abt_iocb->timeout = qla24xx_abort_iocb_timeout; | ||
389 | init_completion(&abt_iocb->u.abt.comp); | ||
390 | |||
391 | rval = qla2x00_start_sp(sp); | ||
392 | if (rval != QLA_SUCCESS) | ||
393 | goto done_free_sp; | ||
394 | |||
395 | ql_dbg(ql_dbg_async, vha, 0x507c, | ||
396 | "Abort command issued - hdl=%x, target_id=%x\n", | ||
397 | cmd_sp->handle, fcport->tgt_id); | ||
398 | |||
399 | wait_for_completion(&abt_iocb->u.abt.comp); | ||
400 | |||
401 | rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ? | ||
402 | QLA_SUCCESS : QLA_FUNCTION_FAILED; | ||
334 | 403 | ||
335 | done_free_sp: | 404 | done_free_sp: |
336 | sp->free(fcport->vha, sp); | 405 | sp->free(vha, sp); |
337 | done: | 406 | done: |
338 | return rval; | 407 | return rval; |
339 | } | 408 | } |
340 | 409 | ||
410 | int | ||
411 | qla24xx_async_abort_command(srb_t *sp) | ||
412 | { | ||
413 | unsigned long flags = 0; | ||
414 | |||
415 | uint32_t handle; | ||
416 | fc_port_t *fcport = sp->fcport; | ||
417 | struct scsi_qla_host *vha = fcport->vha; | ||
418 | struct qla_hw_data *ha = vha->hw; | ||
419 | struct req_que *req = vha->req; | ||
420 | |||
421 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
422 | for (handle = 1; handle < req->num_outstanding_cmds; handle++) { | ||
423 | if (req->outstanding_cmds[handle] == sp) | ||
424 | break; | ||
425 | } | ||
426 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
427 | if (handle == req->num_outstanding_cmds) { | ||
428 | /* Command not found. */ | ||
429 | return QLA_FUNCTION_FAILED; | ||
430 | } | ||
431 | if (sp->type == SRB_FXIOCB_DCMD) | ||
432 | return qlafx00_fx_disc(vha, &vha->hw->mr.fcport, | ||
433 | FXDISC_ABORT_IOCTL); | ||
434 | |||
435 | return qla24xx_async_abort_cmd(sp); | ||
436 | } | ||
437 | |||
341 | void | 438 | void |
342 | qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport, | 439 | qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport, |
343 | uint16_t *data) | 440 | uint16_t *data) |
@@ -1379,7 +1476,12 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) | |||
1379 | } | 1476 | } |
1380 | 1477 | ||
1381 | ha->fw_dumped = 0; | 1478 | ha->fw_dumped = 0; |
1382 | fixed_size = mem_size = eft_size = fce_size = mq_size = 0; | 1479 | dump_size = fixed_size = mem_size = eft_size = fce_size = mq_size = 0; |
1480 | req_q_size = rsp_q_size = 0; | ||
1481 | |||
1482 | if (IS_QLA27XX(ha)) | ||
1483 | goto try_fce; | ||
1484 | |||
1383 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { | 1485 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { |
1384 | fixed_size = sizeof(struct qla2100_fw_dump); | 1486 | fixed_size = sizeof(struct qla2100_fw_dump); |
1385 | } else if (IS_QLA23XX(ha)) { | 1487 | } else if (IS_QLA23XX(ha)) { |
@@ -1395,6 +1497,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) | |||
1395 | fixed_size = offsetof(struct qla25xx_fw_dump, ext_mem); | 1497 | fixed_size = offsetof(struct qla25xx_fw_dump, ext_mem); |
1396 | else | 1498 | else |
1397 | fixed_size = offsetof(struct qla24xx_fw_dump, ext_mem); | 1499 | fixed_size = offsetof(struct qla24xx_fw_dump, ext_mem); |
1500 | |||
1398 | mem_size = (ha->fw_memory_size - 0x100000 + 1) * | 1501 | mem_size = (ha->fw_memory_size - 0x100000 + 1) * |
1399 | sizeof(uint32_t); | 1502 | sizeof(uint32_t); |
1400 | if (ha->mqenable) { | 1503 | if (ha->mqenable) { |
@@ -1412,9 +1515,16 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) | |||
1412 | if (ha->tgt.atio_ring) | 1515 | if (ha->tgt.atio_ring) |
1413 | mq_size += ha->tgt.atio_q_length * sizeof(request_t); | 1516 | mq_size += ha->tgt.atio_q_length * sizeof(request_t); |
1414 | /* Allocate memory for Fibre Channel Event Buffer. */ | 1517 | /* Allocate memory for Fibre Channel Event Buffer. */ |
1415 | if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha)) | 1518 | if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) && |
1519 | !IS_QLA27XX(ha)) | ||
1416 | goto try_eft; | 1520 | goto try_eft; |
1417 | 1521 | ||
1522 | try_fce: | ||
1523 | if (ha->fce) | ||
1524 | dma_free_coherent(&ha->pdev->dev, | ||
1525 | FCE_SIZE, ha->fce, ha->fce_dma); | ||
1526 | |||
1527 | /* Allocate memory for Fibre Channel Event Buffer. */ | ||
1418 | tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma, | 1528 | tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma, |
1419 | GFP_KERNEL); | 1529 | GFP_KERNEL); |
1420 | if (!tc) { | 1530 | if (!tc) { |
@@ -1442,7 +1552,12 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) | |||
1442 | ha->flags.fce_enabled = 1; | 1552 | ha->flags.fce_enabled = 1; |
1443 | ha->fce_dma = tc_dma; | 1553 | ha->fce_dma = tc_dma; |
1444 | ha->fce = tc; | 1554 | ha->fce = tc; |
1555 | |||
1445 | try_eft: | 1556 | try_eft: |
1557 | if (ha->eft) | ||
1558 | dma_free_coherent(&ha->pdev->dev, | ||
1559 | EFT_SIZE, ha->eft, ha->eft_dma); | ||
1560 | |||
1446 | /* Allocate memory for Extended Trace Buffer. */ | 1561 | /* Allocate memory for Extended Trace Buffer. */ |
1447 | tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma, | 1562 | tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma, |
1448 | GFP_KERNEL); | 1563 | GFP_KERNEL); |
@@ -1469,15 +1584,28 @@ try_eft: | |||
1469 | ha->eft_dma = tc_dma; | 1584 | ha->eft_dma = tc_dma; |
1470 | ha->eft = tc; | 1585 | ha->eft = tc; |
1471 | } | 1586 | } |
1587 | |||
1472 | cont_alloc: | 1588 | cont_alloc: |
1589 | if (IS_QLA27XX(ha)) { | ||
1590 | if (!ha->fw_dump_template) { | ||
1591 | ql_log(ql_log_warn, vha, 0x00ba, | ||
1592 | "Failed missing fwdump template\n"); | ||
1593 | return; | ||
1594 | } | ||
1595 | dump_size = qla27xx_fwdt_calculate_dump_size(vha); | ||
1596 | ql_dbg(ql_dbg_init, vha, 0x00fa, | ||
1597 | "-> allocating fwdump (%x bytes)...\n", dump_size); | ||
1598 | goto allocate; | ||
1599 | } | ||
1600 | |||
1473 | req_q_size = req->length * sizeof(request_t); | 1601 | req_q_size = req->length * sizeof(request_t); |
1474 | rsp_q_size = rsp->length * sizeof(response_t); | 1602 | rsp_q_size = rsp->length * sizeof(response_t); |
1475 | |||
1476 | dump_size = offsetof(struct qla2xxx_fw_dump, isp); | 1603 | dump_size = offsetof(struct qla2xxx_fw_dump, isp); |
1477 | dump_size += fixed_size + mem_size + req_q_size + rsp_q_size + eft_size; | 1604 | dump_size += fixed_size + mem_size + req_q_size + rsp_q_size + eft_size; |
1478 | ha->chain_offset = dump_size; | 1605 | ha->chain_offset = dump_size; |
1479 | dump_size += mq_size + fce_size; | 1606 | dump_size += mq_size + fce_size; |
1480 | 1607 | ||
1608 | allocate: | ||
1481 | ha->fw_dump = vmalloc(dump_size); | 1609 | ha->fw_dump = vmalloc(dump_size); |
1482 | if (!ha->fw_dump) { | 1610 | if (!ha->fw_dump) { |
1483 | ql_log(ql_log_warn, vha, 0x00c4, | 1611 | ql_log(ql_log_warn, vha, 0x00c4, |
@@ -1499,10 +1627,13 @@ cont_alloc: | |||
1499 | } | 1627 | } |
1500 | return; | 1628 | return; |
1501 | } | 1629 | } |
1630 | ha->fw_dump_len = dump_size; | ||
1502 | ql_dbg(ql_dbg_init, vha, 0x00c5, | 1631 | ql_dbg(ql_dbg_init, vha, 0x00c5, |
1503 | "Allocated (%d KB) for firmware dump.\n", dump_size / 1024); | 1632 | "Allocated (%d KB) for firmware dump.\n", dump_size / 1024); |
1504 | 1633 | ||
1505 | ha->fw_dump_len = dump_size; | 1634 | if (IS_QLA27XX(ha)) |
1635 | return; | ||
1636 | |||
1506 | ha->fw_dump->signature[0] = 'Q'; | 1637 | ha->fw_dump->signature[0] = 'Q'; |
1507 | ha->fw_dump->signature[1] = 'L'; | 1638 | ha->fw_dump->signature[1] = 'L'; |
1508 | ha->fw_dump->signature[2] = 'G'; | 1639 | ha->fw_dump->signature[2] = 'G'; |
@@ -1718,9 +1849,6 @@ enable_82xx_npiv: | |||
1718 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 1849 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
1719 | } | 1850 | } |
1720 | 1851 | ||
1721 | if (IS_QLA83XX(ha)) | ||
1722 | goto skip_fac_check; | ||
1723 | |||
1724 | if (rval == QLA_SUCCESS && IS_FAC_REQUIRED(ha)) { | 1852 | if (rval == QLA_SUCCESS && IS_FAC_REQUIRED(ha)) { |
1725 | uint32_t size; | 1853 | uint32_t size; |
1726 | 1854 | ||
@@ -1733,8 +1861,8 @@ enable_82xx_npiv: | |||
1733 | "Unsupported FAC firmware (%d.%02d.%02d).\n", | 1861 | "Unsupported FAC firmware (%d.%02d.%02d).\n", |
1734 | ha->fw_major_version, ha->fw_minor_version, | 1862 | ha->fw_major_version, ha->fw_minor_version, |
1735 | ha->fw_subminor_version); | 1863 | ha->fw_subminor_version); |
1736 | skip_fac_check: | 1864 | |
1737 | if (IS_QLA83XX(ha)) { | 1865 | if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { |
1738 | ha->flags.fac_supported = 0; | 1866 | ha->flags.fac_supported = 0; |
1739 | rval = QLA_SUCCESS; | 1867 | rval = QLA_SUCCESS; |
1740 | } | 1868 | } |
@@ -1933,7 +2061,7 @@ qla24xx_config_rings(struct scsi_qla_host *vha) | |||
1933 | icb->atio_q_address[0] = cpu_to_le32(LSD(ha->tgt.atio_dma)); | 2061 | icb->atio_q_address[0] = cpu_to_le32(LSD(ha->tgt.atio_dma)); |
1934 | icb->atio_q_address[1] = cpu_to_le32(MSD(ha->tgt.atio_dma)); | 2062 | icb->atio_q_address[1] = cpu_to_le32(MSD(ha->tgt.atio_dma)); |
1935 | 2063 | ||
1936 | if (ha->mqenable || IS_QLA83XX(ha)) { | 2064 | if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) { |
1937 | icb->qos = __constant_cpu_to_le16(QLA_DEFAULT_QUE_QOS); | 2065 | icb->qos = __constant_cpu_to_le16(QLA_DEFAULT_QUE_QOS); |
1938 | icb->rid = __constant_cpu_to_le16(rid); | 2066 | icb->rid = __constant_cpu_to_le16(rid); |
1939 | if (ha->flags.msix_enabled) { | 2067 | if (ha->flags.msix_enabled) { |
@@ -4792,13 +4920,14 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) | |||
4792 | nv = ha->nvram; | 4920 | nv = ha->nvram; |
4793 | 4921 | ||
4794 | /* Determine NVRAM starting address. */ | 4922 | /* Determine NVRAM starting address. */ |
4795 | if (ha->flags.port0) { | 4923 | if (ha->port_no == 0) { |
4796 | ha->nvram_base = FA_NVRAM_FUNC0_ADDR; | 4924 | ha->nvram_base = FA_NVRAM_FUNC0_ADDR; |
4797 | ha->vpd_base = FA_NVRAM_VPD0_ADDR; | 4925 | ha->vpd_base = FA_NVRAM_VPD0_ADDR; |
4798 | } else { | 4926 | } else { |
4799 | ha->nvram_base = FA_NVRAM_FUNC1_ADDR; | 4927 | ha->nvram_base = FA_NVRAM_FUNC1_ADDR; |
4800 | ha->vpd_base = FA_NVRAM_VPD1_ADDR; | 4928 | ha->vpd_base = FA_NVRAM_VPD1_ADDR; |
4801 | } | 4929 | } |
4930 | |||
4802 | ha->nvram_size = sizeof(struct nvram_24xx); | 4931 | ha->nvram_size = sizeof(struct nvram_24xx); |
4803 | ha->vpd_size = FA_NVRAM_VPD_SIZE; | 4932 | ha->vpd_size = FA_NVRAM_VPD_SIZE; |
4804 | 4933 | ||
@@ -4842,7 +4971,7 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) | |||
4842 | nv->exchange_count = __constant_cpu_to_le16(0); | 4971 | nv->exchange_count = __constant_cpu_to_le16(0); |
4843 | nv->hard_address = __constant_cpu_to_le16(124); | 4972 | nv->hard_address = __constant_cpu_to_le16(124); |
4844 | nv->port_name[0] = 0x21; | 4973 | nv->port_name[0] = 0x21; |
4845 | nv->port_name[1] = 0x00 + ha->port_no; | 4974 | nv->port_name[1] = 0x00 + ha->port_no + 1; |
4846 | nv->port_name[2] = 0x00; | 4975 | nv->port_name[2] = 0x00; |
4847 | nv->port_name[3] = 0xe0; | 4976 | nv->port_name[3] = 0xe0; |
4848 | nv->port_name[4] = 0x8b; | 4977 | nv->port_name[4] = 0x8b; |
@@ -5117,6 +5246,99 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, | |||
5117 | segments--; | 5246 | segments--; |
5118 | } | 5247 | } |
5119 | 5248 | ||
5249 | if (!IS_QLA27XX(ha)) | ||
5250 | return rval; | ||
5251 | |||
5252 | if (ha->fw_dump_template) | ||
5253 | vfree(ha->fw_dump_template); | ||
5254 | ha->fw_dump_template = NULL; | ||
5255 | ha->fw_dump_template_len = 0; | ||
5256 | |||
5257 | ql_dbg(ql_dbg_init, vha, 0x0161, | ||
5258 | "Loading fwdump template from %x\n", faddr); | ||
5259 | qla24xx_read_flash_data(vha, dcode, faddr, 7); | ||
5260 | risc_size = be32_to_cpu(dcode[2]); | ||
5261 | ql_dbg(ql_dbg_init, vha, 0x0162, | ||
5262 | "-> array size %x dwords\n", risc_size); | ||
5263 | if (risc_size == 0 || risc_size == ~0) | ||
5264 | goto default_template; | ||
5265 | |||
5266 | dlen = (risc_size - 8) * sizeof(*dcode); | ||
5267 | ql_dbg(ql_dbg_init, vha, 0x0163, | ||
5268 | "-> template allocating %x bytes...\n", dlen); | ||
5269 | ha->fw_dump_template = vmalloc(dlen); | ||
5270 | if (!ha->fw_dump_template) { | ||
5271 | ql_log(ql_log_warn, vha, 0x0164, | ||
5272 | "Failed fwdump template allocate %x bytes.\n", risc_size); | ||
5273 | goto default_template; | ||
5274 | } | ||
5275 | |||
5276 | faddr += 7; | ||
5277 | risc_size -= 8; | ||
5278 | dcode = ha->fw_dump_template; | ||
5279 | qla24xx_read_flash_data(vha, dcode, faddr, risc_size); | ||
5280 | for (i = 0; i < risc_size; i++) | ||
5281 | dcode[i] = le32_to_cpu(dcode[i]); | ||
5282 | |||
5283 | if (!qla27xx_fwdt_template_valid(dcode)) { | ||
5284 | ql_log(ql_log_warn, vha, 0x0165, | ||
5285 | "Failed fwdump template validate\n"); | ||
5286 | goto default_template; | ||
5287 | } | ||
5288 | |||
5289 | dlen = qla27xx_fwdt_template_size(dcode); | ||
5290 | ql_dbg(ql_dbg_init, vha, 0x0166, | ||
5291 | "-> template size %x bytes\n", dlen); | ||
5292 | if (dlen > risc_size * sizeof(*dcode)) { | ||
5293 | ql_log(ql_log_warn, vha, 0x0167, | ||
5294 | "Failed fwdump template exceeds array by %x bytes\n", | ||
5295 | (uint32_t)(dlen - risc_size * sizeof(*dcode))); | ||
5296 | goto default_template; | ||
5297 | } | ||
5298 | ha->fw_dump_template_len = dlen; | ||
5299 | return rval; | ||
5300 | |||
5301 | default_template: | ||
5302 | ql_log(ql_log_warn, vha, 0x0168, "Using default fwdump template\n"); | ||
5303 | if (ha->fw_dump_template) | ||
5304 | vfree(ha->fw_dump_template); | ||
5305 | ha->fw_dump_template = NULL; | ||
5306 | ha->fw_dump_template_len = 0; | ||
5307 | |||
5308 | dlen = qla27xx_fwdt_template_default_size(); | ||
5309 | ql_dbg(ql_dbg_init, vha, 0x0169, | ||
5310 | "-> template allocating %x bytes...\n", dlen); | ||
5311 | ha->fw_dump_template = vmalloc(dlen); | ||
5312 | if (!ha->fw_dump_template) { | ||
5313 | ql_log(ql_log_warn, vha, 0x016a, | ||
5314 | "Failed fwdump template allocate %x bytes.\n", risc_size); | ||
5315 | goto failed_template; | ||
5316 | } | ||
5317 | |||
5318 | dcode = ha->fw_dump_template; | ||
5319 | risc_size = dlen / sizeof(*dcode); | ||
5320 | memcpy(dcode, qla27xx_fwdt_template_default(), dlen); | ||
5321 | for (i = 0; i < risc_size; i++) | ||
5322 | dcode[i] = be32_to_cpu(dcode[i]); | ||
5323 | |||
5324 | if (!qla27xx_fwdt_template_valid(ha->fw_dump_template)) { | ||
5325 | ql_log(ql_log_warn, vha, 0x016b, | ||
5326 | "Failed fwdump template validate\n"); | ||
5327 | goto failed_template; | ||
5328 | } | ||
5329 | |||
5330 | dlen = qla27xx_fwdt_template_size(ha->fw_dump_template); | ||
5331 | ql_dbg(ql_dbg_init, vha, 0x016c, | ||
5332 | "-> template size %x bytes\n", dlen); | ||
5333 | ha->fw_dump_template_len = dlen; | ||
5334 | return rval; | ||
5335 | |||
5336 | failed_template: | ||
5337 | ql_log(ql_log_warn, vha, 0x016d, "Failed default fwdump template\n"); | ||
5338 | if (ha->fw_dump_template) | ||
5339 | vfree(ha->fw_dump_template); | ||
5340 | ha->fw_dump_template = NULL; | ||
5341 | ha->fw_dump_template_len = 0; | ||
5120 | return rval; | 5342 | return rval; |
5121 | } | 5343 | } |
5122 | 5344 | ||
@@ -5231,7 +5453,8 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) | |||
5231 | uint32_t risc_size; | 5453 | uint32_t risc_size; |
5232 | uint32_t i; | 5454 | uint32_t i; |
5233 | struct fw_blob *blob; | 5455 | struct fw_blob *blob; |
5234 | uint32_t *fwcode, fwclen; | 5456 | const uint32_t *fwcode; |
5457 | uint32_t fwclen; | ||
5235 | struct qla_hw_data *ha = vha->hw; | 5458 | struct qla_hw_data *ha = vha->hw; |
5236 | struct req_que *req = ha->req_q_map[0]; | 5459 | struct req_que *req = ha->req_q_map[0]; |
5237 | 5460 | ||
@@ -5263,7 +5486,7 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) | |||
5263 | ql_log(ql_log_fatal, vha, 0x0093, | 5486 | ql_log(ql_log_fatal, vha, 0x0093, |
5264 | "Unable to verify integrity of firmware image (%Zd).\n", | 5487 | "Unable to verify integrity of firmware image (%Zd).\n", |
5265 | blob->fw->size); | 5488 | blob->fw->size); |
5266 | goto fail_fw_integrity; | 5489 | return QLA_FUNCTION_FAILED; |
5267 | } | 5490 | } |
5268 | for (i = 0; i < 4; i++) | 5491 | for (i = 0; i < 4; i++) |
5269 | dcode[i] = be32_to_cpu(fwcode[i + 4]); | 5492 | dcode[i] = be32_to_cpu(fwcode[i + 4]); |
@@ -5277,7 +5500,7 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) | |||
5277 | ql_log(ql_log_fatal, vha, 0x0095, | 5500 | ql_log(ql_log_fatal, vha, 0x0095, |
5278 | "Firmware data: %08x %08x %08x %08x.\n", | 5501 | "Firmware data: %08x %08x %08x %08x.\n", |
5279 | dcode[0], dcode[1], dcode[2], dcode[3]); | 5502 | dcode[0], dcode[1], dcode[2], dcode[3]); |
5280 | goto fail_fw_integrity; | 5503 | return QLA_FUNCTION_FAILED; |
5281 | } | 5504 | } |
5282 | 5505 | ||
5283 | while (segments && rval == QLA_SUCCESS) { | 5506 | while (segments && rval == QLA_SUCCESS) { |
@@ -5291,8 +5514,7 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) | |||
5291 | ql_log(ql_log_fatal, vha, 0x0096, | 5514 | ql_log(ql_log_fatal, vha, 0x0096, |
5292 | "Unable to verify integrity of firmware image " | 5515 | "Unable to verify integrity of firmware image " |
5293 | "(%Zd).\n", blob->fw->size); | 5516 | "(%Zd).\n", blob->fw->size); |
5294 | 5517 | return QLA_FUNCTION_FAILED; | |
5295 | goto fail_fw_integrity; | ||
5296 | } | 5518 | } |
5297 | 5519 | ||
5298 | fragment = 0; | 5520 | fragment = 0; |
@@ -5326,10 +5548,100 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) | |||
5326 | /* Next segment. */ | 5548 | /* Next segment. */ |
5327 | segments--; | 5549 | segments--; |
5328 | } | 5550 | } |
5551 | |||
5552 | if (!IS_QLA27XX(ha)) | ||
5553 | return rval; | ||
5554 | |||
5555 | if (ha->fw_dump_template) | ||
5556 | vfree(ha->fw_dump_template); | ||
5557 | ha->fw_dump_template = NULL; | ||
5558 | ha->fw_dump_template_len = 0; | ||
5559 | |||
5560 | ql_dbg(ql_dbg_init, vha, 0x171, | ||
5561 | "Loading fwdump template from %x\n", | ||
5562 | (uint32_t)((void *)fwcode - (void *)blob->fw->data)); | ||
5563 | risc_size = be32_to_cpu(fwcode[2]); | ||
5564 | ql_dbg(ql_dbg_init, vha, 0x172, | ||
5565 | "-> array size %x dwords\n", risc_size); | ||
5566 | if (risc_size == 0 || risc_size == ~0) | ||
5567 | goto default_template; | ||
5568 | |||
5569 | dlen = (risc_size - 8) * sizeof(*fwcode); | ||
5570 | ql_dbg(ql_dbg_init, vha, 0x0173, | ||
5571 | "-> template allocating %x bytes...\n", dlen); | ||
5572 | ha->fw_dump_template = vmalloc(dlen); | ||
5573 | if (!ha->fw_dump_template) { | ||
5574 | ql_log(ql_log_warn, vha, 0x0174, | ||
5575 | "Failed fwdump template allocate %x bytes.\n", risc_size); | ||
5576 | goto default_template; | ||
5577 | } | ||
5578 | |||
5579 | fwcode += 7; | ||
5580 | risc_size -= 8; | ||
5581 | dcode = ha->fw_dump_template; | ||
5582 | for (i = 0; i < risc_size; i++) | ||
5583 | dcode[i] = le32_to_cpu(fwcode[i]); | ||
5584 | |||
5585 | if (!qla27xx_fwdt_template_valid(dcode)) { | ||
5586 | ql_log(ql_log_warn, vha, 0x0175, | ||
5587 | "Failed fwdump template validate\n"); | ||
5588 | goto default_template; | ||
5589 | } | ||
5590 | |||
5591 | dlen = qla27xx_fwdt_template_size(dcode); | ||
5592 | ql_dbg(ql_dbg_init, vha, 0x0176, | ||
5593 | "-> template size %x bytes\n", dlen); | ||
5594 | if (dlen > risc_size * sizeof(*fwcode)) { | ||
5595 | ql_log(ql_log_warn, vha, 0x0177, | ||
5596 | "Failed fwdump template exceeds array by %x bytes\n", | ||
5597 | (uint32_t)(dlen - risc_size * sizeof(*fwcode))); | ||
5598 | goto default_template; | ||
5599 | } | ||
5600 | ha->fw_dump_template_len = dlen; | ||
5329 | return rval; | 5601 | return rval; |
5330 | 5602 | ||
5331 | fail_fw_integrity: | 5603 | default_template: |
5332 | return QLA_FUNCTION_FAILED; | 5604 | ql_log(ql_log_warn, vha, 0x0178, "Using default fwdump template\n"); |
5605 | if (ha->fw_dump_template) | ||
5606 | vfree(ha->fw_dump_template); | ||
5607 | ha->fw_dump_template = NULL; | ||
5608 | ha->fw_dump_template_len = 0; | ||
5609 | |||
5610 | dlen = qla27xx_fwdt_template_default_size(); | ||
5611 | ql_dbg(ql_dbg_init, vha, 0x0179, | ||
5612 | "-> template allocating %x bytes...\n", dlen); | ||
5613 | ha->fw_dump_template = vmalloc(dlen); | ||
5614 | if (!ha->fw_dump_template) { | ||
5615 | ql_log(ql_log_warn, vha, 0x017a, | ||
5616 | "Failed fwdump template allocate %x bytes.\n", risc_size); | ||
5617 | goto failed_template; | ||
5618 | } | ||
5619 | |||
5620 | dcode = ha->fw_dump_template; | ||
5621 | risc_size = dlen / sizeof(*fwcode); | ||
5622 | fwcode = qla27xx_fwdt_template_default(); | ||
5623 | for (i = 0; i < risc_size; i++) | ||
5624 | dcode[i] = be32_to_cpu(fwcode[i]); | ||
5625 | |||
5626 | if (!qla27xx_fwdt_template_valid(ha->fw_dump_template)) { | ||
5627 | ql_log(ql_log_warn, vha, 0x017b, | ||
5628 | "Failed fwdump template validate\n"); | ||
5629 | goto failed_template; | ||
5630 | } | ||
5631 | |||
5632 | dlen = qla27xx_fwdt_template_size(ha->fw_dump_template); | ||
5633 | ql_dbg(ql_dbg_init, vha, 0x017c, | ||
5634 | "-> template size %x bytes\n", dlen); | ||
5635 | ha->fw_dump_template_len = dlen; | ||
5636 | return rval; | ||
5637 | |||
5638 | failed_template: | ||
5639 | ql_log(ql_log_warn, vha, 0x017d, "Failed default fwdump template\n"); | ||
5640 | if (ha->fw_dump_template) | ||
5641 | vfree(ha->fw_dump_template); | ||
5642 | ha->fw_dump_template = NULL; | ||
5643 | ha->fw_dump_template_len = 0; | ||
5644 | return rval; | ||
5333 | } | 5645 | } |
5334 | 5646 | ||
5335 | int | 5647 | int |
@@ -5605,7 +5917,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) | |||
5605 | nv->execution_throttle = __constant_cpu_to_le16(0xFFFF); | 5917 | nv->execution_throttle = __constant_cpu_to_le16(0xFFFF); |
5606 | nv->exchange_count = __constant_cpu_to_le16(0); | 5918 | nv->exchange_count = __constant_cpu_to_le16(0); |
5607 | nv->port_name[0] = 0x21; | 5919 | nv->port_name[0] = 0x21; |
5608 | nv->port_name[1] = 0x00 + ha->port_no; | 5920 | nv->port_name[1] = 0x00 + ha->port_no + 1; |
5609 | nv->port_name[2] = 0x00; | 5921 | nv->port_name[2] = 0x00; |
5610 | nv->port_name[3] = 0xe0; | 5922 | nv->port_name[3] = 0xe0; |
5611 | nv->port_name[4] = 0x8b; | 5923 | nv->port_name[4] = 0x8b; |
@@ -5639,7 +5951,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) | |||
5639 | nv->enode_mac[2] = 0xDD; | 5951 | nv->enode_mac[2] = 0xDD; |
5640 | nv->enode_mac[3] = 0x04; | 5952 | nv->enode_mac[3] = 0x04; |
5641 | nv->enode_mac[4] = 0x05; | 5953 | nv->enode_mac[4] = 0x05; |
5642 | nv->enode_mac[5] = 0x06 + ha->port_no; | 5954 | nv->enode_mac[5] = 0x06 + ha->port_no + 1; |
5643 | 5955 | ||
5644 | rval = 1; | 5956 | rval = 1; |
5645 | } | 5957 | } |
@@ -5677,7 +5989,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) | |||
5677 | icb->enode_mac[2] = 0xDD; | 5989 | icb->enode_mac[2] = 0xDD; |
5678 | icb->enode_mac[3] = 0x04; | 5990 | icb->enode_mac[3] = 0x04; |
5679 | icb->enode_mac[4] = 0x05; | 5991 | icb->enode_mac[4] = 0x05; |
5680 | icb->enode_mac[5] = 0x06 + ha->port_no; | 5992 | icb->enode_mac[5] = 0x06 + ha->port_no + 1; |
5681 | } | 5993 | } |
5682 | 5994 | ||
5683 | /* Use extended-initialization control block. */ | 5995 | /* Use extended-initialization control block. */ |
@@ -5780,7 +6092,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) | |||
5780 | ha->login_retry_count = ql2xloginretrycount; | 6092 | ha->login_retry_count = ql2xloginretrycount; |
5781 | 6093 | ||
5782 | /* if not running MSI-X we need handshaking on interrupts */ | 6094 | /* if not running MSI-X we need handshaking on interrupts */ |
5783 | if (!vha->hw->flags.msix_enabled && IS_QLA83XX(ha)) | 6095 | if (!vha->hw->flags.msix_enabled && (IS_QLA83XX(ha) || IS_QLA27XX(ha))) |
5784 | icb->firmware_options_2 |= __constant_cpu_to_le32(BIT_22); | 6096 | icb->firmware_options_2 |= __constant_cpu_to_le32(BIT_22); |
5785 | 6097 | ||
5786 | /* Enable ZIO. */ | 6098 | /* Enable ZIO. */ |