* Re: Question about invoking of "Task management" functions in USB driver (from newbie)
2009-09-29 19:26 ` Douglas Gilbert
@ 2009-09-29 19:49 ` Greg KH
2009-09-30 9:19 ` yukta eswar
1 sibling, 0 replies; 5+ messages in thread
From: Greg KH @ 2009-09-29 19:49 UTC (permalink / raw)
To: Douglas Gilbert; +Cc: yukta eswar, linux-scsi, linux-usb, FUJITA Tomonori
On Tue, Sep 29, 2009 at 03:26:57PM -0400, Douglas Gilbert wrote:
> Greg KH wrote:
> > On Tue, Sep 29, 2009 at 07:51:47PM +0530, yukta eswar wrote:
> >> Dear Experts,
> >>
> >> I am developing a new USB attached SCSI (UAS) driver for Linux.
> >
> > Why?
> >
> > Do you have a pointer to your source code for your driver?
>
> Greg,
> It would seem that several groups might be working on UAS ***
> drivers for Linux. They may even be in commercial competition.
> Why ask them to show all their cards on the table at this
> stage?
> When they ask informed questions like this one, why not try
> to answer them or find someone (else) who can?
Because there have been at least 5 different people asking questions
like this on the linux-usb list for the past 6 months, with no code
forthcoming.
You don't get a "competitive advantage" with a Linux driver for a USB
class specification. What you do is duplicate effort and make it harder
for everyone involved to help out with the development process by
keeping it private. They are hurting themselves by doing this.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Question about invoking of "Task management" functions in USB driver (from newbie)
2009-09-29 19:26 ` Douglas Gilbert
2009-09-29 19:49 ` Greg KH
@ 2009-09-30 9:19 ` yukta eswar
1 sibling, 0 replies; 5+ messages in thread
From: yukta eswar @ 2009-09-30 9:19 UTC (permalink / raw)
To: dgilbert; +Cc: linux-scsi, linux-usb, FUJITA Tomonori
>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;
}
^ permalink raw reply [flat|nested] 5+ messages in thread