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

Commit 16bca1d5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
SCSI fixes on 20120224:
 "This is a set of assorted bug fixes for power management, mpt2sas,
  ipr, the rdac device handler and quite a big chunk for qla2xxx (plus a
  use after free of scsi_host in scsi_scan.c). "

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6:
  [SCSI] scsi_dh_rdac: Fix for unbalanced reference count
  [SCSI] scsi_pm: Fix bug in the SCSI power management handler
  [SCSI] scsi_scan: Fix 'Poison overwritten' warning caused by using freed 'shost'
  [SCSI] qla2xxx: Update version number to 8.03.07.13-k.
  [SCSI] qla2xxx: Proper detection of firmware abort error code for ISP82xx.
  [SCSI] qla2xxx: Remove resetting memory during device initialization for ISP82xx.
  [SCSI] qla2xxx: Complete mailbox command timedout to avoid initialization failures during next reset cycle.
  [SCSI] qla2xxx: Remove check for null fcport from host reset handler.
  [SCSI] qla2xxx: Correct out of bounds read of ISP2200 mailbox registers.
  [SCSI] qla2xxx: Remove errant clearing of MBX_INTERRUPT flag during CT-IOCB processing.
  [SCSI] qla2xxx: Clear options-flags while issuing stop-firmware mbx command.
  [SCSI] qla2xxx: Add an "is reset active" helper.
  [SCSI] qla2xxx: Add check for null fcport references in qla2xxx_queuecommand.
  [SCSI] qla2xxx: Propagate up abort failures.
  [SCSI] isci: Fix NULL ptr dereference when no firmware is being loaded
  [SCSI] ipr: fix eeh recovery for 64-bit adapters
  [SCSI] mpt2sas: Fix mismatch in mpt2sas_base_hard_reset_handler() mutex lock-unlock
parents e98092be 3569e537
Loading
Loading
Loading
Loading
+14 −11
Original line number Diff line number Diff line
@@ -364,10 +364,7 @@ static void release_controller(struct kref *kref)
	struct rdac_controller *ctlr;
	ctlr = container_of(kref, struct rdac_controller, kref);

	flush_workqueue(kmpath_rdacd);
	spin_lock(&list_lock);
	list_del(&ctlr->node);
	spin_unlock(&list_lock);
	kfree(ctlr);
}

@@ -376,20 +373,17 @@ static struct rdac_controller *get_controller(int index, char *array_name,
{
	struct rdac_controller *ctlr, *tmp;

	spin_lock(&list_lock);

	list_for_each_entry(tmp, &ctlr_list, node) {
		if ((memcmp(tmp->array_id, array_id, UNIQUE_ID_LEN) == 0) &&
			  (tmp->index == index) &&
			  (tmp->host == sdev->host)) {
			kref_get(&tmp->kref);
			spin_unlock(&list_lock);
			return tmp;
		}
	}
	ctlr = kmalloc(sizeof(*ctlr), GFP_ATOMIC);
	if (!ctlr)
		goto done;
		return NULL;

	/* initialize fields of controller */
	memcpy(ctlr->array_id, array_id, UNIQUE_ID_LEN);
@@ -405,8 +399,7 @@ static struct rdac_controller *get_controller(int index, char *array_name,
	INIT_WORK(&ctlr->ms_work, send_mode_select);
	INIT_LIST_HEAD(&ctlr->ms_head);
	list_add(&ctlr->node, &ctlr_list);
done:
	spin_unlock(&list_lock);

	return ctlr;
}

@@ -517,9 +510,12 @@ static int initialize_controller(struct scsi_device *sdev,
			index = 0;
		else
			index = 1;

		spin_lock(&list_lock);
		h->ctlr = get_controller(index, array_name, array_id, sdev);
		if (!h->ctlr)
			err = SCSI_DH_RES_TEMP_UNAVAIL;
		spin_unlock(&list_lock);
	}
	return err;
}
@@ -906,7 +902,9 @@ static int rdac_bus_attach(struct scsi_device *sdev)
	return 0;

clean_ctlr:
	spin_lock(&list_lock);
	kref_put(&h->ctlr->kref, release_controller);
	spin_unlock(&list_lock);

failed:
	kfree(scsi_dh_data);
@@ -921,14 +919,19 @@ static void rdac_bus_detach( struct scsi_device *sdev )
	struct rdac_dh_data *h;
	unsigned long flags;

	spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
	scsi_dh_data = sdev->scsi_dh_data;
	h = (struct rdac_dh_data *) scsi_dh_data->buf;
	if (h->ctlr && h->ctlr->ms_queued)
		flush_workqueue(kmpath_rdacd);

	spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
	sdev->scsi_dh_data = NULL;
	spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);

	h = (struct rdac_dh_data *) scsi_dh_data->buf;
	spin_lock(&list_lock);
	if (h->ctlr)
		kref_put(&h->ctlr->kref, release_controller);
	spin_unlock(&list_lock);
	kfree(scsi_dh_data);
	module_put(THIS_MODULE);
	sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", RDAC_NAME);
