Commit 251a1524 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull SCSI fixes from James Bottomley:
 "Seven fixes, five in drivers.

  The two core changes are a trivial warning removal in scsi_scan.c and
  a change to rescan for capacity when a device makes a user induced
  (via a write to the state variable) offline->running transition to fix
  issues with device mapper"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: core: Fix capacity set to zero after offlinining device
  scsi: sr: Return correct event when media event code is 3
  scsi: ibmvfc: Fix command state accounting and stale response detection
  scsi: core: Avoid printing an error if target_alloc() returns -ENXIO
  scsi: scsi_dh_rdac: Avoid crash during rdac_bus_attach()
  scsi: megaraid_mm: Fix end of loop tests for list_for_each_entry()
  scsi: pm80xx: Fix TMF task completion race condition
parents 0c2e31d2 f0f82e24
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -453,8 +453,8 @@ static int initialize_controller(struct scsi_device *sdev,
		if (!h->ctlr)
			err = SCSI_DH_RES_TEMP_UNAVAIL;
		else {
			list_add_rcu(&h->node, &h->ctlr->dh_list);
			h->sdev = sdev;
			list_add_rcu(&h->node, &h->ctlr->dh_list);
		}
		spin_unlock(&list_lock);
		err = SCSI_DH_OK;
@@ -778,11 +778,11 @@ static void rdac_bus_detach( struct scsi_device *sdev )
	spin_lock(&list_lock);
	if (h->ctlr) {
		list_del_rcu(&h->node);
		h->sdev = NULL;
		kref_put(&h->ctlr->kref, release_controller);
	}
	spin_unlock(&list_lock);
	sdev->handler_data = NULL;
	synchronize_rcu();
	kfree(h);
}

