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

Commit 8dd2e3bd authored by Jeff Garzik's avatar Jeff Garzik
Browse files

Merge branch 'tmp'

parents 2af5920b 71e834f5
Loading
Loading
Loading
Loading
+55 −27
Original line number Diff line number Diff line
@@ -446,10 +446,61 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in,
	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}

static void ahci_phy_reset(struct ata_port *ap)
static int ahci_stop_engine(struct ata_port *ap)
{
	void __iomem *mmio = ap->host_set->mmio_base;
	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
	int work;
	u32 tmp;

	tmp = readl(port_mmio + PORT_CMD);
	tmp &= ~PORT_CMD_START;
	writel(tmp, port_mmio + PORT_CMD);

	/* wait for engine to stop.  TODO: this could be
	 * as long as 500 msec
	 */
	work = 1000;
	while (work-- > 0) {
		tmp = readl(port_mmio + PORT_CMD);
		if ((tmp & PORT_CMD_LIST_ON) == 0)
			return 0;
		udelay(10);
	}

	return -EIO;
}

static void ahci_start_engine(struct ata_port *ap)
{
	void __iomem *mmio = ap->host_set->mmio_base;
	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
	u32 tmp;

	tmp = readl(port_mmio + PORT_CMD);
	tmp |= PORT_CMD_START;
	writel(tmp, port_mmio + PORT_CMD);
	readl(port_mmio + PORT_CMD); /* flush */
}

static unsigned int ahci_dev_classify(struct ata_port *ap)
{
	void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
	struct ata_taskfile tf;
	u32 tmp;

	tmp = readl(port_mmio + PORT_SIG);
	tf.lbah		= (tmp >> 24)	& 0xff;
	tf.lbam		= (tmp >> 16)	& 0xff;
	tf.lbal		= (tmp >> 8)	& 0xff;
	tf.nsect	= (tmp)		& 0xff;

	return ata_dev_classify(&tf);
}

static void ahci_phy_reset(struct ata_port *ap)
{
	void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
	struct ata_device *dev = &ap->device[0];
	u32 new_tmp, tmp;

@@ -458,13 +509,7 @@ static void ahci_phy_reset(struct ata_port *ap)
	if (ap->flags & ATA_FLAG_PORT_DISABLED)
		return;

	tmp = readl(port_mmio + PORT_SIG);
	tf.lbah		= (tmp >> 24)	& 0xff;
	tf.lbam		= (tmp >> 16)	& 0xff;
	tf.lbal		= (tmp >> 8)	& 0xff;
	tf.nsect	= (tmp)		& 0xff;

	dev->class = ata_dev_classify(&tf);
	dev->class = ahci_dev_classify(ap);
	if (!ata_dev_present(dev)) {
		ata_port_disable(ap);
		return;
@@ -572,7 +617,6 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
	void __iomem *mmio = ap->host_set->mmio_base;
	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
	u32 tmp;
	int work;

	if ((ap->device[0].class != ATA_DEV_ATAPI) ||
	    ((irq_stat & PORT_IRQ_TF_ERR) == 0))
@@ -588,20 +632,7 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
			readl(port_mmio + PORT_SCR_ERR));

	/* stop DMA */
	tmp = readl(port_mmio + PORT_CMD);
	tmp &= ~PORT_CMD_START;
	writel(tmp, port_mmio + PORT_CMD);

	/* wait for engine to stop.  TODO: this could be
	 * as long as 500 msec
	 */
	work = 1000;
	while (work-- > 0) {
		tmp = readl(port_mmio + PORT_CMD);
		if ((tmp & PORT_CMD_LIST_ON) == 0)
			break;
		udelay(10);
	}
	ahci_stop_engine(ap);

	/* clear SATA phy error, if any */
	tmp = readl(port_mmio + PORT_SCR_ERR);
@@ -620,10 +651,7 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
	}

	/* re-start DMA */
	tmp = readl(port_mmio + PORT_CMD);
	tmp |= PORT_CMD_START;
	writel(tmp, port_mmio + PORT_CMD);
	readl(port_mmio + PORT_CMD); /* flush */
	ahci_start_engine(ap);
}

