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

Commit 8c1ee54c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev:
  libata: implement and use ATA_QCFLAG_QUIET
  libata: stop being overjealous about non-IO commands
  libata: flush is an IO command
  sata_promise: cleanups
  sata_promise: ASIC PRD table bug workaround, take 2
parents 97855b49 e027bd36
Loading
Loading
Loading
Loading
+14 −6
Original line number Diff line number Diff line
@@ -1800,10 +1800,8 @@ static void ata_eh_link_autopsy(struct ata_link *link)
			qc->err_mask &= ~AC_ERR_OTHER;

		/* SENSE_VALID trumps dev/unknown error and revalidation */
		if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
		if (qc->flags & ATA_QCFLAG_SENSE_VALID)
			qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
			ehc->i.action &= ~ATA_EH_REVALIDATE;
		}

		/* accumulate error info */
		ehc->i.dev = qc->dev;
@@ -1816,7 +1814,8 @@ static void ata_eh_link_autopsy(struct ata_link *link)
	if (ap->pflags & ATA_PFLAG_FROZEN ||
	    all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
		ehc->i.action |= ATA_EH_SOFTRESET;
	else if (all_err_mask)
	else if ((is_io && all_err_mask) ||
		 (!is_io && (all_err_mask & ~AC_ERR_DEV)))
		ehc->i.action |= ATA_EH_REVALIDATE;

	/* if we have offending qcs and the associated failed device */
@@ -1879,7 +1878,9 @@ static void ata_eh_link_report(struct ata_link *link)
	for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
		struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);

		if (!(qc->flags & ATA_QCFLAG_FAILED) || qc->dev->link != link)
		if (!(qc->flags & ATA_QCFLAG_FAILED) || qc->dev->link != link ||
		    ((qc->flags & ATA_QCFLAG_QUIET) &&
		     qc->err_mask == AC_ERR_DEV))
			continue;
		if (qc->flags & ATA_QCFLAG_SENSE_VALID && !qc->err_mask)
			continue;
@@ -2697,8 +2698,15 @@ void ata_eh_finish(struct ata_port *ap)
			/* FIXME: Once EH migration is complete,
			 * generate sense data in this function,
			 * considering both err_mask and tf.
			 *
			 * There's no point in retrying invalid
			 * (detected by libata) and non-IO device
			 * errors (rejected by device).  Finish them
			 * immediately.
			 */
			if (qc->err_mask & AC_ERR_INVALID)
			if ((qc->err_mask & AC_ERR_INVALID) ||
			    (!(qc->flags & ATA_QCFLAG_IO) &&
			     qc->err_mask == AC_ERR_DEV))
				ata_eh_qc_complete(qc);
			else
				ata_eh_qc_retry(qc);
+5 −2
Original line number Diff line number Diff line
@@ -1108,6 +1108,9 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc)
	else
		tf->command = ATA_CMD_FLUSH;

	/* flush is critical for IO integrity, consider it an IO command */
	qc->flags |= ATA_QCFLAG_IO;

	return 0;
}

@@ -2764,8 +2767,8 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
	 */
	qc->nbytes = scsi_bufflen(scmd);

	/* request result TF */
	qc->flags |= ATA_QCFLAG_RESULT_TF;
	/* request result TF and be quiet about device error */
	qc->flags |= ATA_QCFLAG_RESULT_TF | ATA_QCFLAG_QUIET;

	return 0;

+92 −12
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
 *  sata_promise.c - Promise SATA
 *
 *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
 *		    Mikael Pettersson <mikpe@it.uu.se>
 *  		    Please ALWAYS copy linux-ide@vger.kernel.org
 *		    on emails.
 *
@@ -45,11 +46,12 @@
#include "sata_promise.h"

#define DRV_NAME	"sata_promise"
#define DRV_VERSION	"2.10"
#define DRV_VERSION	"2.11"

enum {
	PDC_MAX_PORTS		= 4,
	PDC_MMIO_BAR		= 3,
	PDC_MAX_PRD		= LIBATA_MAX_PRD - 1, /* -1 for ASIC PRD bug workaround */

