linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] libata: separate out ata_ncq_enabled()
@ 2007-02-20 14:20 Tejun Heo
  2007-02-20 14:27 ` [PATCH 2/3] libata: fix ata_scmd_need_defer() Tejun Heo
  2007-02-20 16:02 ` [PATCH 1/3] libata: separate out ata_ncq_enabled() Jeff Garzik
  0 siblings, 2 replies; 4+ messages in thread
From: Tejun Heo @ 2007-02-20 14:20 UTC (permalink / raw)
  To: Jeff Garzik, linux-ide; +Cc: haebler, lkml

Separate out ata_ncq_enabled().

Signed-off-by: Tejun Heo <htejun@gmail.com>
---
 drivers/ata/libata-core.c |    4 +---
 include/linux/libata.h    |   15 +++++++++++++++
 2 files changed, 16 insertions(+), 3 deletions(-)

Index: work/drivers/ata/libata-core.c
===================================================================
--- work.orig/drivers/ata/libata-core.c
+++ work/drivers/ata/libata-core.c
@@ -311,9 +311,7 @@ int ata_build_rw_tf(struct ata_taskfile 
 	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
 	tf->flags |= tf_flags;
 
-	if ((dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ_OFF |
-			   ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ &&
-	    likely(tag != ATA_TAG_INTERNAL)) {
+	if (ata_ncq_enabled(dev) && likely(tag != ATA_TAG_INTERNAL)) {
 		/* yay, NCQ */
 		if (!lba_48_ok(block, n_block))
 			return -ERANGE;
Index: work/include/linux/libata.h
===================================================================
--- work.orig/include/linux/libata.h
+++ work/include/linux/libata.h
@@ -1026,6 +1026,21 @@ static inline u8 ata_chk_status(struct a
 	return ap->ops->check_status(ap);
 }
 
+/**
+ *	ata_ncq_enabled - Test whether NCQ is enabled
+ *	@dev: ATA device to test for
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host lock)
+ *
+ *	RETURNS:
+ *	1 if NCQ is enabled for @dev, 0 otherwise.
+ */
+static inline int ata_ncq_enabled(struct ata_device *dev)
+{
+	return (dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ_OFF |
+			      ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ;
+}
 
 /**
  *	ata_pause - Flush writes and pause 400 nanoseconds.

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

* [PATCH 2/3] libata: fix ata_scmd_need_defer()
  2007-02-20 14:20 [PATCH 1/3] libata: separate out ata_ncq_enabled() Tejun Heo
@ 2007-02-20 14:27 ` Tejun Heo
  2007-02-20 14:31   ` [PATCH 3/3] libata: fix ata_scsi_change_queue_depth() Tejun Heo
  2007-02-20 16:02 ` [PATCH 1/3] libata: separate out ata_ncq_enabled() Jeff Garzik
  1 sibling, 1 reply; 4+ messages in thread
From: Tejun Heo @ 2007-02-20 14:27 UTC (permalink / raw)
  To: Jeff Garzik, linux-ide; +Cc: haebler, lkml

Fix ata_scmd_need_defer() such that...

* whether NCQ is used or not is exactly determined using the same
  criteria as the issue path.

* defer-check is performed in all cases.

This fixes race condition where turning off NCQ on the fly causes
non-NCQ commands sneak into NCQ phase.

Signed-off-by: Tejun Heo <htejun@gmail.com>
---
 drivers/ata/libata-scsi.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

Index: work/drivers/ata/libata-scsi.c
===================================================================
--- work.orig/drivers/ata/libata-scsi.c
+++ work/drivers/ata/libata-scsi.c
@@ -1495,11 +1495,9 @@ static void ata_scsi_qc_complete(struct 
 static int ata_scmd_need_defer(struct ata_device *dev, int is_io)
 {
 	struct ata_port *ap = dev->ap;
+	int is_ncq = is_io && ata_ncq_enabled(dev);
 
-	if (!(dev->flags & ATA_DFLAG_NCQ))
-		return 0;
-
-	if (is_io) {
+	if (is_ncq) {
 		if (!ata_tag_valid(ap->active_tag))
 			return 0;
 	} else {

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

* [PATCH 3/3] libata: fix ata_scsi_change_queue_depth()
  2007-02-20 14:27 ` [PATCH 2/3] libata: fix ata_scmd_need_defer() Tejun Heo
@ 2007-02-20 14:31   ` Tejun Heo
  0 siblings, 0 replies; 4+ messages in thread
From: Tejun Heo @ 2007-02-20 14:31 UTC (permalink / raw)
  To: Jeff Garzik, linux-ide; +Cc: haebler, lkml

Fix ata_scsi_change_queue_depth() such that...

* NCQ on/off is exactly determined using the same logic as the issue path.

* queue depth is adjusted to 1 if NCQ is not enabled.

* -EINVAL is returned if requested action is ignored due to limitations.

This fixes the bug which allows queue depth to be increased on
blacklisted NCQ hosts/devices.

Signed-off-by: Tejun Heo <htejun@gmail.com>
---
 drivers/ata/libata-scsi.c |   27 +++++++++++++++------------
 1 file changed, 15 insertions(+), 12 deletions(-)

Index: work/drivers/ata/libata-scsi.c
===================================================================
--- work.orig/drivers/ata/libata-scsi.c
+++ work/drivers/ata/libata-scsi.c
@@ -986,29 +986,32 @@ int ata_scsi_change_queue_depth(struct s
 	struct ata_port *ap = ata_shost_to_port(sdev->host);
 	struct ata_device *dev;
 	unsigned long flags;
-	int max_depth;
 
-	if (queue_depth < 1)
+	if (queue_depth < 1 || queue_depth == sdev->queue_depth)
 		return sdev->queue_depth;
 
 	dev = ata_scsi_find_dev(ap, sdev);
 	if (!dev || !ata_dev_enabled(dev))
 		return sdev->queue_depth;
 
-	max_depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
-	max_depth = min(ATA_MAX_QUEUE - 1, max_depth);
-	if (queue_depth > max_depth)
-		queue_depth = max_depth;
-
-	scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, queue_depth);
-
+	/* NCQ enabled? */
 	spin_lock_irqsave(ap->lock, flags);
-	if (queue_depth > 1)
-		dev->flags &= ~ATA_DFLAG_NCQ_OFF;
-	else
+	dev->flags &= ~ATA_DFLAG_NCQ_OFF;
+	if (queue_depth == 1 || !ata_ncq_enabled(dev)) {
 		dev->flags |= ATA_DFLAG_NCQ_OFF;
+		queue_depth = 1;
+	}
 	spin_unlock_irqrestore(ap->lock, flags);
 
+	/* limit and apply queue depth */
+	queue_depth = min(queue_depth, sdev->host->can_queue);
+	queue_depth = min(queue_depth, ata_id_queue_depth(dev->id));
+	queue_depth = min(queue_depth, ATA_MAX_QUEUE - 1);
+
+	if (sdev->queue_depth == queue_depth)
+		return -EINVAL;
+
+	scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, queue_depth);
 	return queue_depth;
 }
 

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

* Re: [PATCH 1/3] libata: separate out ata_ncq_enabled()
  2007-02-20 14:20 [PATCH 1/3] libata: separate out ata_ncq_enabled() Tejun Heo
  2007-02-20 14:27 ` [PATCH 2/3] libata: fix ata_scmd_need_defer() Tejun Heo
@ 2007-02-20 16:02 ` Jeff Garzik
  1 sibling, 0 replies; 4+ messages in thread
From: Jeff Garzik @ 2007-02-20 16:02 UTC (permalink / raw)
  To: Tejun Heo; +Cc: linux-ide, haebler, lkml

Tejun Heo wrote:
> Separate out ata_ncq_enabled().
> 
> Signed-off-by: Tejun Heo <htejun@gmail.com>
> ---
>  drivers/ata/libata-core.c |    4 +---
>  include/linux/libata.h    |   15 +++++++++++++++
>  2 files changed, 16 insertions(+), 3 deletions(-)

applied 1-3



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

end of thread, other threads:[~2007-02-20 16:02 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-02-20 14:20 [PATCH 1/3] libata: separate out ata_ncq_enabled() Tejun Heo
2007-02-20 14:27 ` [PATCH 2/3] libata: fix ata_scmd_need_defer() Tejun Heo
2007-02-20 14:31   ` [PATCH 3/3] libata: fix ata_scsi_change_queue_depth() Tejun Heo
2007-02-20 16:02 ` [PATCH 1/3] libata: separate out ata_ncq_enabled() Jeff Garzik

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).