All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH/RFC 0/4] libata: more irq driven pio follow-up patches
@ 2005-11-01 11:12 Albert Lee
  2005-11-01 11:19 ` [PATCH/RFC 1/4] irq-pio: misc fixes Albert Lee
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Albert Lee @ 2005-11-01 11:12 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Doug Maxey, Bartlomiej Zolnierkiewicz, Mark Lord, Linux IDE

Dear all,

More irq driven PIO follow-up patches (revised).

Changes:
  1. merge the ata_dataout_task workqueue with the ata_pio_task workqueue
  2. add read/write multiple support

patch 1/4: misc fixes
   - ata_pio_block(): add ata_altstatus(ap) to prevent reading device status before it is valid
   - remove the unnecessary HSM_ST_IDLE state from ata_pio_task()
   - raise BUG() when unknown state is found in ata_pio_task()

patch 2/4: merge the ata_dataout_task workqueue with the ata_pio_task workqueue
   - remove ap->dataout_task from struct ata_port
   - let ata_pio_task() handle the HSM_ST_FIRST state.
   - rename ata_dataout_task() to ata_pio_first_block()

patch 3/4: eliminate unnecessary queuing in ata_pio_first_block()
   - change the return value of ata_pio_complete()
   - add return value to ata_pio_first_block()
   - rename the variable "qc_completed" to "has_next" in ata_pio_task()
   - use "has_next" to eliminate unnecessary queuing in ata_pio_first_block()

patch 4/4: add read/write multiple support
   - add is_multi_taskfile() to ata.h
   - initialize ata_device->multi_count with device identify data
   - use ata_pio_sectors() to support r/w multiple commands

Patch against the libata-dev irq-pio branch (cd8200e6d4f9f05e6ea48f7c000be890337396ac).

For your review and advice, thanks.

Albert



^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH/RFC 1/4] irq-pio: misc fixes
  2005-11-01 11:12 [PATCH/RFC 0/4] libata: more irq driven pio follow-up patches Albert Lee
@ 2005-11-01 11:19 ` Albert Lee
  2005-11-09  6:22   ` Jeff Garzik
  2005-11-01 11:24 ` [PATCH/RFC 2/4] irq-pio: merge the ata_dataout_task workqueue with ata_pio_task workqueue Albert Lee
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 6+ messages in thread
From: Albert Lee @ 2005-11-01 11:19 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Doug Maxey, Bartlomiej Zolnierkiewicz, Mark Lord, Linux IDE

Patch 1/4: misc fixes

Changes:
   - ata_pio_block(): add ata_altstatus(ap) to prevent reading device status before it is valid
   - remove the unnecessary HSM_ST_IDLE state from ata_pio_task()
   - raise BUG() when unknown state is found in ata_pio_task()

For your review, thanks.

Albert
Signed-off-by: Albert Lee <albertcc@tw.ibm.com> 

============

--- linux-ori/drivers/scsi/libata-core.c	2005-11-01 17:22:41.000000000 +0800
+++ id1/drivers/scsi/libata-core.c	2005-11-01 18:45:16.000000000 +0800
@@ -3224,6 +3224,8 @@ static void ata_pio_block(struct ata_por
 
 		ata_pio_sector(qc);
 	}
+
+	ata_altstatus(ap); /* flush */
 }
 
 static void ata_pio_error(struct ata_port *ap)
@@ -3251,9 +3253,6 @@ fsm_start:
 	qc_completed = 0;
 
 	switch (ap->hsm_task_state) {
-	case HSM_ST_IDLE:
-		return;
-
 	case HSM_ST:
 		ata_pio_block(ap);
 		break;
@@ -3271,6 +3270,10 @@ fsm_start:
 	case HSM_ST_ERR:
 		ata_pio_error(ap);
 		return;
+
+	default:
+		BUG();
+		return;
 	}
 
 	if (timeout)



^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH/RFC 2/4] irq-pio: merge the ata_dataout_task workqueue with ata_pio_task workqueue
  2005-11-01 11:12 [PATCH/RFC 0/4] libata: more irq driven pio follow-up patches Albert Lee
  2005-11-01 11:19 ` [PATCH/RFC 1/4] irq-pio: misc fixes Albert Lee
@ 2005-11-01 11:24 ` Albert Lee
  2005-11-01 11:30 ` [PATCH/RFC 3/4] irq-pio: eliminate unnecessary queuing in ata_pio_first_block() Albert Lee
  2005-11-01 11:33 ` [PATCH/RFC 4/4] irq-pio: add read/write multiple support Albert Lee
  3 siblings, 0 replies; 6+ messages in thread
