* [PATCH 3/4] libata: kill unused pio_task and packet_task
2006-03-05 6:29 [PATCHSET] implement and use port_task Tejun Heo
@ 2006-03-05 6:29 ` Tejun Heo
2006-03-05 6:29 ` [PATCH 2/4] libata: convert pio_task and packet_task to port_task Tejun Heo
` (2 subsequent siblings)
3 siblings, 0 replies; 8+ messages in thread
From: Tejun Heo @ 2006-03-05 6:29 UTC (permalink / raw)
To: jgarzik, albertcc, linux-ide; +Cc: Tejun Heo
Kill unused pio_task and packet_task.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/libata-core.c | 68 --------------------------------------------
include/linux/libata.h | 3 --
2 files changed, 0 insertions(+), 71 deletions(-)
aaf1bca7a373df0a4e301da177d6c71329b98196
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index ebd4072..657b196 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -796,71 +796,6 @@ void ata_port_flush_task(struct ata_port
DPRINTK("EXIT\n");
}
-static inline void
-ata_queue_packet_task(struct ata_port *ap)
-{
- if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK))
- queue_work(ata_wq, &ap->packet_task);
-}
-
-static inline void
-ata_queue_pio_task(struct ata_port *ap)
-{
- if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK))
- queue_work(ata_wq, &ap->pio_task);
-}
-
-static inline void
-ata_queue_delayed_pio_task(struct ata_port *ap, unsigned long delay)
-{
- if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK))
- queue_delayed_work(ata_wq, &ap->pio_task, delay);
-}
-
-/**
- * ata_flush_pio_tasks - Flush pio_task and packet_task
- * @ap: the target ata_port
- *
- * After this function completes, pio_task and packet_task are
- * guranteed not to be running or scheduled.
- *
- * LOCKING:
- * Kernel thread context (may sleep)
- */
-
-static void ata_flush_pio_tasks(struct ata_port *ap)
-{
- int tmp = 0;
- unsigned long flags;
-
- DPRINTK("ENTER\n");
-
- spin_lock_irqsave(&ap->host_set->lock, flags);
- ap->flags |= ATA_FLAG_FLUSH_PIO_TASK;
- spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
- DPRINTK("flush #1\n");
- flush_workqueue(ata_wq);
-
- /*
- * At this point, if a task is running, it's guaranteed to see
- * the FLUSH flag; thus, it will never queue pio tasks again.
- * Cancel and flush.
- */
- tmp |= cancel_delayed_work(&ap->pio_task);
- tmp |= cancel_delayed_work(&ap->packet_task);
- if (!tmp) {
- DPRINTK("flush #2\n");
- flush_workqueue(ata_wq);
- }
-
- spin_lock_irqsave(&ap->host_set->lock, flags);
- ap->flags &= ~ATA_FLAG_FLUSH_PIO_TASK;
- spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
- DPRINTK("EXIT\n");
-}
-
void ata_qc_complete_internal(struct ata_queued_cmd *qc)
{
struct completion *waiting = qc->private_data;
@@ -3675,7 +3610,6 @@ static void ata_qc_timeout(struct ata_qu
DPRINTK("ENTER\n");
- ata_flush_pio_tasks(ap);
ap->hsm_task_state = HSM_ST_IDLE;
spin_lock_irqsave(&host_set->lock, flags);
@@ -4554,8 +4488,6 @@ static void ata_host_init(struct ata_por
ap->last_ctl = 0xFF;
INIT_WORK(&ap->port_task, NULL, NULL);
- INIT_WORK(&ap->packet_task, atapi_packet_task, ap);
- INIT_WORK(&ap->pio_task, ata_pio_task, ap);
INIT_LIST_HEAD(&ap->eh_done_q);
for (i = 0; i < ATA_MAX_DEVICES; i++)
diff --git a/include/linux/libata.h b/include/linux/libata.h
index abc5c6e..d856660 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -390,9 +390,6 @@ struct ata_port {
struct work_struct port_task;
- struct work_struct packet_task;
-
- struct work_struct pio_task;
unsigned int hsm_task_state;
unsigned long pio_task_timeout;
--
1.2.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/4] libata: convert pio_task and packet_task to port_task
2006-03-05 6:29 [PATCHSET] implement and use port_task Tejun Heo
2006-03-05 6:29 ` [PATCH 3/4] libata: kill unused pio_task and packet_task Tejun Heo
@ 2006-03-05 6:29 ` Tejun Heo
2006-03-11 23:43 ` Jeff Garzik
2006-03-05 6:29 ` [PATCH 4/4] libata: rename ATA_FLAG_FLUSH_PIO_TASK to ATA_FLAG_FLUSH_PORT_TASK Tejun Heo
2006-03-05 6:29 ` [PATCH 1/4] libata: implement port_task Tejun Heo
3 siblings, 1 reply; 8+ messages in thread
From: Tejun Heo @ 2006-03-05 6:29 UTC (permalink / raw)
To: jgarzik, albertcc, linux-ide; +Cc: Tejun Heo
Make pio_task and atapi_packet_task use port_task.
atapi_packet_task() is moved upward such that it's right after
ata_pio_task(). This position is more natural and makes adding
prototype for ata_qc_issue_prot() unnecessary.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/libata-core.c | 154 ++++++++++++++++++++++----------------------
1 files changed, 77 insertions(+), 77 deletions(-)
b5b1469010fc9cd99e149f0503cbf6e6f1ac17b2
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 3575d68..ebd4072 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -3570,12 +3570,84 @@ fsm_start:
}
if (timeout)
- ata_queue_delayed_pio_task(ap, timeout);
+ ata_port_queue_task(ap, ata_pio_task, ap, timeout);
else if (!qc_completed)
goto fsm_start;
}
/**
+ * atapi_packet_task - Write CDB bytes to hardware
+ * @_data: Port to which ATAPI device is attached.
+ *
+ * When device has indicated its readiness to accept
+ * a CDB, this function is called. Send the CDB.
+ * If DMA is to be performed, exit immediately.
+ * Otherwise, we are in polling mode, so poll
+ * status under operation succeeds or fails.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep)
+ */
+
+static void atapi_packet_task(void *_data)
+{
+ struct ata_port *ap = _data;
+ struct ata_queued_cmd *qc;
+ u8 status;
+
+ qc = ata_qc_from_tag(ap, ap->active_tag);
+ WARN_ON(qc == NULL);
+ WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
+
+ /* sleep-wait for BSY to clear */
+ DPRINTK("busy wait\n");
+ if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) {
+ qc->err_mask |= AC_ERR_TIMEOUT;
+ goto err_out;
+ }
+
+ /* make sure DRQ is set */
+ status = ata_chk_status(ap);
+ if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) {
+ qc->err_mask |= AC_ERR_HSM;
+ goto err_out;
+ }
+
+ /* send SCSI cdb */
+ DPRINTK("send cdb\n");
+ WARN_ON(qc->dev->cdb_len < 12);
+
+ if (qc->tf.protocol == ATA_PROT_ATAPI_DMA ||
+ qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
+ unsigned long flags;
+
+ /* Once we're done issuing command and kicking bmdma,
+ * irq handler takes over. To not lose irq, we need
+ * to clear NOINTR flag before sending cdb, but
+ * interrupt handler shouldn't be invoked before we're
+ * finished. Hence, the following locking.
+ */
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+ ap->flags &= ~ATA_FLAG_NOINTR;
+ ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1);
+ if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
+ ap->ops->bmdma_start(qc); /* initiate bmdma */
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+ } else {
+ ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1);
+
+ /* PIO commands are handled by polling */
+ ap->hsm_task_state = HSM_ST;
+ ata_port_queue_task(ap, ata_pio_task, ap, 0);
+ }
+
+ return;
+
+err_out:
+ ata_poll_qc_complete(qc);
+}
+
+/**
* ata_qc_timeout - Handle timeout of queued command
* @qc: Command that timed out
*
@@ -3874,26 +3946,26 @@ unsigned int ata_qc_issue_prot(struct at
ata_qc_set_polling(qc);
ata_tf_to_host(ap, &qc->tf);
ap->hsm_task_state = HSM_ST;
- ata_queue_pio_task(ap);
+ ata_port_queue_task(ap, ata_pio_task, ap, 0);
break;
case ATA_PROT_ATAPI:
ata_qc_set_polling(qc);
ata_tf_to_host(ap, &qc->tf);
- ata_queue_packet_task(ap);
+ ata_port_queue_task(ap, atapi_packet_task, ap, 0);
break;
case ATA_PROT_ATAPI_NODATA:
ap->flags |= ATA_FLAG_NOINTR;
ata_tf_to_host(ap, &qc->tf);
- ata_queue_packet_task(ap);
+ ata_port_queue_task(ap, atapi_packet_task, ap, 0);
break;
case ATA_PROT_ATAPI_DMA:
ap->flags |= ATA_FLAG_NOINTR;
ap->ops->tf_load(ap, &qc->tf); /* load tf registers */
ap->ops->bmdma_setup(qc); /* set up bmdma */
- ata_queue_packet_task(ap);
+ ata_port_queue_task(ap, atapi_packet_task, ap, 0);
break;
default:
@@ -4261,78 +4333,6 @@ irqreturn_t ata_interrupt (int irq, void
return IRQ_RETVAL(handled);
}
-/**
- * atapi_packet_task - Write CDB bytes to hardware
- * @_data: Port to which ATAPI device is attached.
- *
- * When device has indicated its readiness to accept
- * a CDB, this function is called. Send the CDB.
- * If DMA is to be performed, exit immediately.
- * Otherwise, we are in polling mode, so poll
- * status under operation succeeds or fails.
- *
- * LOCKING:
- * Kernel thread context (may sleep)
- */
-
-static void atapi_packet_task(void *_data)
-{
- struct ata_port *ap = _data;
- struct ata_queued_cmd *qc;
- u8 status;
-
- qc = ata_qc_from_tag(ap, ap->active_tag);
- WARN_ON(qc == NULL);
- WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
-
- /* sleep-wait for BSY to clear */
- DPRINTK("busy wait\n");
- if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) {
- qc->err_mask |= AC_ERR_TIMEOUT;
- goto err_out;
- }
-
- /* make sure DRQ is set */
- status = ata_chk_status(ap);
- if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) {
- qc->err_mask |= AC_ERR_HSM;
- goto err_out;
- }
-
- /* send SCSI cdb */
- DPRINTK("send cdb\n");
- WARN_ON(qc->dev->cdb_len < 12);
-
- if (qc->tf.protocol == ATA_PROT_ATAPI_DMA ||
- qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
- unsigned long flags;
-
- /* Once we're done issuing command and kicking bmdma,
- * irq handler takes over. To not lose irq, we need
- * to clear NOINTR flag before sending cdb, but
- * interrupt handler shouldn't be invoked before we're
- * finished. Hence, the following locking.
- */
- spin_lock_irqsave(&ap->host_set->lock, flags);
- ap->flags &= ~ATA_FLAG_NOINTR;
- ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1);
- if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
- ap->ops->bmdma_start(qc); /* initiate bmdma */
- spin_unlock_irqrestore(&ap->host_set->lock, flags);
- } else {
- ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1);
-
- /* PIO commands are handled by polling */
- ap->hsm_task_state = HSM_ST;
- ata_queue_pio_task(ap);
- }
-
- return;
-
-err_out:
- ata_poll_qc_complete(qc);
-}
-
/*
* Execute a 'simple' command, that only consists of the opcode 'cmd' itself,
--
1.2.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/4] libata: rename ATA_FLAG_FLUSH_PIO_TASK to ATA_FLAG_FLUSH_PORT_TASK
2006-03-05 6:29 [PATCHSET] implement and use port_task Tejun Heo
2006-03-05 6:29 ` [PATCH 3/4] libata: kill unused pio_task and packet_task Tejun Heo
2006-03-05 6:29 ` [PATCH 2/4] libata: convert pio_task and packet_task to port_task Tejun Heo
@ 2006-03-05 6:29 ` Tejun Heo
2006-03-05 6:29 ` [PATCH 1/4] libata: implement port_task Tejun Heo
3 siblings, 0 replies; 8+ messages in thread
From: Tejun Heo @ 2006-03-05 6:29 UTC (permalink / raw)
To: jgarzik, albertcc, linux-ide; +Cc: Tejun Heo
Rename ATA_FLAG_FLUSH_PIO_TASK to ATA_FLAG_FLUSH_PORT_TASK.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/libata-core.c | 6 +++---
include/linux/libata.h | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
4347020e90c1e2ae5d8d48b27e9d52f7143730e1
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 657b196..6a06c47 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -742,7 +742,7 @@ void ata_port_queue_task(struct ata_port
{
int rc;
- if (ap->flags & ATA_FLAG_FLUSH_PIO_TASK)
+ if (ap->flags & ATA_FLAG_FLUSH_PORT_TASK)
return;
PREPARE_WORK(&ap->port_task, fn, data);
@@ -773,7 +773,7 @@ void ata_port_flush_task(struct ata_port
DPRINTK("ENTER\n");
spin_lock_irqsave(&ap->host_set->lock, flags);
- ap->flags |= ATA_FLAG_FLUSH_PIO_TASK;
+ ap->flags |= ATA_FLAG_FLUSH_PORT_TASK;
spin_unlock_irqrestore(&ap->host_set->lock, flags);
DPRINTK("flush #1\n");
@@ -790,7 +790,7 @@ void ata_port_flush_task(struct ata_port
}
spin_lock_irqsave(&ap->host_set->lock, flags);
- ap->flags &= ~ATA_FLAG_FLUSH_PIO_TASK;
+ ap->flags &= ~ATA_FLAG_FLUSH_PORT_TASK;
spin_unlock_irqrestore(&ap->host_set->lock, flags);
DPRINTK("EXIT\n");
diff --git a/include/linux/libata.h b/include/linux/libata.h
index d856660..034f515 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -151,7 +151,7 @@ enum {
ATA_FLAG_PIO_LBA48 = (1 << 13), /* Host DMA engine is LBA28 only */
ATA_FLAG_IRQ_MASK = (1 << 14), /* Mask IRQ in PIO xfers */
- ATA_FLAG_FLUSH_PIO_TASK = (1 << 15), /* Flush PIO task */
+ ATA_FLAG_FLUSH_PORT_TASK = (1 << 15), /* Flush port task */
ATA_FLAG_IN_EH = (1 << 16), /* EH in progress */
ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */
--
1.2.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCHSET] implement and use port_task
@ 2006-03-05 6:29 Tejun Heo
2006-03-05 6:29 ` [PATCH 3/4] libata: kill unused pio_task and packet_task Tejun Heo
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Tejun Heo @ 2006-03-05 6:29 UTC (permalink / raw)
To: jgarzik, albertcc, linux-ide, htejun
Hello, Jeff and Albert.
This patchset implements port_task and replace pio_task and
packet_task with it. port_task isn't very different from pio_task or
packet_task - it's straight forward generalization. The port_task is
a per-port task avaliable to low level drivers which is managed by
libata core layer.
Differences from pio/packet task.
* Not limited to PIO HSM implementation. Other drivers can use it.
* Synchronization against EH core layer is done within libata core
layer, not in PIO HSM implementation (ata_qc_timeout()).
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/4] libata: implement port_task
2006-03-05 6:29 [PATCHSET] implement and use port_task Tejun Heo
` (2 preceding siblings ...)
2006-03-05 6:29 ` [PATCH 4/4] libata: rename ATA_FLAG_FLUSH_PIO_TASK to ATA_FLAG_FLUSH_PORT_TASK Tejun Heo
@ 2006-03-05 6:29 ` Tejun Heo
2006-03-05 16:09 ` Jeff Garzik
3 siblings, 1 reply; 8+ messages in thread
From: Tejun Heo @ 2006-03-05 6:29 UTC (permalink / raw)
To: jgarzik, albertcc, linux-ide; +Cc: Tejun Heo
Implement port_task. LLDD's can schedule a function to be executed
with context after specified delay. libata core takes care of
synchronization against EH. This is generalized form of pio_task and
packet_task which are tied to PIO hsm implementation.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/libata-core.c | 77 ++++++++++++++++++++++++++++++++++++++++++++
drivers/scsi/libata-scsi.c | 2 +
drivers/scsi/libata.h | 1 +
include/linux/libata.h | 4 ++
4 files changed, 84 insertions(+), 0 deletions(-)
4d83950873856672ed469f25c6421de1eb98ba97
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index b710fc4..3575d68 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -721,6 +721,81 @@ static unsigned int ata_pio_modes(const
timing API will get this right anyway */
}
+/**
+ * ata_port_queue_task - Queue port_task
+ * @ap: The ata_port to queue port_task for
+ *
+ * Schedule @fn(@data) for execution after @delay jiffies using
+ * port_task. There is one port_task per port and it's the
+ * user(low level driver)'s responsibility to make sure that only
+ * one task is active at any given time.
+ *
+ * libata core layer takes care of synchronization between
+ * port_task and EH. ata_port_queue_task() may be ignored for EH
+ * synchronization.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data,
+ unsigned long delay)
+{
+ int rc;
+
+ if (ap->flags & ATA_FLAG_FLUSH_PIO_TASK)
+ return;
+
+ PREPARE_WORK(&ap->port_task, fn, data);
+
+ if (!delay)
+ rc = queue_work(ata_wq, &ap->port_task);
+ else
+ rc = queue_delayed_work(ata_wq, &ap->port_task, delay);
+
+ /* rc == 0 means that another user is using port task */
+ WARN_ON(rc == 0);
+}
+
+/**
+ * ata_port_flush_task - Flush port_task
+ * @ap: The ata_port to flush port_task for
+ *
+ * After this function completes, port_task is guranteed not to
+ * be running or scheduled.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep)
+ */
+void ata_port_flush_task(struct ata_port *ap)
+{
+ unsigned long flags;
+
+ DPRINTK("ENTER\n");
+
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+ ap->flags |= ATA_FLAG_FLUSH_PIO_TASK;
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+ DPRINTK("flush #1\n");
+ flush_workqueue(ata_wq);
+
+ /*
+ * At this point, if a task is running, it's guaranteed to see
+ * the FLUSH flag; thus, it will never queue pio tasks again.
+ * Cancel and flush.
+ */
+ if (!cancel_delayed_work(&ap->port_task)) {
+ DPRINTK("flush #2\n");
+ flush_workqueue(ata_wq);
+ }
+
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+ ap->flags &= ~ATA_FLAG_FLUSH_PIO_TASK;
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+ DPRINTK("EXIT\n");
+}
+
static inline void
ata_queue_packet_task(struct ata_port *ap)
{
@@ -4478,6 +4553,7 @@ static void ata_host_init(struct ata_por
ap->active_tag = ATA_TAG_POISON;
ap->last_ctl = 0xFF;
+ INIT_WORK(&ap->port_task, NULL, NULL);
INIT_WORK(&ap->packet_task, atapi_packet_task, ap);
INIT_WORK(&ap->pio_task, ata_pio_task, ap);
INIT_LIST_HEAD(&ap->eh_done_q);
@@ -4948,6 +5024,7 @@ EXPORT_SYMBOL_GPL(ata_drive_probe_reset)
EXPORT_SYMBOL_GPL(ata_port_disable);
EXPORT_SYMBOL_GPL(ata_ratelimit);
EXPORT_SYMBOL_GPL(ata_busy_sleep);
+EXPORT_SYMBOL_GPL(ata_port_queue_task);
EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
EXPORT_SYMBOL_GPL(ata_scsi_timed_out);
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index d0bd94a..ccedb45 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -785,6 +785,8 @@ int ata_scsi_error(struct Scsi_Host *hos
WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL);
spin_unlock_irqrestore(&ap->host_set->lock, flags);
+ ata_port_flush_task(ap);
+
ap->ops->eng_timeout(ap);
WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q));
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index d822eba..f4c48c9 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -45,6 +45,7 @@ extern int libata_fua;
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
struct ata_device *dev);
extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
+extern void ata_port_flush_task(struct ata_port *ap);
extern void ata_qc_free(struct ata_queued_cmd *qc);
extern unsigned int ata_qc_issue(struct ata_queued_cmd *qc);
extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 86a504f..abc5c6e 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -388,6 +388,8 @@ struct ata_port {
struct ata_host_stats stats;
struct ata_host_set *host_set;
+ struct work_struct port_task;
+
struct work_struct packet_task;
struct work_struct pio_task;
@@ -513,6 +515,8 @@ extern int ata_ratelimit(void);
extern unsigned int ata_busy_sleep(struct ata_port *ap,
unsigned long timeout_pat,
unsigned long timeout);
+extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *),
+ void *data, unsigned long delay);
/*
* Default driver ops implementations
--
1.2.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/4] libata: implement port_task
2006-03-05 6:29 ` [PATCH 1/4] libata: implement port_task Tejun Heo
@ 2006-03-05 16:09 ` Jeff Garzik
2006-03-05 16:23 ` Tejun Heo
0 siblings, 1 reply; 8+ messages in thread
From: Jeff Garzik @ 2006-03-05 16:09 UTC (permalink / raw)
To: Tejun Heo; +Cc: albertcc, linux-ide
Tejun Heo wrote:
> Implement port_task. LLDD's can schedule a function to be executed
> with context after specified delay. libata core takes care of
> synchronization against EH. This is generalized form of pio_task and
> packet_task which are tied to PIO hsm implementation.
>
> Signed-off-by: Tejun Heo <htejun@gmail.com>
>
> ---
>
> drivers/scsi/libata-core.c | 77 ++++++++++++++++++++++++++++++++++++++++++++
> drivers/scsi/libata-scsi.c | 2 +
> drivers/scsi/libata.h | 1 +
> include/linux/libata.h | 4 ++
> 4 files changed, 84 insertions(+), 0 deletions(-)
>
> 4d83950873856672ed469f25c6421de1eb98ba97
> diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
> index b710fc4..3575d68 100644
> --- a/drivers/scsi/libata-core.c
> +++ b/drivers/scsi/libata-core.c
> @@ -721,6 +721,81 @@ static unsigned int ata_pio_modes(const
> timing API will get this right anyway */
> }
>
> +/**
> + * ata_port_queue_task - Queue port_task
> + * @ap: The ata_port to queue port_task for
> + *
> + * Schedule @fn(@data) for execution after @delay jiffies using
> + * port_task. There is one port_task per port and it's the
> + * user(low level driver)'s responsibility to make sure that only
> + * one task is active at any given time.
> + *
> + * libata core layer takes care of synchronization between
> + * port_task and EH. ata_port_queue_task() may be ignored for EH
> + * synchronization.
> + *
> + * LOCKING:
> + * Inherited from caller.
> + */
> +void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data,
> + unsigned long delay)
> +{
> + int rc;
> +
> + if (ap->flags & ATA_FLAG_FLUSH_PIO_TASK)
> + return;
> +
> + PREPARE_WORK(&ap->port_task, fn, data);
> +
> + if (!delay)
> + rc = queue_work(ata_wq, &ap->port_task);
> + else
> + rc = queue_delayed_work(ata_wq, &ap->port_task, delay);
Two worries here, though not quite a NAK:
1) This is abuse of the PREPARE_WORK(), which is usually not used
because INIT_WORK() took care of the initialization. However, it should
be OK if...
2) This will fall apart if anything tries to queue a task while a
previous task is still pending. Are you certain a double-queue never
ever happens?
Jeff
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/4] libata: implement port_task
2006-03-05 16:09 ` Jeff Garzik
@ 2006-03-05 16:23 ` Tejun Heo
0 siblings, 0 replies; 8+ messages in thread
From: Tejun Heo @ 2006-03-05 16:23 UTC (permalink / raw)
To: Jeff Garzik; +Cc: albertcc, linux-ide
On Sun, Mar 05, 2006 at 11:09:08AM -0500, Jeff Garzik wrote:
> >+/**
> >+ * ata_port_queue_task - Queue port_task
> >+ * @ap: The ata_port to queue port_task for
> >+ *
> >+ * Schedule @fn(@data) for execution after @delay jiffies using
> >+ * port_task. There is one port_task per port and it's the
> >+ * user(low level driver)'s responsibility to make sure that only
> >+ * one task is active at any given time.
> >+ *
> >+ * libata core layer takes care of synchronization between
> >+ * port_task and EH. ata_port_queue_task() may be ignored for EH
> >+ * synchronization.
> >+ *
> >+ * LOCKING:
> >+ * Inherited from caller.
> >+ */
> >+void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void
> >*data,
> >+ unsigned long delay)
> >+{
> >+ int rc;
> >+
> >+ if (ap->flags & ATA_FLAG_FLUSH_PIO_TASK)
> >+ return;
> >+
> >+ PREPARE_WORK(&ap->port_task, fn, data);
> >+
> >+ if (!delay)
> >+ rc = queue_work(ata_wq, &ap->port_task);
> >+ else
> >+ rc = queue_delayed_work(ata_wq, &ap->port_task, delay);
>
> Two worries here, though not quite a NAK:
>
> 1) This is abuse of the PREPARE_WORK(), which is usually not used
> because INIT_WORK() took care of the initialization. However, it should
> be OK if...
I first used separate atomic flag and INIT_WORK() for this but seemed
like an overkill as task->pending does mostly the same thing.
> 2) This will fall apart if anything tries to queue a task while a
> previous task is still pending. Are you certain a double-queue never
> ever happens?
The current code never does and neither does irq-pio branch (irq-pio
actually uses only one task, so...). Also, if any such event occurs,
WARN_ON(rc == 0) should almost always trigger and whine about it.
We can also choose to generalize it further such that there can be
more than one libata-managed tasks but there's no need yet.
--
tejun
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/4] libata: convert pio_task and packet_task to port_task
2006-03-05 6:29 ` [PATCH 2/4] libata: convert pio_task and packet_task to port_task Tejun Heo
@ 2006-03-11 23:43 ` Jeff Garzik
0 siblings, 0 replies; 8+ messages in thread
From: Jeff Garzik @ 2006-03-11 23:43 UTC (permalink / raw)
To: Tejun Heo; +Cc: albertcc, linux-ide
Tejun Heo wrote:
> Make pio_task and atapi_packet_task use port_task.
> atapi_packet_task() is moved upward such that it's right after
> ata_pio_task(). This position is more natural and makes adding
> prototype for ata_qc_issue_prot() unnecessary.
>
> Signed-off-by: Tejun Heo <htejun@gmail.com>
Applied 1-4, though in the future, please -do not- include function
shuffling in the same patch as other changes. atapi_packet_task() has
been moved all over the place, over the lifetime of libata, and it just
clutters up cumulative diffs at review time.
Jeff
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2006-03-11 23:43 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-03-05 6:29 [PATCHSET] implement and use port_task Tejun Heo
2006-03-05 6:29 ` [PATCH 3/4] libata: kill unused pio_task and packet_task Tejun Heo
2006-03-05 6:29 ` [PATCH 2/4] libata: convert pio_task and packet_task to port_task Tejun Heo
2006-03-11 23:43 ` Jeff Garzik
2006-03-05 6:29 ` [PATCH 4/4] libata: rename ATA_FLAG_FLUSH_PIO_TASK to ATA_FLAG_FLUSH_PORT_TASK Tejun Heo
2006-03-05 6:29 ` [PATCH 1/4] libata: implement port_task Tejun Heo
2006-03-05 16:09 ` Jeff Garzik
2006-03-05 16:23 ` Tejun Heo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).