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
This commit is contained in:
Linus Torvalds
2010-04-05 15:37:12 -07:00
11 changed files with 172 additions and 84 deletions
+109 -52
View File
@@ -17,9 +17,11 @@
* General Public License for more details.
*
******************************************************************************/
#define QLA1280_VERSION "3.27"
#define QLA1280_VERSION "3.27.1"
/*****************************************************************************
Revision History:
Rev 3.27.1, February 8, 2010, Michael Reed
- Retain firmware image for error recovery.
Rev 3.27, February 10, 2009, Michael Reed
- General code cleanup.
- Improve error recovery.
@@ -537,9 +539,9 @@ __setup("qla1280=", qla1280_setup);
/*****************************************/
struct qla_boards {
unsigned char name[9]; /* Board ID String */
char *name; /* Board ID String */
int numPorts; /* Number of SCSI ports */
char *fwname; /* firmware name */
int fw_index; /* index into qla1280_fw_tbl for firmware */
};
/* 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[] = {
};
MODULE_DEVICE_TABLE(pci, qla1280_pci_tbl);
DEFINE_MUTEX(qla1280_firmware_mutex);
struct qla_fw {
char *fwname;
const struct firmware *fw;
};
#define QL_NUM_FW_IMAGES 3
struct qla_fw qla1280_fw_tbl[QL_NUM_FW_IMAGES] = {
{"qlogic/1040.bin", NULL}, /* image 0 */
{"qlogic/1280.bin", NULL}, /* image 1 */
{"qlogic/12160.bin", NULL}, /* image 2 */
};
/* NOTE: Order of boards in this table must match order in qla1280_pci_tbl */
static struct qla_boards ql1280_board_tbl[] = {
/* Name , Number of ports, FW details */
{"QLA12160", 2, "qlogic/12160.bin"},
{"QLA1040", 1, "qlogic/1040.bin"},
{"QLA1080", 1, "qlogic/1280.bin"},
{"QLA1240", 2, "qlogic/1280.bin"},
{"QLA1280", 2, "qlogic/1280.bin"},
{"QLA10160", 1, "qlogic/12160.bin"},
{" ", 0, " "},
{.name = "QLA12160", .numPorts = 2, .fw_index = 2},
{.name = "QLA1040" , .numPorts = 1, .fw_index = 0},
{.name = "QLA1080" , .numPorts = 1, .fw_index = 1},
{.name = "QLA1240" , .numPorts = 2, .fw_index = 1},
{.name = "QLA1280" , .numPorts = 2, .fw_index = 1},
{.name = "QLA10160", .numPorts = 1, .fw_index = 2},
{.name = " ", .numPorts = 0, .fw_index = -1},
};
static int qla1280_verbose = 1;
@@ -1510,6 +1527,63 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha)
return status;
}
/*
* qla1280_request_firmware
* Acquire firmware for chip. Retain in memory
* for error recovery.
*
* Input:
* ha = adapter block pointer.
*
* Returns:
* Pointer to firmware image or an error code
* cast to pointer via ERR_PTR().
*/
static const struct firmware *
qla1280_request_firmware(struct scsi_qla_host *ha)
{
const struct firmware *fw;
int err;
int index;
char *fwname;
spin_unlock_irq(ha->host->host_lock);
mutex_lock(&qla1280_firmware_mutex);
index = ql1280_board_tbl[ha->devnum].fw_index;
fw = qla1280_fw_tbl[index].fw;
if (fw)
goto out;
fwname = qla1280_fw_tbl[index].fwname;
err = request_firmware(&fw, fwname, &ha->pdev->dev);
if (err) {
printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
fwname, err);
fw = ERR_PTR(err);
goto unlock;
}
if ((fw->size % 2) || (fw->size < 6)) {
printk(KERN_ERR "Invalid firmware length %zu in image \"%s\"\n",
fw->size, fwname);
release_firmware(fw);
fw = ERR_PTR(-EINVAL);
goto unlock;
}
qla1280_fw_tbl[index].fw = fw;
out:
ha->fwver1 = fw->data[0];
ha->fwver2 = fw->data[1];
ha->fwver3 = fw->data[2];
unlock:
mutex_unlock(&qla1280_firmware_mutex);
spin_lock_irq(ha->host->host_lock);
return fw;
}
/*
* Chip diagnostics
* Test chip for proper operation.
@@ -1633,30 +1707,18 @@ qla1280_chip_diag(struct scsi_qla_host *ha)
static int
qla1280_load_firmware_pio(struct scsi_qla_host *ha)
{
/* enter with host_lock acquired */
const struct firmware *fw;
const __le16 *fw_data;
uint16_t risc_address, risc_code_size;
uint16_t mb[MAILBOX_REGISTER_COUNT], i;
int err;
int err = 0;
fw = qla1280_request_firmware(ha);
if (IS_ERR(fw))
return PTR_ERR(fw);
spin_unlock_irq(ha->host->host_lock);
err = request_firmware(&fw, ql1280_board_tbl[ha->devnum].fwname,
&ha->pdev->dev);
spin_lock_irq(ha->host->host_lock);
if (err) {
printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
ql1280_board_tbl[ha->devnum].fwname, err);
return err;
}
if ((fw->size % 2) || (fw->size < 6)) {
printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
fw->size, ql1280_board_tbl[ha->devnum].fwname);
err = -EINVAL;
goto out;
}
ha->fwver1 = fw->data[0];
ha->fwver2 = fw->data[1];
ha->fwver3 = fw->data[2];
fw_data = (const __le16 *)&fw->data[0];
ha->fwstart = __le16_to_cpu(fw_data[2]);
@@ -1674,11 +1736,10 @@ qla1280_load_firmware_pio(struct scsi_qla_host *ha)
if (err) {
printk(KERN_ERR "scsi(%li): Failed to load firmware\n",
ha->host_no);
goto out;
break;
}
}
out:
release_firmware(fw);
return err;
}
@@ -1686,6 +1747,7 @@ out:
static int
qla1280_load_firmware_dma(struct scsi_qla_host *ha)
{
/* enter with host_lock acquired */
const struct firmware *fw;
const __le16 *fw_data;
uint16_t risc_address, risc_code_size;
@@ -1700,24 +1762,10 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
return -ENOMEM;
#endif
spin_unlock_irq(ha->host->host_lock);
err = request_firmware(&fw, ql1280_board_tbl[ha->devnum].fwname,
&ha->pdev->dev);
spin_lock_irq(ha->host->host_lock);
if (err) {
printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
ql1280_board_tbl[ha->devnum].fwname, err);
return err;
}
if ((fw->size % 2) || (fw->size < 6)) {
printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
fw->size, ql1280_board_tbl[ha->devnum].fwname);
err = -EINVAL;
goto out;
}
ha->fwver1 = fw->data[0];
ha->fwver2 = fw->data[1];
ha->fwver3 = fw->data[2];
fw = qla1280_request_firmware(ha);
if (IS_ERR(fw))
return PTR_ERR(fw);
fw_data = (const __le16 *)&fw->data[0];
ha->fwstart = __le16_to_cpu(fw_data[2]);
@@ -1802,7 +1850,6 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
#if DUMP_IT_BACK
pci_free_consistent(ha->pdev, 8000, tbuf, p_tbuf);
#endif
release_firmware(fw);
return err;
}
@@ -1841,6 +1888,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha)
static int
qla1280_load_firmware(struct scsi_qla_host *ha)
{
/* enter with host_lock taken */
int err;
err = qla1280_chip_diag(ha);
@@ -4419,7 +4467,16 @@ qla1280_init(void)
static void __exit
qla1280_exit(void)
{
int i;
pci_unregister_driver(&qla1280_pci_driver);
/* release any allocated firmware images */
for (i = 0; i < QL_NUM_FW_IMAGES; i++) {
if (qla1280_fw_tbl[i].fw) {
release_firmware(qla1280_fw_tbl[i].fw);
qla1280_fw_tbl[i].fw = NULL;
}
}
}
module_init(qla1280_init);