+17 −2
Original line number Diff line number Diff line
@@ -807,6 +807,13 @@ static int ibmvfc_init_event_pool(struct ibmvfc_host *vhost,
	for (i = 0; i < size; ++i) {
		struct ibmvfc_event *evt = &pool->events[i];

		/*
		 * evt->active states
		 *  1 = in flight
		 *  0 = being completed
		 * -1 = free/freed
		 */
		atomic_set(&evt->active, -1);
		atomic_set(&evt->free, 1);
		evt->crq.valid = 0x80;
		evt->crq.ioba = cpu_to_be64(pool->iu_token + (sizeof(*evt->xfer_iu) * i));
@@ -1017,6 +1024,7 @@ static void ibmvfc_free_event(struct ibmvfc_event *evt)

	BUG_ON(!ibmvfc_valid_event(pool, evt));
	BUG_ON(atomic_inc_return(&evt->free) != 1);
	BUG_ON(atomic_dec_and_test(&evt->active));

	spin_lock_irqsave(&evt->queue->l_lock, flags);
	list_add_tail(&evt->queue_list, &evt->queue->free);
@@ -1072,6 +1080,12 @@ static void ibmvfc_complete_purge(struct list_head *purge_list)
 **/
static void ibmvfc_fail_request(struct ibmvfc_event *evt, int error_code)
{
	/*
	 * Anything we are failing should still be active. Otherwise, it
	 * implies we already got a response for the command and are doing
	 * something bad like double completing it.
	 */
	BUG_ON(!atomic_dec_and_test(&evt->active));
	if (evt->cmnd) {
		evt->cmnd->result = (error_code << 16);
		evt->done = ibmvfc_scsi_eh_done;
@@ -1723,6 +1737,7 @@ static int ibmvfc_send_event(struct ibmvfc_event *evt,

		evt->done(evt);
	} else {
		atomic_set(&evt->active, 1);
		spin_unlock_irqrestore(&evt->queue->l_lock, flags);
		ibmvfc_trc_start(evt);
	}
@@ -3251,7 +3266,7 @@ static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost,
		return;
	}

	if (unlikely(atomic_read(&evt->free))) {
	if (unlikely(atomic_dec_if_positive(&evt->active))) {
		dev_err(vhost->dev, "Received duplicate correlation_token 0x%08llx!\n",
			crq->ioba);
		return;
@@ -3778,7 +3793,7 @@ static void ibmvfc_handle_scrq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost
		return;
	}

	if (unlikely(atomic_read(&evt->free))) {
	if (unlikely(atomic_dec_if_positive(&evt->active))) {
		dev_err(vhost->dev, "Received duplicate correlation_token 0x%08llx!\n",
			crq->ioba);
		return;
+1 −0
Original line number Diff line number Diff line
@@ -745,6 +745,7 @@ struct ibmvfc_event {
	struct ibmvfc_target *tgt;
	struct scsi_cmnd *cmnd;
	atomic_t free;
	atomic_t active;
	union ibmvfc_iu *xfer_iu;
	void (*done)(struct ibmvfc_event *evt);
	void (*_done)(struct ibmvfc_event *evt);
+15 −6
Original line number Diff line number Diff line
@@ -238,7 +238,7 @@ mraid_mm_get_adapter(mimd_t __user *umimd, int *rval)
	mimd_t		mimd;
	uint32_t	adapno;
	int		iterator;

	bool		is_found;

	if (copy_from_user(&mimd, umimd, sizeof(mimd_t))) {
		*rval = -EFAULT;
@@ -254,12 +254,16 @@ mraid_mm_get_adapter(mimd_t __user *umimd, int *rval)

	adapter = NULL;
	iterator = 0;
	is_found = false;

	list_for_each_entry(adapter, &adapters_list_g, list) {
		if (iterator++ == adapno) break;
		if (iterator++ == adapno) {
			is_found = true;
			break;
		}
	}

	if (!adapter) {
	if (!is_found) {
		*rval = -ENODEV;
		return NULL;
	}
@@ -725,6 +729,7 @@ ioctl_done(uioc_t *kioc)
	uint32_t	adapno;
	int		iterator;
	mraid_mmadp_t*	adapter;
	bool		is_found;

	/*
	 * When the kioc returns from driver, make sure it still doesn't
@@ -747,19 +752,23 @@ ioctl_done(uioc_t *kioc)
		iterator	= 0;
		adapter		= NULL;
		adapno		= kioc->adapno;
		is_found	= false;

		con_log(CL_ANN, ( KERN_WARNING "megaraid cmm: completed "
					"ioctl that was timedout before\n"));

		list_for_each_entry(adapter, &adapters_list_g, list) {
			if (iterator++ == adapno) break;
			if (iterator++ == adapno) {
				is_found = true;
				break;
			}
		}

		kioc->timedout = 0;

		if (adapter) {
		if (is_found)
			mraid_mm_dealloc_kioc( adapter, kioc );
		}

	}
	else {
		wake_up(&wait_q);
+15 −17
Original line number Diff line number Diff line
@@ -684,8 +684,7 @@ int pm8001_dev_found(struct domain_device *dev)

void pm8001_task_done(struct sas_task *task)
{
	if (!del_timer(&task->slow_task->timer))
		return;
	del_timer(&task->slow_task->timer);
	complete(&task->slow_task->completion);
}

@@ -693,10 +692,15 @@ static void pm8001_tmf_timedout(struct timer_list *t)
{
	struct sas_task_slow *slow = from_timer(slow, t, timer);
	struct sas_task *task = slow->task;
	unsigned long flags;

	spin_lock_irqsave(&task->task_state_lock, flags);
	if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
		task->task_state_flags |= SAS_TASK_STATE_ABORTED;
		complete(&task->slow_task->completion);
	}
	spin_unlock_irqrestore(&task->task_state_lock, flags);
}

#define PM8001_TASK_TIMEOUT 20
/**
@@ -748,14 +752,11 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev,
		}
		res = -TMF_RESP_FUNC_FAILED;
		/* Even TMF timed out, return direct. */
		if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
			if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
				pm8001_dbg(pm8001_ha, FAIL,
					   "TMF task[%x]timeout.\n",
		if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
			pm8001_dbg(pm8001_ha, FAIL, "TMF task[%x]timeout.\n",
				   tmf->tmf);
			goto ex_err;
		}
		}

		if (task->task_status.resp == SAS_TASK_COMPLETE &&
			task->task_status.stat == SAS_SAM_STAT_GOOD) {
@@ -834,13 +835,10 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
		wait_for_completion(&task->slow_task->completion);
		res = TMF_RESP_FUNC_FAILED;
		/* Even TMF timed out, return direct. */
		if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
			if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
				pm8001_dbg(pm8001_ha, FAIL,
					   "TMF task timeout.\n");
		if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
			pm8001_dbg(pm8001_ha, FAIL, "TMF task timeout.\n");
			goto ex_err;
		}
		}

		if (task->task_status.resp == SAS_TASK_COMPLETE &&
			task->task_status.stat == SAS_SAM_STAT_GOOD) {
Loading