diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-04-05 18:37:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-04-05 18:37:12 -0400 |
commit | 7da23b86e14b77c094b11a9fa5ef5b3758fc9193 (patch) | |
tree | 3da1b6c3c105daf61f1fe1c785821213ab6a9dde /drivers/scsi/qla1280.c | |
parent | 749d229761ff0135cc4e16b8a28b41ae2f6b2c35 (diff) | |
parent | 421e33d0045ac0aa119c033b78742e0fbf4c3b21 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6:
[SCSI] qla1280: retain firmware for error recovery
[SCSI] attirbute_container: Initialize sysfs attributes with sysfs_attr_init
[SCSI] advansys: fix regression with request_firmware change
[SCSI] qla2xxx: Updated version number to 8.03.02-k2.
[SCSI] qla2xxx: Prevent sending mbx commands from sysfs during isp reset.
[SCSI] qla2xxx: Disable MSI on qla24xx chips other than QLA2432.
[SCSI] qla2xxx: Check to make sure multique and CPU affinity support is not enabled at the same time.
[SCSI] qla2xxx: Correct vp_idx checking during PORT_UPDATE processing.
[SCSI] qla2xxx: Honour "Extended BB credits" bit for CNAs.
[SCSI] scsi_transport_fc: Make sure commands are completed when rport is offline
[SCSI] libiscsi: Fix recovery slowdown regression
Diffstat (limited to 'drivers/scsi/qla1280.c')
-rw-r--r-- | drivers/scsi/qla1280.c | 161 |
1 files changed, 109 insertions, 52 deletions
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 8ef87781e51d..b8166ecfd0e3 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c | |||
@@ -17,9 +17,11 @@ | |||
17 | * General Public License for more details. | 17 | * General Public License for more details. |
18 | * | 18 | * |
19 | ******************************************************************************/ | 19 | ******************************************************************************/ |
20 | #define QLA1280_VERSION "3.27" | 20 | #define QLA1280_VERSION "3.27.1" |
21 | /***************************************************************************** | 21 | /***************************************************************************** |
22 | Revision History: | 22 | Revision History: |
23 | Rev 3.27.1, February 8, 2010, Michael Reed | ||
24 | - Retain firmware image for error recovery. | ||
23 | Rev 3.27, February 10, 2009, Michael Reed | 25 | Rev 3.27, February 10, 2009, Michael Reed |
24 | - General code cleanup. | 26 | - General code cleanup. |
25 | - Improve error recovery. | 27 | - Improve error recovery. |
@@ -537,9 +539,9 @@ __setup("qla1280=", qla1280_setup); | |||
537 | /*****************************************/ | 539 | /*****************************************/ |
538 | 540 | ||
539 | struct qla_boards { | 541 | struct qla_boards { |
540 | unsigned char name[9]; /* Board ID String */ | 542 | char *name; /* Board ID String */ |
541 | int numPorts; /* Number of SCSI ports */ | 543 | int numPorts; /* Number of SCSI ports */ |
542 | char *fwname; /* firmware name */ | 544 | int fw_index; /* index into qla1280_fw_tbl for firmware */ |
543 | }; | 545 | }; |
544 | 546 | ||
545 | /* NOTE: the last argument in each entry is used to index ql1280_board_tbl */ | 547 | /* NOTE: the last argument in each entry is used to index ql1280_board_tbl */ |
@@ -560,15 +562,30 @@ static struct pci_device_id qla1280_pci_tbl[] = { | |||
560 | }; | 562 | }; |
561 | MODULE_DEVICE_TABLE(pci, qla1280_pci_tbl); | 563 | MODULE_DEVICE_TABLE(pci, qla1280_pci_tbl); |
562 | 564 | ||
565 | DEFINE_MUTEX(qla1280_firmware_mutex); | ||
566 | |||
567 | struct qla_fw { | ||
568 | char *fwname; | ||
569 | const struct firmware *fw; | ||
570 | }; | ||
571 | |||
572 | #define QL_NUM_FW_IMAGES 3 | ||
573 | |||
574 | struct qla_fw qla1280_fw_tbl[QL_NUM_FW_IMAGES] = { | ||
575 | {"qlogic/1040.bin", NULL}, /* image 0 */ | ||
576 | {"qlogic/1280.bin", NULL}, /* image 1 */ | ||
577 | {"qlogic/12160.bin", NULL}, /* image 2 */ | ||
578 | }; | ||
579 | |||
580 | /* NOTE: Order of boards in this table must match order in qla1280_pci_tbl */ | ||
563 | static struct qla_boards ql1280_board_tbl[] = { | 581 | static struct qla_boards ql1280_board_tbl[] = { |
564 | /* Name , Number of ports, FW details */ | 582 | {.name = "QLA12160", .numPorts = 2, .fw_index = 2}, |
565 | {"QLA12160", 2, "qlogic/12160.bin"}, | 583 | {.name = "QLA1040" , .numPorts = 1, .fw_index = 0}, |
566 | {"QLA1040", 1, "qlogic/1040.bin"}, | 584 | {.name = "QLA1080" , .numPorts = 1, .fw_index = 1}, |
567 | {"QLA1080", 1, "qlogic/1280.bin"}, | 585 | {.name = "QLA1240" , .numPorts = 2, .fw_index = 1}, |
568 | {"QLA1240", 2, "qlogic/1280.bin"}, | 586 | {.name = "QLA1280" , .numPorts = 2, .fw_index = 1}, |
569 | {"QLA1280", 2, "qlogic/1280.bin"}, | 587 | {.name = "QLA10160", .numPorts = 1, .fw_index = 2}, |
570 | {"QLA10160", 1, "qlogic/12160.bin"}, | 588 | {.name = " ", .numPorts = 0, .fw_index = -1}, |
571 | {" ", 0, " "}, | ||
572 | }; | 589 | }; |
573 | 590 | ||
574 | static int qla1280_verbose = 1; | 591 | static int qla1280_verbose = 1; |
@@ -1511,6 +1528,63 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha) | |||
1511 | } | 1528 | } |
1512 | 1529 | ||
1513 | /* | 1530 | /* |
1531 | * qla1280_request_firmware | ||
1532 | * Acquire firmware for chip. Retain in memory | ||
1533 | * for error recovery. | ||
1534 | * | ||
1535 | * Input: | ||
1536 | * ha = adapter block pointer. | ||
1537 | * | ||
1538 | * Returns: | ||
1539 | * Pointer to firmware image or an error code | ||
1540 | * cast to pointer via ERR_PTR(). | ||
1541 | */ | ||
1542 | static const struct firmware * | ||
1543 | qla1280_request_firmware(struct scsi_qla_host *ha) | ||
1544 | { | ||
1545 | const struct firmware *fw; | ||
1546 | int err; | ||
1547 | int index; | ||
1548 | char *fwname; | ||
1549 | |||
1550 | spin_unlock_irq(ha->host->host_lock); | ||
1551 | mutex_lock(&qla1280_firmware_mutex); | ||
1552 | |||
1553 | index = ql1280_board_tbl[ha->devnum].fw_index; | ||
1554 | fw = qla1280_fw_tbl[index].fw; | ||
1555 | if (fw) | ||
1556 | goto out; | ||
1557 | |||
1558 | fwname = qla1280_fw_tbl[index].fwname; | ||
1559 | err = request_firmware(&fw, fwname, &ha->pdev->dev); | ||
1560 | |||
1561 | if (err) { | ||
1562 | printk(KERN_ERR "Failed to load image \"%s\" err %d\n", | ||
1563 | fwname, err); | ||
1564 | fw = ERR_PTR(err); | ||
1565 | goto unlock; | ||
1566 | } | ||
1567 | if ((fw->size % 2) || (fw->size < 6)) { | ||
1568 | printk(KERN_ERR "Invalid firmware length %zu in image \"%s\"\n", | ||
1569 | fw->size, fwname); | ||
1570 | release_firmware(fw); | ||
1571 | fw = ERR_PTR(-EINVAL); | ||
1572 | goto unlock; | ||
1573 | } | ||
1574 | |||
1575 | qla1280_fw_tbl[index].fw = fw; | ||
1576 | |||
1577 | out: | ||
1578 | ha->fwver1 = fw->data[0]; | ||
1579 | ha->fwver2 = fw->data[1]; | ||
1580 | ha->fwver3 = fw->data[2]; | ||
1581 | unlock: | ||
1582 | mutex_unlock(&qla1280_firmware_mutex); | ||
1583 | spin_lock_irq(ha->host->host_lock); | ||
1584 | return fw; | ||
1585 | } | ||
1586 | |||
1587 | /* | ||
1514 | * Chip diagnostics | 1588 | * Chip diagnostics |
1515 | * Test chip for proper operation. | 1589 | * Test chip for proper operation. |
1516 | * | 1590 | * |
@@ -1633,30 +1707,18 @@ qla1280_chip_diag(struct scsi_qla_host *ha) | |||
1633 | static int | 1707 | static int |
1634 | qla1280_load_firmware_pio(struct scsi_qla_host *ha) | 1708 | qla1280_load_firmware_pio(struct scsi_qla_host *ha) |
1635 | { | 1709 | { |
1710 | /* enter with host_lock acquired */ | ||
1711 | |||
1636 | const struct firmware *fw; | 1712 | const struct firmware *fw; |
1637 | const __le16 *fw_data; | 1713 | const __le16 *fw_data; |
1638 | uint16_t risc_address, risc_code_size; | 1714 | uint16_t risc_address, risc_code_size; |
1639 | uint16_t mb[MAILBOX_REGISTER_COUNT], i; | 1715 | uint16_t mb[MAILBOX_REGISTER_COUNT], i; |
1640 | int err; | 1716 | int err = 0; |
1717 | |||
1718 | fw = qla1280_request_firmware(ha); | ||
1719 | if (IS_ERR(fw)) | ||
1720 | return PTR_ERR(fw); | ||
1641 | 1721 | ||
1642 | spin_unlock_irq(ha->host->host_lock); | ||
1643 | err = request_firmware(&fw, ql1280_board_tbl[ha->devnum].fwname, | ||
1644 | &ha->pdev->dev); | ||
1645 | spin_lock_irq(ha->host->host_lock); | ||
1646 | if (err) { | ||
1647 | printk(KERN_ERR "Failed to load image \"%s\" err %d\n", | ||
1648 | ql1280_board_tbl[ha->devnum].fwname, err); | ||
1649 | return err; | ||
1650 | } | ||
1651 | if ((fw->size % 2) || (fw->size < 6)) { | ||
1652 | printk(KERN_ERR "Bogus length %zu in image \"%s\"\n", | ||
1653 | fw->size, ql1280_board_tbl[ha->devnum].fwname); | ||
1654 | err = -EINVAL; | ||
1655 | goto out; | ||
1656 | } | ||
1657 | ha->fwver1 = fw->data[0]; | ||
1658 | ha->fwver2 = fw->data[1]; | ||
1659 | ha->fwver3 = fw->data[2]; | ||
1660 | fw_data = (const __le16 *)&fw->data[0]; | 1722 | fw_data = (const __le16 *)&fw->data[0]; |
1661 | ha->fwstart = __le16_to_cpu(fw_data[2]); | 1723 | ha->fwstart = __le16_to_cpu(fw_data[2]); |
1662 | 1724 | ||
@@ -1674,11 +1736,10 @@ qla1280_load_firmware_pio(struct scsi_qla_host *ha) | |||
1674 | if (err) { | 1736 | if (err) { |
1675 | printk(KERN_ERR "scsi(%li): Failed to load firmware\n", | 1737 | printk(KERN_ERR "scsi(%li): Failed to load firmware\n", |
1676 | ha->host_no); | 1738 | ha->host_no); |
1677 | goto out; | 1739 | break; |
1678 | } | 1740 | } |
1679 | } | 1741 | } |
1680 | out: | 1742 | |
1681 | release_firmware(fw); | ||
1682 | return err; | 1743 | return err; |
1683 | } | 1744 | } |
1684 | 1745 | ||
@@ -1686,6 +1747,7 @@ out: | |||
1686 | static int | 1747 | static int |
1687 | qla1280_load_firmware_dma(struct scsi_qla_host *ha) | 1748 | qla1280_load_firmware_dma(struct scsi_qla_host *ha) |
1688 | { | 1749 | { |
1750 | /* enter with host_lock acquired */ | ||
1689 | const struct firmware *fw; | 1751 | const struct firmware *fw; |
1690 | const __le16 *fw_data; | 1752 | const __le16 *fw_data; |
1691 | uint16_t risc_address, risc_code_size; | 1753 | uint16_t risc_address, risc_code_size; |
@@ -1700,24 +1762,10 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha) | |||
1700 | return -ENOMEM; | 1762 | return -ENOMEM; |
1701 | #endif | 1763 | #endif |
1702 | 1764 | ||
1703 | spin_unlock_irq(ha->host->host_lock); | 1765 | fw = qla1280_request_firmware(ha); |
1704 | err = request_firmware(&fw, ql1280_board_tbl[ha->devnum].fwname, | 1766 | if (IS_ERR(fw)) |
1705 | &ha->pdev->dev); | 1767 | return PTR_ERR(fw); |
1706 | spin_lock_irq(ha->host->host_lock); | 1768 | |
1707 | if (err) { | ||
1708 | printk(KERN_ERR "Failed to load image \"%s\" err %d\n", | ||
1709 | ql1280_board_tbl[ha->devnum].fwname, err); | ||
1710 | return err; | ||
1711 | } | ||
1712 | if ((fw->size % 2) || (fw->size < 6)) { | ||
1713 | printk(KERN_ERR "Bogus length %zu in image \"%s\"\n", | ||
1714 | fw->size, ql1280_board_tbl[ha->devnum].fwname); | ||
1715 | err = -EINVAL; | ||
1716 | goto out; | ||
1717 | } | ||
1718 | ha->fwver1 = fw->data[0]; | ||
1719 | ha->fwver2 = fw->data[1]; | ||
1720 | ha->fwver3 = fw->data[2]; | ||
1721 | fw_data = (const __le16 *)&fw->data[0]; | 1769 | fw_data = (const __le16 *)&fw->data[0]; |
1722 | ha->fwstart = __le16_to_cpu(fw_data[2]); | 1770 | ha->fwstart = __le16_to_cpu(fw_data[2]); |
1723 | 1771 | ||
@@ -1802,7 +1850,6 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha) | |||
1802 | #if DUMP_IT_BACK | 1850 | #if DUMP_IT_BACK |
1803 | pci_free_consistent(ha->pdev, 8000, tbuf, p_tbuf); | 1851 | pci_free_consistent(ha->pdev, 8000, tbuf, p_tbuf); |
1804 | #endif | 1852 | #endif |
1805 | release_firmware(fw); | ||
1806 | return err; | 1853 | return err; |
1807 | } | 1854 | } |
1808 | 1855 | ||
@@ -1841,6 +1888,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha) | |||
1841 | static int | 1888 | static int |
1842 | qla1280_load_firmware(struct scsi_qla_host *ha) | 1889 | qla1280_load_firmware(struct scsi_qla_host *ha) |
1843 | { | 1890 | { |
1891 | /* enter with host_lock taken */ | ||
1844 | int err; | 1892 | int err; |
1845 | 1893 | ||
1846 | err = qla1280_chip_diag(ha); | 1894 | err = qla1280_chip_diag(ha); |
@@ -4419,7 +4467,16 @@ qla1280_init(void) | |||
4419 | static void __exit | 4467 | static void __exit |
4420 | qla1280_exit(void) | 4468 | qla1280_exit(void) |
4421 | { | 4469 | { |
4470 | int i; | ||
4471 | |||
4422 | pci_unregister_driver(&qla1280_pci_driver); | 4472 | pci_unregister_driver(&qla1280_pci_driver); |
4473 | /* release any allocated firmware images */ | ||
4474 | for (i = 0; i < QL_NUM_FW_IMAGES; i++) { | ||
4475 | if (qla1280_fw_tbl[i].fw) { | ||
4476 | release_firmware(qla1280_fw_tbl[i].fw); | ||
4477 | qla1280_fw_tbl[i].fw = NULL; | ||
4478 | } | ||
4479 | } | ||
4423 | } | 4480 | } |
4424 | 4481 | ||
4425 | module_init(qla1280_init); | 4482 | module_init(qla1280_init); |