From: Albert Lee @ 2005-11-01 11:24 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Doug Maxey, Bartlomiej Zolnierkiewicz, Mark Lord, Linux IDE

Patch 2/4:
  merge the ata_dataout_task workqueue with ata_pio_task workqueue

Changes:
   - remove ap->dataout_task from struct ata_port
   - let ata_pio_task() handle the HSM_ST_FIRST state.
   - rename ata_dataout_task() to ata_pio_first_block()
   - replace the ata_dataout_task workqueue with ata_pio_task workqueue

For your review, thanks.

Albert
Signed-off-by: Albert Lee <albertcc@tw.ibm.com>

========

--- id1/include/linux/libata.h	2005-11-01 17:39:14.000000000 +0800
+++ id2/include/linux/libata.h	2005-11-01 17:57:00.000000000 +0800
@@ -334,8 +334,6 @@ struct ata_port {
 	struct ata_host_stats	stats;
 	struct ata_host_set	*host_set;
 
-	struct work_struct	dataout_task;
-
 	struct work_struct	pio_task;
 	unsigned int		hsm_task_state;
 	unsigned long		pio_task_timeout;
--- id1/drivers/scsi/libata-core.c	2005-11-01 18:45:16.000000000 +0800
+++ id2/drivers/scsi/libata-core.c	2005-11-01 18:45:35.000000000 +0800
@@ -2963,8 +2963,8 @@ static void atapi_send_cdb(struct ata_po
 }
 
 /**
- *	ata_dataout_task - Write first data block to hardware
- *	@_data: Port to which ATA/ATAPI device is attached.
+ *	ata_pio_first_block - Write first data block to hardware
+ *	@ap: Port to which ATA/ATAPI device is attached.
  *
  *	When device has indicated its readiness to accept
  *	the data, this function sends out the CDB or 
@@ -2977,9 +2977,8 @@ static void atapi_send_cdb(struct ata_po
  *	Kernel thread context (may sleep)
  */
 
-static void ata_dataout_task(void *_data)
+static void ata_pio_first_block(struct ata_port *ap)
 {
-	struct ata_port *ap = _data;
 	struct ata_queued_cmd *qc;
 	u8 status;
 	unsigned long flags;
@@ -3253,6 +3252,10 @@ fsm_start:
 	qc_completed = 0;
 
 	switch (ap->hsm_task_state) {
+	case HSM_ST_FIRST:
+		ata_pio_first_block(ap);
+		return;
+
 	case HSM_ST:
 		ata_pio_block(ap);
 		break;
@@ -3703,10 +3706,10 @@ int ata_qc_issue_prot(struct ata_queued_
 		if (qc->tf.flags & ATA_TFLAG_WRITE) {
 			/* PIO data out protocol */
 			ap->hsm_task_state = HSM_ST_FIRST;
-			queue_work(ata_wq, &ap->dataout_task);
+			queue_work(ata_wq, &ap->pio_task);
 
 			/* always send first data block using
-			 * the ata_dataout_task() codepath.
+			 * the ata_pio_task() codepath.
 			 */
 		} else {
 			/* PIO data in protocol */
@@ -3733,7 +3736,7 @@ int ata_qc_issue_prot(struct ata_queued_
 		/* send cdb by polling if no cdb interrupt */
 		if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) ||
 		    (qc->tf.flags & ATA_TFLAG_POLLING))
-			queue_work(ata_wq, &ap->dataout_task);
+			queue_work(ata_wq, &ap->pio_task);
 		break;
 
 	case ATA_PROT_ATAPI_DMA:
@@ -3745,7 +3748,7 @@ int ata_qc_issue_prot(struct ata_queued_
 
 		/* send cdb by polling if no cdb interrupt */
 		if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
-			queue_work(ata_wq, &ap->dataout_task);
+			queue_work(ata_wq, &ap->pio_task);
 		break;
 
 	default:
@@ -4325,7 +4328,6 @@ static void ata_host_init(struct ata_por
 	ap->active_tag = ATA_TAG_POISON;
 	ap->last_ctl = 0xFF;
 
-	INIT_WORK(&ap->dataout_task, ata_dataout_task, ap);
 	INIT_WORK(&ap->pio_task, ata_pio_task, ap);
 
 	for (i = 0; i < ATA_MAX_DEVICES; i++)



^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH/RFC 3/4] irq-pio: eliminate unnecessary queuing in ata_pio_first_block()
  2005-11-01 11:12 [PATCH/RFC 0/4] libata: more irq driven pio follow-up patches Albert Lee
  2005-11-01 11:19 ` [PATCH/RFC 1/4] irq-pio: misc fixes Albert Lee
  2005-11-01 11:24 ` [PATCH/RFC 2/4] irq-pio: merge the ata_dataout_task workqueue with ata_pio_task workqueue Albert Lee
@ 2005-11-01 11:30 ` Albert Lee
  2005-11-01 11:33 ` [PATCH/RFC 4/4] irq-pio: add read/write multiple support Albert Lee
  3 siblings, 0 replies; 6+ messages in thread
From: Albert Lee @ 2005-11-01 11:30 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Doug Maxey, Bartlomiej Zolnierkiewicz, Mark Lord, Linux IDE

patch 3/4: 
  eliminate unnecessary queuing in ata_pio_first_block()

Changes:
   - change the return value of ata_pio_complete() 0 <-> 1
   - add return value for ata_pio_first_block()
   - rename variable "qc_completed" to "has_next" in ata_pio_task()
   - use has_next to eliminate unnecessary queuing in ata_pio_first_block()

For your review, thanks.

Albert
Signed-off-by: Albert Lee <albertcc@tw.ibm.com>

==========

--- id2/drivers/scsi/libata-core.c	2005-11-01 18:45:35.000000000 +0800
+++ id3/drivers/scsi/libata-core.c	2005-11-01 18:45:50.000000000 +0800
@@ -2697,7 +2697,8 @@ static unsigned long ata_pio_poll(struct
  *	None.  (executing in kernel thread context)
  *
  *	RETURNS:
- *	Non-zero if qc completed, zero otherwise.
+ *	Zero if qc completed.
+ *	Non-zero if has next.
  */
 
 static int ata_pio_complete (struct ata_port *ap)
@@ -2719,14 +2720,14 @@ static int ata_pio_complete (struct ata_
 		if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
 			ap->hsm_task_state = HSM_ST_LAST_POLL;
 			ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
-			return 0;
+			return 1;
 		}
 	}
 
 	drv_stat = ata_wait_idle(ap);
 	if (!ata_ok(drv_stat)) {
 		ap->hsm_task_state = HSM_ST_ERR;
-		return 0;
+		return 1;
 	}
 
 	qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -2738,7 +2739,7 @@ static int ata_pio_complete (struct ata_
 
 	/* another command may start at this point */
 
-	return 1;
+	return 0;
 }
 
 
@@ -2975,27 +2976,42 @@ static void atapi_send_cdb(struct ata_po
  *
  *	LOCKING:
  *	Kernel thread context (may sleep)
+ *
+ *	RETURNS:
+ *	Zero if irq handler takes over
+ *	Non-zero if has next (polling).
  */
 
-static void ata_pio_first_block(struct ata_port *ap)
+static int ata_pio_first_block(struct ata_port *ap)
 {
 	struct ata_queued_cmd *qc;
 	u8 status;
 	unsigned long flags;
+	int has_next;
 
 	qc = ata_qc_from_tag(ap, ap->active_tag);
 	assert(qc != NULL);
 	assert(qc->flags & ATA_QCFLAG_ACTIVE);
 
+	/* if polling, we will stay in the work queue after sending the data.
+	 * otherwise, interrupt handler takes over after sending the data.
+	 */
+	has_next = (qc->tf.flags & ATA_TFLAG_POLLING);
+
 	/* sleep-wait for BSY to clear */
 	DPRINTK("busy wait\n");
-	if (ata_busy_sleep(ap, ATA_TMOUT_DATAOUT_QUICK, ATA_TMOUT_DATAOUT))
+	if (ata_busy_sleep(ap, ATA_TMOUT_DATAOUT_QUICK, ATA_TMOUT_DATAOUT)) {
+		ap->hsm_task_state = HSM_ST_TMOUT;
 		goto err_out;
+	}
 
 	/* make sure DRQ is set */
 	status = ata_chk_status(ap);
-	if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)
+	if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) {
+		/* device status error */
+		ap->hsm_task_state = HSM_ST_ERR;
 		goto err_out;
+	}
 
 	/* Send the CDB (atapi) or the first data block (ata pio out).
 	 * During the state transition, interrupt handler shouldn't
@@ -3019,18 +3035,15 @@ static void ata_pio_first_block(struct a
 		/* send CDB */
 		atapi_send_cdb(ap, qc);
 
+	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
 	/* if polling, ata_pio_task() handles the rest.
 	 * otherwise, interrupt handler takes over from here.
 	 */
-	if (qc->tf.flags & ATA_TFLAG_POLLING)
-		queue_work(ata_wq, &ap->pio_task);
-
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
-	return;
+	return has_next;
 
 err_out:
-	ata_pio_error(ap);
+	return 1; /* has next */
 }
 
 /**
@@ -3245,23 +3258,23 @@ static void ata_pio_task(void *_data)
 {
 	struct ata_port *ap = _data;
 	unsigned long timeout;
-	int qc_completed;
+	int has_next;
 
 fsm_start:
 	timeout = 0;
-	qc_completed = 0;
+	has_next = 1;
 
 	switch (ap->hsm_task_state) {
 	case HSM_ST_FIRST:
-		ata_pio_first_block(ap);
-		return;
+		has_next = ata_pio_first_block(ap);
+		break;
 
 	case HSM_ST:
 		ata_pio_block(ap);
 		break;
 
 	case HSM_ST_LAST:
-		qc_completed = ata_pio_complete(ap);
+		has_next = ata_pio_complete(ap);
 		break;
 
 	case HSM_ST_POLL:
@@ -3281,7 +3294,7 @@ fsm_start:
 
 	if (timeout)
 		queue_delayed_work(ata_wq, &ap->pio_task, timeout);
-	else if (!qc_completed)
+	else if (has_next)
 		goto fsm_start;
 }
 



^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH/RFC 4/4] irq-pio: add read/write multiple support
  2005-11-01 11:12 [PATCH/RFC 0/4] libata: more irq driven pio follow-up patches Albert Lee
                   ` (2 preceding siblings ...)
  2005-11-01 11:30 ` [PATCH/RFC 3/4] irq-pio: eliminate unnecessary queuing in ata_pio_first_block() Albert Lee
@ 2005-11-01 11:33 ` Albert Lee
  3 siblings, 0 replies; 6+ messages in thread
From: Albert Lee @ 2005-11-01 11:33 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Doug Maxey, Bartlomiej Zolnierkiewicz, Mark Lord, Linux IDE

patch 4/4: 
  add read/write multiple support

Changes:
   - add is_multi_taskfile() to ata.h
   - initialize ata_device->multi_count with device identify data
   - use ata_pio_sectors() to support r/w multiple commands

For your review, thanks.

Albert
Signed-off-by: Albert Lee <albertcc@tw.ibm.com>

========

--- linux-ori/include/linux/ata.h	2005-11-01 17:22:45.000000000 +0800
+++ id4/include/linux/ata.h	2005-11-01 18:27:08.000000000 +0800
@@ -293,6 +293,14 @@ static inline int is_atapi_taskfile(cons
 	       (tf->protocol == ATA_PROT_ATAPI_DMA);
 }
 
+static inline int is_multi_taskfile(struct ata_taskfile *tf)
+{
+	return (tf->command == ATA_CMD_READ_MULTI) ||
+	       (tf->command == ATA_CMD_WRITE_MULTI) ||
+	       (tf->command == ATA_CMD_READ_MULTI_EXT) ||
+	       (tf->command == ATA_CMD_WRITE_MULTI_EXT);
+}
+
 static inline int ata_ok(u8 status)
 {
 	return ((status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ATA_ERR))
--- id3/drivers/scsi/libata-core.c	2005-11-01 18:45:50.000000000 +0800
+++ id4/drivers/scsi/libata-core.c	2005-11-01 18:36:08.000000000 +0800
@@ -1261,6 +1261,12 @@ retry:
 
 		}
 
+		if (dev->id[59] & 0x100) {
+			dev->multi_count = dev->id[59] & 0xff;
+			DPRINTK("ata%u: dev %u multi count %u\n",
+				ap->id, device, dev->multi_count);
+		}
+
 		ap->host->max_cmd_len = 16;
 	}
 
@@ -2711,7 +2717,7 @@ static int ata_pio_complete (struct ata_
 	 * we enter, BSY will be cleared in a chk-status or two.  If not,
 	 * the drive is probably seeking or something.  Snooze for a couple
 	 * msecs, then chk-status again.  If still busy, fall back to
-	 * HSM_ST_POLL state.
+	 * HSM_ST_LAST_POLL state.
 	 */
 	drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
 	if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
@@ -2928,6 +2934,32 @@ static void ata_pio_sector(struct ata_qu
 }
 
 /**
+ *	ata_pio_sectors - Transfer one or many 512-byte sectors.
+ *	@qc: Command on going
+ *
+ *	Transfer one or many ATA_SECT_SIZE of data from/to the 
+ *	ATA device for the DRQ request.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+
+static void ata_pio_sectors(struct ata_queued_cmd *qc)
+{
+	if (is_multi_taskfile(&qc->tf)) {
+		/* READ/WRITE MULTIPLE */
+		unsigned int nsect;
+
+		assert(qc->dev->multi_count);
+
+		nsect = min(qc->nsect - qc->cursect, qc->dev->multi_count);
+		while (nsect--)
+			ata_pio_sector(qc);
+	} else
+		ata_pio_sector(qc);
+}
+
+/**
  *	atapi_send_cdb - Write CDB bytes to hardware
  *	@ap: Port to which ATAPI device is attached.
  *	@qc: Taskfile currently active
@@ -3025,11 +3057,11 @@ static int ata_pio_first_block(struct at
 		 * send first data block.
 		 */
 
-		/* ata_pio_sector() might change the state to HSM_ST_LAST.
-		 * so, the state is changed here before ata_pio_sector().
+		/* ata_pio_sectors() might change the state to HSM_ST_LAST.
+		 * so, the state is changed here before ata_pio_sectors().
 		 */
 		ap->hsm_task_state = HSM_ST;
-		ata_pio_sector(qc);
+		ata_pio_sectors(qc);
 		ata_altstatus(ap); /* flush */
 	} else
 		/* send CDB */
@@ -3234,7 +3266,7 @@ static void ata_pio_block(struct ata_por
 			return;
 		}
 
-		ata_pio_sector(qc);
+		ata_pio_sectors(qc);
 	}
 
 	ata_altstatus(ap); /* flush */