+18 −6
Original line number Diff line number Diff line
@@ -4613,11 +4613,13 @@ static int __ipr_eh_host_reset(struct scsi_cmnd * scsi_cmd)
	ENTER;
	ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata;

	if (!ioa_cfg->in_reset_reload) {
		dev_err(&ioa_cfg->pdev->dev,
			"Adapter being reset as a result of error recovery.\n");

		if (WAIT_FOR_DUMP == ioa_cfg->sdt_state)
			ioa_cfg->sdt_state = GET_DUMP;
	}

	rc = ipr_reset_reload(ioa_cfg, IPR_SHUTDOWN_ABBREV);

@@ -4907,7 +4909,7 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
	struct ipr_ioa_cfg *ioa_cfg;
	struct ipr_resource_entry *res;
	struct ipr_cmd_pkt *cmd_pkt;
	u32 ioasc;
	u32 ioasc, int_reg;
	int op_found = 0;

	ENTER;
@@ -4920,7 +4922,17 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
	 */
	if (ioa_cfg->in_reset_reload || ioa_cfg->ioa_is_dead)
		return FAILED;
	if (!res || !ipr_is_gscsi(res))
	if (!res)
		return FAILED;

	/*
	 * If we are aborting a timed out op, chances are that the timeout was caused
	 * by a still not detected EEH error. In such cases, reading a register will
	 * trigger the EEH recovery infrastructure.
	 */
	int_reg = readl(ioa_cfg->regs.sense_interrupt_reg);

	if (!ipr_is_gscsi(res))
		return FAILED;

	list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) {
+3 −1
Original line number Diff line number Diff line
@@ -1848,9 +1848,11 @@ static enum sci_status sci_oem_parameters_set(struct isci_host *ihost)
	if (state == SCIC_RESET ||
	    state == SCIC_INITIALIZING ||
	    state == SCIC_INITIALIZED) {
		u8 oem_version = pci_info->orom ? pci_info->orom->hdr.version :
			ISCI_ROM_VER_1_0;

		if (sci_oem_parameters_validate(&ihost->oem_parameters,
						pci_info->orom->hdr.version))
						oem_version))
			return SCI_FAILURE_INVALID_PARAMETER_VALUE;

		return SCI_SUCCESS;
+2 −1
Original line number Diff line number Diff line
@@ -4548,7 +4548,7 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
		printk(MPT2SAS_ERR_FMT "%s: pci error recovery reset\n",
		    ioc->name, __func__);
		r = 0;
		goto out;
		goto out_unlocked;
	}

	if (mpt2sas_fwfault_debug)
@@ -4604,6 +4604,7 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
	spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
	mutex_unlock(&ioc->reset_in_progress_mutex);

 out_unlocked:
	dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit\n", ioc->name,
	    __func__));
	return r;
+4 −9
Original line number Diff line number Diff line
@@ -1036,8 +1036,7 @@ qla2x00_link_state_show(struct device *dev, struct device_attribute *attr,
	    vha->device_flags & DFLG_NO_CABLE)
		len = snprintf(buf, PAGE_SIZE, "Link Down\n");
	else if (atomic_read(&vha->loop_state) != LOOP_READY ||
	    test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
	    test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
	    qla2x00_reset_active(vha))
		len = snprintf(buf, PAGE_SIZE, "Unknown Link State\n");
	else {
		len = snprintf(buf, PAGE_SIZE, "Link Up - ");
@@ -1359,8 +1358,7 @@ qla2x00_thermal_temp_show(struct device *dev,
		return snprintf(buf, PAGE_SIZE, "\n");

	temp = frac = 0;
	if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
	    test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
	if (qla2x00_reset_active(vha))
		ql_log(ql_log_warn, vha, 0x707b,
		    "ISP reset active.\n");
	else if (!vha->hw->flags.eeh_busy)
@@ -1379,8 +1377,7 @@ qla2x00_fw_state_show(struct device *dev, struct device_attribute *attr,
	int rval = QLA_FUNCTION_FAILED;
	uint16_t state[5];

	if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
		test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
	if (qla2x00_reset_active(vha))
		ql_log(ql_log_warn, vha, 0x707c,
		    "ISP reset active.\n");
	else if (!vha->hw->flags.eeh_busy)
@@ -1693,9 +1690,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
	if (IS_FWI2_CAPABLE(ha)) {
		rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma);
	} else if (atomic_read(&base_vha->loop_state) == LOOP_READY &&
		    !test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) &&
		    !test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags) &&
		    !ha->dpc_active) {
	    !qla2x00_reset_active(vha) && !ha->dpc_active) {
		/* Must be in a 'READY' state for statistics retrieval. */
		rval = qla2x00_get_link_status(base_vha, base_vha->loop_id,
						stats, stats_dma);
Loading