	/* register offsets */
	PDC_FEATURE		= 0x04, /* Feature/Error reg (per port) */
@@ -157,7 +159,7 @@ static struct scsi_host_template pdc_ata_sht = {
	.queuecommand		= ata_scsi_queuecmd,
	.can_queue		= ATA_DEF_QUEUE,
	.this_id		= ATA_SHT_THIS_ID,
	.sg_tablesize		= LIBATA_MAX_PRD,
	.sg_tablesize		= PDC_MAX_PRD,
	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
	.emulated		= ATA_SHT_EMULATED,
	.use_clustering		= ATA_SHT_USE_CLUSTERING,
@@ -240,7 +242,7 @@ static const struct ata_port_operations pdc_pata_ops = {
};

static const struct ata_port_info pdc_port_info[] = {
	/* board_2037x */
	[board_2037x] =
	{
		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SATA |
				  PDC_FLAG_SATA_PATA,
@@ -250,7 +252,7 @@ static const struct ata_port_info pdc_port_info[] = {
		.port_ops	= &pdc_old_sata_ops,
	},

	/* board_2037x_pata */
	[board_2037x_pata] =
	{
		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS,
		.pio_mask	= 0x1f, /* pio0-4 */
@@ -259,7 +261,7 @@ static const struct ata_port_info pdc_port_info[] = {
		.port_ops	= &pdc_pata_ops,
	},

	/* board_20319 */
	[board_20319] =
	{
		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SATA |
				  PDC_FLAG_4_PORTS,
@@ -269,7 +271,7 @@ static const struct ata_port_info pdc_port_info[] = {
		.port_ops	= &pdc_old_sata_ops,
	},

	/* board_20619 */
	[board_20619] =
	{
		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS |
				  PDC_FLAG_4_PORTS,
@@ -279,7 +281,7 @@ static const struct ata_port_info pdc_port_info[] = {
		.port_ops	= &pdc_pata_ops,
	},

	/* board_2057x */
	[board_2057x] =
	{
		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SATA |
				  PDC_FLAG_GEN_II | PDC_FLAG_SATA_PATA,
@@ -289,7 +291,7 @@ static const struct ata_port_info pdc_port_info[] = {
		.port_ops	= &pdc_sata_ops,
	},

	/* board_2057x_pata */
	[board_2057x_pata] =
	{
		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS |
				  PDC_FLAG_GEN_II,
@@ -299,7 +301,7 @@ static const struct ata_port_info pdc_port_info[] = {
		.port_ops	= &pdc_pata_ops,
	},

	/* board_40518 */
	[board_40518] =
	{
		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SATA |
				  PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS,
@@ -523,6 +525,84 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc)
	memcpy(buf+31, cdb, cdb_len);
}

/**
 *	pdc_fill_sg - Fill PCI IDE PRD table
 *	@qc: Metadata associated with taskfile to be transferred
 *
 *	Fill PCI IDE PRD (scatter-gather) table with segments
 *	associated with the current disk command.
 *	Make sure hardware does not choke on it.
 *
 *	LOCKING:
 *	spin_lock_irqsave(host lock)
 *
 */
static void pdc_fill_sg(struct ata_queued_cmd *qc)
{
	struct ata_port *ap = qc->ap;
	struct scatterlist *sg;
	unsigned int idx;
	const u32 SG_COUNT_ASIC_BUG = 41*4;

	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
		return;

	WARN_ON(qc->__sg == NULL);
	WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);

	idx = 0;
	ata_for_each_sg(sg, qc) {
		u32 addr, offset;
		u32 sg_len, len;

		/* determine if physical DMA addr spans 64K boundary.
		 * Note h/w doesn't support 64-bit, so we unconditionally
		 * truncate dma_addr_t to u32.
		 */
		addr = (u32) sg_dma_address(sg);
		sg_len = sg_dma_len(sg);

		while (sg_len) {
			offset = addr & 0xffff;
			len = sg_len;
			if ((offset + sg_len) > 0x10000)
				len = 0x10000 - offset;

			ap->prd[idx].addr = cpu_to_le32(addr);
			ap->prd[idx].flags_len = cpu_to_le32(len & 0xffff);
			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);

			idx++;
			sg_len -= len;
			addr += len;
		}
	}

	if (idx) {
		u32 len = le32_to_cpu(ap->prd[idx - 1].flags_len);

		if (len > SG_COUNT_ASIC_BUG) {
			u32 addr;

			VPRINTK("Splitting last PRD.\n");

			addr = le32_to_cpu(ap->prd[idx - 1].addr);
			ap->prd[idx - 1].flags_len -= cpu_to_le32(SG_COUNT_ASIC_BUG);
			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx - 1, addr, SG_COUNT_ASIC_BUG);

			addr = addr + len - SG_COUNT_ASIC_BUG;
			len = SG_COUNT_ASIC_BUG;
			ap->prd[idx].addr = cpu_to_le32(addr);
			ap->prd[idx].flags_len = cpu_to_le32(len);
			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);

			idx++;
		}

		ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
	}
}

static void pdc_qc_prep(struct ata_queued_cmd *qc)
{
	struct pdc_port_priv *pp = qc->ap->private_data;
@@ -532,7 +612,7 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)

	switch (qc->tf.protocol) {
	case ATA_PROT_DMA:
		ata_qc_prep(qc);
		pdc_fill_sg(qc);
		/* fall through */

	case ATA_PROT_NODATA:
@@ -548,11 +628,11 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)
		break;

	case ATA_PROT_ATAPI:
		ata_qc_prep(qc);
		pdc_fill_sg(qc);
		break;

	case ATA_PROT_ATAPI_DMA:
		ata_qc_prep(qc);
		pdc_fill_sg(qc);
		/*FALLTHROUGH*/
	case ATA_PROT_ATAPI_NODATA:
		pdc_atapi_pkt(qc);
+3 −3
Original line number Diff line number Diff line
@@ -265,11 +265,11 @@ static struct sil24_cerr_info {
	unsigned int err_mask, action;
	const char *desc;
} sil24_cerr_db[] = {
	[0]			= { AC_ERR_DEV, ATA_EH_REVALIDATE,
	[0]			= { AC_ERR_DEV, 0,
				    "device error" },
	[PORT_CERR_DEV]		= { AC_ERR_DEV, ATA_EH_REVALIDATE,
	[PORT_CERR_DEV]		= { AC_ERR_DEV, 0,
				    "device error via D2H FIS" },
	[PORT_CERR_SDB]		= { AC_ERR_DEV, ATA_EH_REVALIDATE,
	[PORT_CERR_SDB]		= { AC_ERR_DEV, 0,
				    "device error via SDB FIS" },
	[PORT_CERR_DATA]	= { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET,
				    "error in data FIS" },
+1 −0
Original line number Diff line number Diff line
@@ -221,6 +221,7 @@ enum {
	ATA_QCFLAG_IO		= (1 << 3), /* standard IO command */
	ATA_QCFLAG_RESULT_TF	= (1 << 4), /* result TF requested */
	ATA_QCFLAG_CLEAR_EXCL	= (1 << 5), /* clear excl_link on completion */
	ATA_QCFLAG_QUIET	= (1 << 6), /* don't report device error */

	ATA_QCFLAG_FAILED	= (1 << 16), /* cmd failed and is owned by EH */
	ATA_QCFLAG_SENSE_VALID	= (1 << 17), /* sense data valid */