@@ -4120,7 +4152,7 @@ fsm_start:
 				goto fsm_start;
 			}
 
-			ata_pio_sector(qc);
+			ata_pio_sectors(qc);
 
 			if (ap->hsm_task_state == HSM_ST_LAST &&
 			    (!(qc->tf.flags & ATA_TFLAG_WRITE))) {



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH/RFC 1/4] irq-pio: misc fixes
  2005-11-01 11:19 ` [PATCH/RFC 1/4] irq-pio: misc fixes Albert Lee
@ 2005-11-09  6:22   ` Jeff Garzik
  0 siblings, 0 replies; 6+ messages in thread
From: Jeff Garzik @ 2005-11-09  6:22 UTC (permalink / raw)
  To: Albert Lee; +Cc: Doug Maxey, Bartlomiej Zolnierkiewicz, Mark Lord, Linux IDE

applied 1-4


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2005-11-09  6:22 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-11-01 11:12 [PATCH/RFC 0/4] libata: more irq driven pio follow-up patches Albert Lee
2005-11-01 11:19 ` [PATCH/RFC 1/4] irq-pio: misc fixes Albert Lee
2005-11-09  6:22   ` Jeff Garzik
2005-11-01 11:24 ` [PATCH/RFC 2/4] irq-pio: merge the ata_dataout_task workqueue with ata_pio_task workqueue Albert Lee
2005-11-01 11:30 ` [PATCH/RFC 3/4] irq-pio: eliminate unnecessary queuing in ata_pio_first_block() Albert Lee
2005-11-01 11:33 ` [PATCH/RFC 4/4] irq-pio: add read/write multiple support Albert Lee

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.