Loading drivers/scsi/ahci.c +55 −27 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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)) Loading @@ -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); Loading @@ -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) Loading drivers/scsi/ata_piix.c +39 −14 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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 */ Loading @@ -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 */ Loading Loading @@ -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, Loading @@ -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) { Loading @@ -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) Loading @@ -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. Loading @@ -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) { Loading drivers/scsi/libata-core.c +40 −18 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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; Loading drivers/scsi/libata-scsi.c +21 −27 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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 */ Loading @@ -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; Loading @@ -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)) Loading include/linux/ata.h +12 −0 Original line number Diff line number Diff line Loading @@ -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
drivers/scsi/ahci.c +55 −27 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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)) Loading @@ -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); Loading @@ -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) Loading
drivers/scsi/ata_piix.c +39 −14 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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 */ Loading @@ -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 */ Loading Loading @@ -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, Loading @@ -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) { Loading @@ -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) Loading @@ -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. Loading @@ -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) { Loading
drivers/scsi/libata-core.c +40 −18 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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; Loading
drivers/scsi/libata-scsi.c +21 −27 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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 */ Loading @@ -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; Loading @@ -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)) Loading
include/linux/ata.h +12 −0 Original line number Diff line number Diff line Loading @@ -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__ */