Re: Question about invoking of "Task management" functions in USB driver (from newbie)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



>one way to trip that for
> your testing is to send a SCSI command that is going
> to take some time (e.g. a READ of thousands of blocks
> should take some time, even on flash) and setup the
> command timeout to zero seconds and or close as you can to
> zero.

Actually I am registering my task management functions to
scsi_transport_template. I am handling all my task management
functions in eh_strategy_handler. Whare as in eh_timed_out I am just
completing the request.

Here I am pasting the the code I have with me.

struct scsi_transport_template *
uas_domain_attach_transport(struct uas_domain_function_template *dft)
{
	struct scsi_transport_template *stt = uas_attach_transport();
	struct uas_internal *i;

	PRINTK("<%s> <%s> Entry!\n",__FILE__, __FUNCTION__);

	if (!stt)
		return stt;

	i = to_uas_internal(stt);
	i->dft = dft;
	stt->create_work_queue = 1;
	stt->eh_timed_out = uas_scsi_timed_out;
	stt->eh_strategy_handler = uas_scsi_recover_host;

	PRINTK("<%s> <%s> Exit!\n",__FILE__, __FUNCTION__);
	return stt;
}

void uas_scsi_recover_host(struct Scsi_Host *shost)
{
	struct us_data *us = host_to_us(shost);
	unsigned long flags;
	LIST_HEAD(eh_work_q);

	spin_lock_irqsave(shost->host_lock, flags);
	list_splice_init(&shost->eh_cmd_q, &eh_work_q);
	spin_unlock_irqrestore(shost->host_lock, flags);

	PRINTK("<%s> <%s> Entry!\n",__FILE__, __FUNCTION__);
	
	if (uas_eh_handle_uas_errors(shost, &eh_work_q, &us->eh_done_q))
		goto out;

	
	if (!scsi_eh_get_sense(&eh_work_q, &us->eh_done_q))
		scsi_eh_ready_devs(shost, &eh_work_q, &us->eh_done_q);

out:
	scsi_eh_flush_done_q(&us->eh_done_q);
	PRINTK("<%s> <%s> Exit!\n",__FILE__, __FUNCTION__);
	return;
}



static int uas_eh_handle_uas_errors(struct Scsi_Host *shost,
				    struct list_head *work_q,
				    struct list_head *done_q)
{
	struct scsi_cmnd *cmd, *n;
	enum task_disposition res = TASK_IS_DONE;
	int tmf_resp, need_reset;	
	unsigned long flags;
	struct us_data *us = host_to_us(shost);

	PRINTK("<%s> <%s> Entry!\n",__FILE__, __FUNCTION__);

Again:
	list_for_each_entry_safe(cmd, n, work_q, eh_entry) {
		struct uas_task *task = TO_UAS_TASK(cmd);

		if (!task)
			continue;

		list_del_init(&cmd->eh_entry);

		spin_lock_irqsave(&task->task_state_lock, flags);
		need_reset = task->task_state_flags & UAS_TASK_NEED_DEV_RESET;
		spin_unlock_irqrestore(&task->task_state_lock, flags);

		if (need_reset) {
			PRINTK("%s: task 0x%p requests reset\n",
				    __func__, task);
			goto reset;
		}

		PRINTK("trying to find task 0x%p\n", task);
		res = uas_scsi_find_task(task, us);

		cmd->eh_eflags = 0;

		switch (res) {
		case TASK_IS_DONE:
			PRINTK("%s: task 0x%p is done\n", __func__,
				    task);
			uas_eh_finish_cmd(cmd);
			continue;
		case TASK_IS_ABORTED:
			PRINTK("%s: task 0x%p is aborted\n",
				    __func__, task);
			uas_eh_finish_cmd(cmd);
			continue;
		case TASK_IS_AT_LU:
			PRINTK("task 0x%p is at LU: lu recover\n", task);
 reset:
			tmf_resp = uas_recover_lu(us, cmd);
			if (tmf_resp == TMF_RESP_FUNC_COMPLETE) {
				PRINTK("LU %x is "
					    "recovered\n",
					    cmd->device->lun);
				uas_eh_finish_cmd(cmd);
				uas_scsi_clear_queue_lu(work_q, cmd);
				goto Again;
			}
			/* fallthrough */
		case TASK_IS_NOT_AT_LU:
		case TASK_ABORT_FAILED:
			PRINTK("task 0x%p is not at LU: I_T recover\n",
				    task);
			tmf_resp = uas_recover_I_T(us);
			if (tmf_resp == TMF_RESP_FUNC_COMPLETE) {
				uas_eh_finish_cmd(cmd);
				uas_scsi_clear_queue_I_T(work_q, us);
				goto Again;
			}
			/* Hammer time :-) */
			try_to_reset_cmd_device(cmd);
					
			/* If we are here -- this means that no amount
			 * of effort could recover from errors.  Quite
			 * possibly the HA just disappeared.
			 */
			PRINTK("error from  device LUN %x "
				    "couldn't be recovered in any way\n",
				    cmd->device->lun);

			uas_eh_finish_cmd(cmd);
			goto clear_q;
		}
	}
	return list_empty(work_q);
clear_q:
	PRINTK("--- Exit %s -- clear_q\n", __func__);
	list_for_each_entry_safe(cmd, n, work_q, eh_entry)
		uas_eh_finish_cmd(cmd);

	PRINTK("<%s> <%s> Exit!\n",__FILE__, __FUNCTION__);

	return list_empty(work_q);
}

enum blk_eh_timer_return uas_scsi_timed_out(struct scsi_cmnd *cmd)
{
	struct uas_task *task = TO_UAS_TASK(cmd);
	unsigned long flags;

	if (!task) {
		cmd->request->timeout /= 2;
		PRINTK("command 0x%p, task 0x%p, gone: %s\n",
			    cmd, task, (cmd->request->timeout ?
			    "BLK_EH_RESET_TIMER" : "BLK_EH_NOT_HANDLED"));
		if (!cmd->request->timeout)
			return BLK_EH_NOT_HANDLED;
		return BLK_EH_RESET_TIMER;
	}

	spin_lock_irqsave(&task->task_state_lock, flags);
	BUG_ON(task->task_state_flags & UAS_TASK_STATE_ABORTED);
	if (task->task_state_flags & UAS_TASK_STATE_DONE) {
		spin_unlock_irqrestore(&task->task_state_lock, flags);
		PRINTK("command 0x%p, task 0x%p, timed out: "
			    "BLK_EH_HANDLED\n", cmd, task);
		return BLK_EH_HANDLED;
	}
	if (!(task->task_state_flags & UAS_TASK_AT_INITIATOR)) {
		spin_unlock_irqrestore(&task->task_state_lock, flags);
		PRINTK("command 0x%p, task 0x%p, not at initiator: "
			    "BLK_EH_RESET_TIMER\n",
			    cmd, task);
		return BLK_EH_RESET_TIMER;
	}
	task->task_state_flags |= UAS_TASK_STATE_ABORTED;
	spin_unlock_irqrestore(&task->task_state_lock, flags);

	PRINTK("command 0x%p, task 0x%p, timed out: BLK_EH_NOT_HANDLED\n",
		    cmd, task);

	PRINTK("<%s> <%s> Exit!\n",__FILE__, __FUNCTION__);

	return BLK_EH_NOT_HANDLED;
}
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux