Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7da23b86 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 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
parents 749d2297 421e33d0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -328,6 +328,7 @@ attribute_container_add_attrs(struct device *classdev)
		return sysfs_create_group(&classdev->kobj, cont->grp);

	for (i = 0; attrs[i]; i++) {
		sysfs_attr_init(&attrs[i]->attr);
		error = device_create_file(classdev, attrs[i]);
		if (error)
			return error;
+8 −0
Original line number Diff line number Diff line
@@ -4781,12 +4781,14 @@ static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
	if (err) {
		printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
		       fwname, err);
		asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
		return err;
	}
	if (fw->size < 4) {
		printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
		       fw->size, fwname);
		release_firmware(fw);
		asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
		return -EINVAL;
	}
	chksum = (fw->data[3] << 24) | (fw->data[2] << 16) |
@@ -5110,12 +5112,14 @@ static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
	if (err) {
		printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
		       fwname, err);
		asc_dvc->err_code = ASC_IERR_MCODE_CHKSUM;
		return err;
	}
	if (fw->size < 4) {
		printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
		       fw->size, fwname);
		release_firmware(fw);
		asc_dvc->err_code = ASC_IERR_MCODE_CHKSUM;
		return -EINVAL;
	}
	chksum = (fw->data[3] << 24) | (fw->data[2] << 16) |
@@ -5624,12 +5628,14 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
	if (err) {
		printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
		       fwname, err);
		asc_dvc->err_code = ASC_IERR_MCODE_CHKSUM;
		return err;
	}
	if (fw->size < 4) {
		printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
		       fw->size, fwname);
		release_firmware(fw);
		asc_dvc->err_code = ASC_IERR_MCODE_CHKSUM;
		return -EINVAL;
	}
	chksum = (fw->data[3] << 24) | (fw->data[2] << 16) |
@@ -6124,12 +6130,14 @@ static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
	if (err) {
		printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
		       fwname, err);
		asc_dvc->err_code = ASC_IERR_MCODE_CHKSUM;
		return err;
	}
	if (fw->size < 4) {
		printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
		       fw->size, fwname);
		release_firmware(fw);
		asc_dvc->err_code = ASC_IERR_MCODE_CHKSUM;
		return -EINVAL;
	}
	chksum = (fw->data[3] << 24) | (fw->data[2] << 16) |
+3 −2
Original line number Diff line number Diff line
@@ -3088,14 +3088,15 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
		session->state = ISCSI_STATE_TERMINATE;
	else if (conn->stop_stage != STOP_CONN_RECOVER)
		session->state = ISCSI_STATE_IN_RECOVERY;

	old_stop_stage = conn->stop_stage;
	conn->stop_stage = flag;
	spin_unlock_bh(&session->lock);

	del_timer_sync(&conn->transport_timer);
	iscsi_suspend_tx(conn);

	spin_lock_bh(&session->lock);
	old_stop_stage = conn->stop_stage;
	conn->stop_stage = flag;
	conn->c_stage = ISCSI_CONN_STOPPED;
	spin_unlock_bh(&session->lock);

+109 −52
Original line number Diff line number Diff line
@@ -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 @@ qla1280_load_firmware_pio(struct scsi_qla_host *ha)
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);
+5 −1
Original line number Diff line number Diff line
@@ -1275,7 +1275,11 @@ qla2x00_fw_state_show(struct device *dev, struct device_attribute *attr,
	int rval = QLA_FUNCTION_FAILED;
	uint16_t state[5];

	if (!vha->hw->flags.eeh_busy)
	if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
		test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
		DEBUG2_3_11(printk("%s(%ld): isp reset in progress.\n",
			__func__, vha->host_no));
	else if (!vha->hw->flags.eeh_busy)
		rval = qla2x00_get_firmware_state(vha, state);
	if (rval != QLA_SUCCESS)
		memset(state, -1, sizeof(state));
Loading