static void ahci_eng_timeout(struct ata_port *ap)
+39 −14
Original line number Diff line number Diff line
@@ -101,9 +101,11 @@ enum {
	ICH5_PCS		= 0x92,	/* port control and status */
	PIIX_SCC		= 0x0A, /* sub-class code register */

	PIIX_FLAG_AHCI		= (1 << 28), /* AHCI possible */
	PIIX_FLAG_CHECKINTR	= (1 << 29), /* make sure PCI INTx enabled */
	PIIX_FLAG_COMBINED	= (1 << 30), /* combined mode possible */
	PIIX_FLAG_AHCI		= (1 << 27), /* AHCI possible */
	PIIX_FLAG_CHECKINTR	= (1 << 28), /* make sure PCI INTx enabled */
	PIIX_FLAG_COMBINED	= (1 << 29), /* combined mode possible */
	/* ICH6/7 use different scheme for map value */
	PIIX_FLAG_COMBINED_ICH6	= PIIX_FLAG_COMBINED | (1 << 30),

	/* combined mode.  if set, PATA is channel 0.
	 * if clear, PATA is channel 1.
@@ -297,8 +299,8 @@ static struct ata_port_info piix_port_info[] = {
	{
		.sht		= &piix_sht,
		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST |
				  PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
				  ATA_FLAG_SLAVE_POSS,
				  PIIX_FLAG_COMBINED_ICH6 |
				  PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS,
		.pio_mask	= 0x1f,	/* pio0-4 */
		.mwdma_mask	= 0x07, /* mwdma0-2 */
		.udma_mask	= 0x7f,	/* udma0-6 */
@@ -309,8 +311,9 @@ static struct ata_port_info piix_port_info[] = {
	{
		.sht		= &piix_sht,
		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST |
				  PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
				  ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI,
				  PIIX_FLAG_COMBINED_ICH6 |
				  PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS |
				  PIIX_FLAG_AHCI,
		.pio_mask	= 0x1f,	/* pio0-4 */
		.mwdma_mask	= 0x07, /* mwdma0-2 */
		.udma_mask	= 0x7f,	/* udma0-6 */
@@ -680,6 +683,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
	struct ata_port_info *port_info[2];
	unsigned int combined = 0;
	unsigned int pata_chan = 0, sata_chan = 0;
	unsigned long host_flags;

	if (!printed_version++)
		dev_printk(KERN_DEBUG, &pdev->dev,
@@ -692,7 +696,9 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
	port_info[0] = &piix_port_info[ent->driver_data];
	port_info[1] = &piix_port_info[ent->driver_data];

	if (port_info[0]->host_flags & PIIX_FLAG_AHCI) {
	host_flags = port_info[0]->host_flags;

	if (host_flags & PIIX_FLAG_AHCI) {
		u8 tmp;
		pci_read_config_byte(pdev, PIIX_SCC, &tmp);
		if (tmp == PIIX_AHCI_DEVICE) {
@@ -702,10 +708,28 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
		}
	}

	if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) {
	if (host_flags & PIIX_FLAG_COMBINED) {
		u8 tmp;
		pci_read_config_byte(pdev, ICH5_PMR, &tmp);

		if (host_flags & PIIX_FLAG_COMBINED_ICH6) {
			switch (tmp) {
			case 0:
				break;
			case 1:
				combined = 1;
				sata_chan = 1;
				break;
			case 2:
				combined = 1;
				pata_chan = 1;
				break;
			case 3:
				dev_printk(KERN_WARNING, &pdev->dev,
					   "invalid MAP value %u\n", tmp);
				break;
			}
		} else {
			if (tmp & PIIX_COMB) {
				combined = 1;
				if (tmp & PIIX_COMB_PATA_P0)
@@ -714,6 +738,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
					pata_chan = 1;
			}
		}
	}

	/* On ICH5, some BIOSen disable the interrupt using the
	 * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3.
@@ -721,7 +746,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
	 * MSI is disabled (and it is disabled, as we don't use
	 * message-signalled interrupts currently).
	 */
	if (port_info[0]->host_flags & PIIX_FLAG_CHECKINTR)
	if (host_flags & PIIX_FLAG_CHECKINTR)
		pci_intx(pdev, 1);

	if (combined) {
+40 −18
Original line number Diff line number Diff line
@@ -1535,6 +1535,41 @@ void ata_port_probe(struct ata_port *ap)
	ap->flags &= ~ATA_FLAG_PORT_DISABLED;
}

/**
 *	sata_print_link_status - Print SATA link status
 *	@ap: SATA port to printk link status about
 *
 *	This function prints link speed and status of a SATA link.
 *
 *	LOCKING:
 *	None.
 */
static void sata_print_link_status(struct ata_port *ap)
{
	u32 sstatus, tmp;
	const char *speed;

	if (!ap->ops->scr_read)
		return;

	sstatus = scr_read(ap, SCR_STATUS);

	if (sata_dev_present(ap)) {
		tmp = (sstatus >> 4) & 0xf;
		if (tmp & (1 << 0))
			speed = "1.5";
		else if (tmp & (1 << 1))
			speed = "3.0";
		else
			speed = "<unknown>";
		printk(KERN_INFO "ata%u: SATA link up %s Gbps (SStatus %X)\n",
		       ap->id, speed, sstatus);
	} else {
		printk(KERN_INFO "ata%u: SATA link down (SStatus %X)\n",
		       ap->id, sstatus);
	}
}

/**
 *	__sata_phy_reset - Wake/reset a low-level SATA PHY
 *	@ap: SATA port associated with target SATA PHY.
@@ -1569,27 +1604,14 @@ void __sata_phy_reset(struct ata_port *ap)
			break;
	} while (time_before(jiffies, timeout));

	/* TODO: phy layer with polling, timeouts, etc. */
	sstatus = scr_read(ap, SCR_STATUS);
	if (sata_dev_present(ap)) {
		const char *speed;
		u32 tmp;
	/* print link status */
	sata_print_link_status(ap);

		tmp = (sstatus >> 4) & 0xf;
		if (tmp & (1 << 0))
			speed = "1.5";
		else if (tmp & (1 << 1))
			speed = "3.0";
		else
			speed = "<unknown>";
		printk(KERN_INFO "ata%u: SATA link up %s Gbps (SStatus %X)\n",
		       ap->id, speed, sstatus);
	/* TODO: phy layer with polling, timeouts, etc. */
	if (sata_dev_present(ap))
		ata_port_probe(ap);
	} else {
		printk(KERN_INFO "ata%u: SATA link down (SStatus %X)\n",
		       ap->id, sstatus);
	else
		ata_port_disable(ap);
	}

	if (ap->flags & ATA_FLAG_PORT_DISABLED)
		return;
+21 −27
Original line number Diff line number Diff line
@@ -985,9 +985,13 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc
	if (dev->flags & ATA_DFLAG_LBA) {
		tf->flags |= ATA_TFLAG_LBA;

		if (dev->flags & ATA_DFLAG_LBA48) {
			if (n_block > (64 * 1024))
				goto invalid_fld;
		if (lba_28_ok(block, n_block)) {
			/* use LBA28 */
			tf->command = ATA_CMD_VERIFY;
			tf->device |= (block >> 24) & 0xf;
		} else if (lba_48_ok(block, n_block)) {
			if (!(dev->flags & ATA_DFLAG_LBA48))
				goto out_of_range;

			/* use LBA48 */
			tf->flags |= ATA_TFLAG_LBA48;
@@ -998,15 +1002,9 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc
			tf->hob_lbah = (block >> 40) & 0xff;
			tf->hob_lbam = (block >> 32) & 0xff;
			tf->hob_lbal = (block >> 24) & 0xff;
		} else {
			if (n_block > 256)
				goto invalid_fld;

			/* use LBA28 */
			tf->command = ATA_CMD_VERIFY;

			tf->device |= (block >> 24) & 0xf;
		}
		} else
			/* request too large even for LBA48 */
			goto out_of_range;

		tf->nsect = n_block & 0xff;

@@ -1019,8 +1017,8 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc
		/* CHS */
		u32 sect, head, cyl, track;

		if (n_block > 256)
			goto invalid_fld;
		if (!lba_28_ok(block, n_block))
			goto out_of_range;

		/* Convert LBA to CHS */
		track = (u32)block / dev->sectors;
@@ -1139,9 +1137,11 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
	if (dev->flags & ATA_DFLAG_LBA) {
		tf->flags |= ATA_TFLAG_LBA;

		if (dev->flags & ATA_DFLAG_LBA48) {
			/* The request -may- be too large for LBA48. */
			if ((block >> 48) || (n_block > 65536))
		if (lba_28_ok(block, n_block)) {
			/* use LBA28 */
			tf->device |= (block >> 24) & 0xf;
		} else if (lba_48_ok(block, n_block)) {
			if (!(dev->flags & ATA_DFLAG_LBA48))
				goto out_of_range;

			/* use LBA48 */
@@ -1152,16 +1152,10 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
			tf->hob_lbah = (block >> 40) & 0xff;
			tf->hob_lbam = (block >> 32) & 0xff;
			tf->hob_lbal = (block >> 24) & 0xff;
		} else { 
			/* use LBA28 */

			/* The request -may- be too large for LBA28. */
			if ((block >> 28) || (n_block > 256))
		} else
			/* request too large even for LBA48 */
			goto out_of_range;

			tf->device |= (block >> 24) & 0xf;
		}

		if (unlikely(ata_rwcmd_protocol(qc) < 0))
			goto invalid_fld;

@@ -1178,7 +1172,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
		u32 sect, head, cyl, track;

		/* The request -may- be too large for CHS addressing. */
		if ((block >> 28) || (n_block > 256))
		if (!lba_28_ok(block, n_block))
			goto out_of_range;

		if (unlikely(ata_rwcmd_protocol(qc) < 0))
+12 −0
Original line number Diff line number Diff line
@@ -313,4 +313,16 @@ static inline int ata_ok(u8 status)
			== ATA_DRDY);
}

static inline int lba_28_ok(u64 block, u32 n_block)
{
	/* check the ending block number */
	return ((block + n_block - 1) < ((u64)1 << 28)) && (n_block <= 256);
}

static inline int lba_48_ok(u64 block, u32 n_block)
{
	/* check the ending block number */
	return ((block + n_block - 1) < ((u64)1 << 48)) && (n_block <= 65536);
}

#endif /* __LINUX_ATA_H__ */
Loading