瀏覽代碼

libata: add qc_fill_rtf port operation

On command completion, ata_qc_complete() directly called ops->tf_read
to fill qc->result_tf.  This patch adds ops->qc_fill_rtf to replace
hardcoded ops->tf_read usage.

ata_sff_qc_fill_rtf() which uses ops->tf_read to fill result_tf is
implemented and set in ata_base_port_ops and other ops tables which
don't inherit from ata_base_port_ops, so this patch doesn't introduce
any behavior change.

ops->qc_fill_rtf() is similar to ops->sff_tf_read() but can only be
called when a command finishes.  As some non-SFF controllers don't
have TF registers defined unless they're associated with in-flight
commands, this limited operation makes life easier for those drivers
and help lifting SFF assumptions from libata core layer.

Signed-off-by: Tejun Heo <htejun@gmail.com>
Tejun Heo 17 年之前
父節點
當前提交
22183bf569
共有 6 個文件被更改,包括 27 次插入1 次删除
  1. 2 1
      drivers/ata/libata-core.c
  2. 20 0
      drivers/ata/libata-sff.c
  3. 1 0
      drivers/ata/sata_sx4.c
  4. 1 0
      drivers/scsi/ipr.c
  5. 1 0
      drivers/scsi/libsas/sas_ata.c
  6. 2 0
      include/linux/libata.h

+ 2 - 1
drivers/ata/libata-core.c

@@ -74,6 +74,7 @@ const unsigned long sata_deb_timing_hotplug[]		= {  25,  500, 2000 };
 const unsigned long sata_deb_timing_long[]		= { 100, 2000, 5000 };
 const unsigned long sata_deb_timing_long[]		= { 100, 2000, 5000 };
 
 
 const struct ata_port_operations ata_base_port_ops = {
 const struct ata_port_operations ata_base_port_ops = {
+	.qc_fill_rtf		= ata_sff_qc_fill_rtf,
 	.prereset		= ata_std_prereset,
 	.prereset		= ata_std_prereset,
 	.postreset		= ata_std_postreset,
 	.postreset		= ata_std_postreset,
 	.error_handler		= ata_std_error_handler,
 	.error_handler		= ata_std_error_handler,
@@ -4562,7 +4563,7 @@ static void fill_result_tf(struct ata_queued_cmd *qc)
 	struct ata_port *ap = qc->ap;
 	struct ata_port *ap = qc->ap;
 
 
 	qc->result_tf.flags = qc->tf.flags;
 	qc->result_tf.flags = qc->tf.flags;
-	ap->ops->sff_tf_read(ap, &qc->result_tf);
+	ap->ops->qc_fill_rtf(qc);
 }
 }
 
 
 static void ata_verify_xfer(struct ata_queued_cmd *qc)
 static void ata_verify_xfer(struct ata_queued_cmd *qc)

+ 20 - 0
drivers/ata/libata-sff.c

@@ -1407,6 +1407,25 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
 	return 0;
 	return 0;
 }
 }
 
 
