Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 210486
b: refs/heads/master
c: ea3c645
h: refs/heads/master
v: v3
  • Loading branch information
Gwendal Grignou authored and Jeff Garzik committed Sep 10, 2010
1 parent e6c2da0 commit 9c94da3
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 13 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e2f3d75fc0e4a0d03c61872bad39ffa2e74a04ff
refs/heads/master: ea3c64506ea7965f86f030155e6fdef381de10e2
38 changes: 28 additions & 10 deletions trunk/drivers/ata/libata-sff.c
Original file line number Diff line number Diff line change
Expand Up @@ -1045,7 +1045,8 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
u8 status, int in_wq)
{
struct ata_eh_info *ehi = &ap->link.eh_info;
struct ata_link *link = qc->dev->link;
struct ata_eh_info *ehi = &link->eh_info;
unsigned long flags = 0;
int poll_next;

Expand Down Expand Up @@ -1301,8 +1302,14 @@ int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
}
EXPORT_SYMBOL_GPL(ata_sff_hsm_move);

void ata_sff_queue_pio_task(struct ata_port *ap, unsigned long delay)
void ata_sff_queue_pio_task(struct ata_link *link, unsigned long delay)
{
struct ata_port *ap = link->ap;

WARN_ON((ap->sff_pio_task_link != NULL) &&
(ap->sff_pio_task_link != link));
ap->sff_pio_task_link = link;

/* may fail if ata_sff_flush_pio_task() in progress */
queue_delayed_work(ata_sff_wq, &ap->sff_pio_task,
msecs_to_jiffies(delay));
Expand All @@ -1324,14 +1331,18 @@ static void ata_sff_pio_task(struct work_struct *work)
{
struct ata_port *ap =
container_of(work, struct ata_port, sff_pio_task.work);
struct ata_link *link = ap->sff_pio_task_link;
struct ata_queued_cmd *qc;
u8 status;
int poll_next;

BUG_ON(ap->sff_pio_task_link == NULL);
/* qc can be NULL if timeout occurred */
qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (!qc)
qc = ata_qc_from_tag(ap, link->active_tag);
if (!qc) {
ap->sff_pio_task_link = NULL;
return;
}

fsm_start:
WARN_ON_ONCE(ap->hsm_task_state == HSM_ST_IDLE);
Expand All @@ -1348,11 +1359,16 @@ static void ata_sff_pio_task(struct work_struct *work)
msleep(2);
status = ata_sff_busy_wait(ap, ATA_BUSY, 10);
if (status & ATA_BUSY) {
ata_sff_queue_pio_task(ap, ATA_SHORT_PAUSE);
ata_sff_queue_pio_task(link, ATA_SHORT_PAUSE);
return;
}
}

/*
* hsm_move() may trigger another command to be processed.
* clean the link beforehand.
*/
ap->sff_pio_task_link = NULL;
/* move the HSM */
poll_next = ata_sff_hsm_move(ap, qc, status, 1);

Expand All @@ -1379,6 +1395,7 @@ static void ata_sff_pio_task(struct work_struct *work)
unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct ata_link *link = qc->dev->link;

/* Use polling pio if the LLD doesn't handle
* interrupt driven pio and atapi CDB interrupt.
Expand All @@ -1399,7 +1416,7 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
ap->hsm_task_state = HSM_ST_LAST;

if (qc->tf.flags & ATA_TFLAG_POLLING)
ata_sff_queue_pio_task(ap, 0);
ata_sff_queue_pio_task(link, 0);

break;

Expand All @@ -1412,7 +1429,7 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
if (qc->tf.flags & ATA_TFLAG_WRITE) {
/* PIO data out protocol */
ap->hsm_task_state = HSM_ST_FIRST;
ata_sff_queue_pio_task(ap, 0);
ata_sff_queue_pio_task(link, 0);

/* always send first data block using the
* ata_sff_pio_task() codepath.
Expand All @@ -1422,7 +1439,7 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
ap->hsm_task_state = HSM_ST;

if (qc->tf.flags & ATA_TFLAG_POLLING)
ata_sff_queue_pio_task(ap, 0);
ata_sff_queue_pio_task(link, 0);

/* if polling, ata_sff_pio_task() handles the
* rest. otherwise, interrupt handler takes
Expand All @@ -1444,7 +1461,7 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
/* send cdb by polling if no cdb interrupt */
if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) ||
(qc->tf.flags & ATA_TFLAG_POLLING))
ata_sff_queue_pio_task(ap, 0);
ata_sff_queue_pio_task(link, 0);
break;

default:
Expand Down Expand Up @@ -2737,6 +2754,7 @@ EXPORT_SYMBOL_GPL(ata_bmdma_dumb_qc_prep);
unsigned int ata_bmdma_qc_issue(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct ata_link *link = qc->dev->link;

/* defer PIO handling to sff_qc_issue */
if (!ata_is_dma(qc->tf.protocol))
Expand Down Expand Up @@ -2765,7 +2783,7 @@ unsigned int ata_bmdma_qc_issue(struct ata_queued_cmd *qc)

/* send cdb by polling if no cdb interrupt */
if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
ata_sff_queue_pio_task(ap, 0);
ata_sff_queue_pio_task(link, 0);
break;

default:
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/ata/sata_mv.c
Original file line number Diff line number Diff line change
Expand Up @@ -2284,7 +2284,7 @@ static unsigned int mv_qc_issue_fis(struct ata_queued_cmd *qc)
}

if (qc->tf.flags & ATA_TFLAG_POLLING)
ata_sff_queue_pio_task(ap, 0);
ata_sff_queue_pio_task(link, 0);
return 0;
}

Expand Down
3 changes: 2 additions & 1 deletion trunk/include/linux/libata.h
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,7 @@ struct ata_port {
struct ata_ioports ioaddr; /* ATA cmd/ctl/dma register blocks */
u8 ctl; /* cache of ATA control register */
u8 last_ctl; /* Cache last written value */
struct ata_link* sff_pio_task_link; /* link currently used */
struct delayed_work sff_pio_task;
#ifdef CONFIG_ATA_BMDMA
struct ata_bmdma_prd *bmdma_prd; /* BMDMA SG list */
Expand Down Expand Up @@ -1595,7 +1596,7 @@ extern void ata_sff_irq_on(struct ata_port *ap);
extern void ata_sff_irq_clear(struct ata_port *ap);
extern int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
u8 status, int in_wq);
extern void ata_sff_queue_pio_task(struct ata_port *ap, unsigned long delay);
extern void ata_sff_queue_pio_task(struct ata_link *link, unsigned long delay);
extern unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc);
extern bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc);
extern unsigned int ata_sff_port_intr(struct ata_port *ap,
Expand Down

0 comments on commit 9c94da3

Please sign in to comment.