Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6a575fa9 authored by Tejun Heo's avatar Tejun Heo Committed by Jeff Garzik
Browse files

[PATCH] sil24: implement proper TF register reading & caching



03_sil24_add-tf-reading.patch

	This patch implements proper TF register reading back and
	caching and bumps up version to 0.22.  This is taken from
	Edward's driver.

Signed-off-by: default avatarTejun Heo <htejun@gmail.com>

 sata_sil24.c |   50 +++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 45 insertions(+), 5 deletions(-)
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent 46b93e7b
Loading
Loading
Loading
Loading
+45 −5
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@
#include <asm/io.h>

#define DRV_NAME	"sata_sil24"
#define DRV_VERSION	"0.21"	/* Silicon Image's preview driver was 0.10 */
#define DRV_VERSION	"0.22"	/* Silicon Image's preview driver was 0.10 */

#define NR_PORTS	4

@@ -216,6 +216,7 @@ struct sil24_cmd_block {
struct sil24_port_priv {
	struct sil24_cmd_block *cmd_block;	/* 32 cmd blocks */
	dma_addr_t cmd_block_dma;		/* DMA base addr for them */
	struct ata_taskfile tf;			/* Cached taskfile registers */
};

/* ap->host_set->private_data */
@@ -322,14 +323,25 @@ static struct ata_port_info sil24_port_info[] = {
	},
};

static inline void sil24_update_tf(struct ata_port *ap)
{
	struct sil24_port_priv *pp = ap->private_data;
	void *port = (void *)ap->ioaddr.cmd_addr;
	struct sil24_prb *prb = port;

	ata_tf_from_fis(prb->fis, &pp->tf);
}

static u8 sil24_check_status(struct ata_port *ap)
{
	return ATA_DRDY;
	struct sil24_port_priv *pp = ap->private_data;
	return pp->tf.command;
}

static u8 sil24_check_err(struct ata_port *ap)
{
	return 0;
	struct sil24_port_priv *pp = ap->private_data;
	return pp->tf.feature;
}

static int sil24_scr_map[] = {
@@ -485,6 +497,7 @@ static void sil24_eng_timeout(struct ata_port *ap)
static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
{
	struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
	struct sil24_port_priv *pp = ap->private_data;
	void *port = (void *)ap->ioaddr.cmd_addr;
	u32 irq_stat, cmd_err, sstatus, serror;

@@ -509,8 +522,22 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
	       "  stat=0x%x irq=0x%x cmd_err=%d sstatus=0x%x serror=0x%x\n",
	       ap->id, ap->port_no, slot_stat, irq_stat, cmd_err, sstatus, serror);

	if (cmd_err == PORT_CERR_DEV || cmd_err == PORT_CERR_SDB) {
		/*
		 * Device is reporting error, tf registers are valid.
		 */
		sil24_update_tf(ap);
	} else {
		/*
		 * Other errors.  libata currently doesn't have any
		 * mechanism to report these errors.  Just turn on
		 * ATA_ERR.
		 */
		pp->tf.command = ATA_ERR;
	}

	if (qc)
		ata_qc_complete(qc, ATA_ERR);
		ata_qc_complete(qc, pp->tf.command);

	sil24_reset_controller(ap);
}
@@ -523,8 +550,19 @@ static inline void sil24_host_intr(struct ata_port *ap)

	slot_stat = readl(port + PORT_SLOT_STAT);
	if (!(slot_stat & HOST_SSTAT_ATTN)) {
		struct sil24_port_priv *pp = ap->private_data;
		/*
		 * !HOST_SSAT_ATTN guarantees successful completion,
		 * so reading back tf registers is unnecessary for
		 * most commands.  TODO: read tf registers for
		 * commands which require these values on successful
		 * completion (EXECUTE DEVICE DIAGNOSTIC, CHECK POWER,
		 * DEVICE RESET and READ PORT MULTIPLIER (any more?).
		 */
		sil24_update_tf(ap);

		if (qc)
			ata_qc_complete(qc, 0);
			ata_qc_complete(qc, pp->tf.command);
	} else
		sil24_error_intr(ap, slot_stat);
}
@@ -579,6 +617,8 @@ static int sil24_port_start(struct ata_port *ap)
		return -ENOMEM;
	memset(pp, 0, sizeof(*pp));

	pp->tf.command = ATA_DRDY;

	cb = dma_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL);
	if (!cb) {
		kfree(pp);