+/**
+ *	ata_sff_qc_fill_rtf - fill result TF using ->sff_tf_read
+ *	@qc: qc to fill result TF for
+ *
+ *	@qc is finished and result TF needs to be filled.  Fill it
+ *	using ->sff_tf_read.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host lock)
+ *
+ *	RETURNS:
+ *	true indicating that result TF is successfully filled.
+ */
+bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc)
+{
+	qc->ap->ops->sff_tf_read(qc->ap, &qc->result_tf);
+	return true;
+}
+
 /**
 /**
  *	ata_sff_host_intr - Handle host interrupt for given (port, task)
  *	ata_sff_host_intr - Handle host interrupt for given (port, task)
  *	@ap: Port on which interrupt arrived (possibly...)
  *	@ap: Port on which interrupt arrived (possibly...)
@@ -2724,6 +2743,7 @@ EXPORT_SYMBOL_GPL(ata_sff_irq_on);
 EXPORT_SYMBOL_GPL(ata_sff_irq_clear);
 EXPORT_SYMBOL_GPL(ata_sff_irq_clear);
 EXPORT_SYMBOL_GPL(ata_sff_hsm_move);
 EXPORT_SYMBOL_GPL(ata_sff_hsm_move);
 EXPORT_SYMBOL_GPL(ata_sff_qc_issue);
 EXPORT_SYMBOL_GPL(ata_sff_qc_issue);
+EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf);
 EXPORT_SYMBOL_GPL(ata_sff_host_intr);
 EXPORT_SYMBOL_GPL(ata_sff_host_intr);
 EXPORT_SYMBOL_GPL(ata_sff_interrupt);
 EXPORT_SYMBOL_GPL(ata_sff_interrupt);
 EXPORT_SYMBOL_GPL(ata_sff_freeze);
 EXPORT_SYMBOL_GPL(ata_sff_freeze);

+ 1 - 0
drivers/ata/sata_sx4.c

@@ -251,6 +251,7 @@ static struct ata_port_operations pdc_20621_ops = {
 	.phy_reset		= pdc_20621_phy_reset,
 	.phy_reset		= pdc_20621_phy_reset,
 	.qc_prep		= pdc20621_qc_prep,
 	.qc_prep		= pdc20621_qc_prep,
 	.qc_issue		= pdc20621_qc_issue,
 	.qc_issue		= pdc20621_qc_issue,
+	.qc_fill_rtf		= ata_sff_qc_fill_rtf,
 	.sff_data_xfer		= ata_sff_data_xfer,
 	.sff_data_xfer		= ata_sff_data_xfer,
 	.eng_timeout		= pdc_eng_timeout,
 	.eng_timeout		= pdc_eng_timeout,
 	.sff_irq_clear		= pdc20621_irq_clear,
 	.sff_irq_clear		= pdc20621_irq_clear,

+ 1 - 0
drivers/scsi/ipr.c

@@ -5280,6 +5280,7 @@ static struct ata_port_operations ipr_sata_ops = {
 	.sff_tf_read = ipr_tf_read,
 	.sff_tf_read = ipr_tf_read,
 	.qc_prep = ata_noop_qc_prep,
 	.qc_prep = ata_noop_qc_prep,
 	.qc_issue = ipr_qc_issue,
 	.qc_issue = ipr_qc_issue,
+	.qc_fill_rtf = ata_sff_qc_fill_rtf,
 	.port_start = ata_sas_port_start,
 	.port_start = ata_sas_port_start,
 	.port_stop = ata_sas_port_stop
 	.port_stop = ata_sas_port_stop
 };
 };

+ 1 - 0
drivers/scsi/libsas/sas_ata.c

@@ -356,6 +356,7 @@ static struct ata_port_operations sas_sata_ops = {
 	.sff_tf_read		= sas_ata_tf_read,
 	.sff_tf_read		= sas_ata_tf_read,
 	.qc_prep		= ata_noop_qc_prep,
 	.qc_prep		= ata_noop_qc_prep,
 	.qc_issue		= sas_ata_qc_issue,
 	.qc_issue		= sas_ata_qc_issue,
+	.qc_fill_rtf		= ata_sff_qc_fill_rtf,
 	.port_start		= ata_sas_port_start,
 	.port_start		= ata_sas_port_start,
 	.port_stop		= ata_sas_port_stop,
 	.port_stop		= ata_sas_port_stop,
 	.scr_read		= sas_ata_scr_read,
 	.scr_read		= sas_ata_scr_read,

+ 2 - 0
include/linux/libata.h

@@ -715,6 +715,7 @@ struct ata_port_operations {
 	int  (*check_atapi_dma)(struct ata_queued_cmd *qc);
 	int  (*check_atapi_dma)(struct ata_queued_cmd *qc);
 	void (*qc_prep)(struct ata_queued_cmd *qc);
 	void (*qc_prep)(struct ata_queued_cmd *qc);
 	unsigned int (*qc_issue)(struct ata_queued_cmd *qc);
 	unsigned int (*qc_issue)(struct ata_queued_cmd *qc);
+	bool (*qc_fill_rtf)(struct ata_queued_cmd *qc);
 
 
 	/*
 	/*
 	 * Configuration and exception handling
 	 * Configuration and exception handling
@@ -1385,6 +1386,7 @@ 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,
 extern int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
 			    u8 status, int in_wq);
 			    u8 status, int in_wq);
 extern unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc);
 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_host_intr(struct ata_port *ap,
 extern unsigned int ata_sff_host_intr(struct ata_port *ap,
 				      struct ata_queued_cmd *qc);
 				      struct ata_queued_cmd *qc);
 extern irqreturn_t ata_sff_interrupt(int irq, void *dev_instance);
 extern irqreturn_t ata_sff_interrupt(int irq, void *dev_instance);