diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-11-17 10:59:48 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-11-17 10:59:48 -0500 |
commit | 22374677d18c5eeefd3a283431d312b8c44fef02 (patch) | |
tree | 4d923291cdab7c84e0346a8500f090f2b11e2bc1 /drivers | |
parent | 64f043d80752a8e5f0d55255e7bb9a1a05af206f (diff) |
[libata sata_mv] SATA probe, DMA boundary fixes
- DMA boundary was being handled incorrectly. Copied the code from
ata_fill_sg(), since Marvell has the same DMA boundary needs.
(we can't use ata_fill_sg directly since we have different hardware
descriptors)
- cleaned up the SATA phy reset code, to deal with various errata
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/sata_mv.c | 88 |
1 files changed, 70 insertions, 18 deletions
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 722ab537b7a6..ee0634da0872 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c | |||
@@ -321,6 +321,7 @@ static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); | |||
321 | static u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in); | 321 | static u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in); |
322 | static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); | 322 | static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); |
323 | static void mv_phy_reset(struct ata_port *ap); | 323 | static void mv_phy_reset(struct ata_port *ap); |
324 | static void __mv_phy_reset(struct ata_port *ap, int can_sleep); | ||
324 | static void mv_host_stop(struct ata_host_set *host_set); | 325 | static void mv_host_stop(struct ata_host_set *host_set); |
325 | static int mv_port_start(struct ata_port *ap); | 326 | static int mv_port_start(struct ata_port *ap); |
326 | static void mv_port_stop(struct ata_port *ap); | 327 | static void mv_port_stop(struct ata_port *ap); |
@@ -362,7 +363,7 @@ static struct scsi_host_template mv_sht = { | |||
362 | .eh_strategy_handler = ata_scsi_error, | 363 | .eh_strategy_handler = ata_scsi_error, |
363 | .can_queue = MV_USE_Q_DEPTH, | 364 | .can_queue = MV_USE_Q_DEPTH, |
364 | .this_id = ATA_SHT_THIS_ID, | 365 | .this_id = ATA_SHT_THIS_ID, |
365 | .sg_tablesize = MV_MAX_SG_CT, | 366 | .sg_tablesize = MV_MAX_SG_CT / 2, |
366 | .max_sectors = ATA_MAX_SECTORS, | 367 | .max_sectors = ATA_MAX_SECTORS, |
367 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 368 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
368 | .emulated = ATA_SHT_EMULATED, | 369 | .emulated = ATA_SHT_EMULATED, |
@@ -893,20 +894,30 @@ static void mv_fill_sg(struct ata_queued_cmd *qc) | |||
893 | struct scatterlist *sg; | 894 | struct scatterlist *sg; |
894 | 895 | ||
895 | ata_for_each_sg(sg, qc) { | 896 | ata_for_each_sg(sg, qc) { |
896 | u32 sg_len; | ||
897 | dma_addr_t addr; | 897 | dma_addr_t addr; |
898 | u32 sg_len, len, offset; | ||
898 | 899 | ||
899 | addr = sg_dma_address(sg); | 900 | addr = sg_dma_address(sg); |
900 | sg_len = sg_dma_len(sg); | 901 | sg_len = sg_dma_len(sg); |
901 | 902 | ||
902 | pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff); | 903 | while (sg_len) { |
903 | pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16); | 904 | offset = addr & MV_DMA_BOUNDARY; |
904 | assert(0 == (sg_len & ~MV_DMA_BOUNDARY)); | 905 | len = sg_len; |
905 | pp->sg_tbl[i].flags_size = cpu_to_le32(sg_len); | 906 | if ((offset + sg_len) > 0x10000) |
906 | if (ata_sg_is_last(sg, qc)) | 907 | len = 0x10000 - offset; |
907 | pp->sg_tbl[i].flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); | ||
908 | 908 | ||
909 | i++; | 909 | pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff); |
910 | pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16); | ||
911 | pp->sg_tbl[i].flags_size = cpu_to_le32(len); | ||
912 | |||
913 | sg_len -= len; | ||
914 | addr += len; | ||
915 | |||
916 | if (!sg_len && ata_sg_is_last(sg, qc)) | ||
917 | pp->sg_tbl[i].flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); | ||
918 | |||
919 | i++; | ||
920 | } | ||
910 | } | 921 | } |
911 | } | 922 | } |
912 | 923 | ||
@@ -1693,11 +1704,19 @@ static void mv_stop_and_reset(struct ata_port *ap) | |||
1693 | 1704 | ||
1694 | mv_channel_reset(hpriv, mmio, ap->port_no); | 1705 | mv_channel_reset(hpriv, mmio, ap->port_no); |
1695 | 1706 | ||
1696 | mv_phy_reset(ap); | 1707 | __mv_phy_reset(ap, 0); |
1708 | } | ||
1709 | |||
1710 | static inline void __msleep(unsigned int msec, int can_sleep) | ||
1711 | { | ||
1712 | if (can_sleep) | ||
1713 | msleep(msec); | ||
1714 | else | ||
1715 | mdelay(msec); | ||
1697 | } | 1716 | } |
1698 | 1717 | ||
1699 | /** | 1718 | /** |
1700 | * mv_phy_reset - Perform eDMA reset followed by COMRESET | 1719 | * __mv_phy_reset - Perform eDMA reset followed by COMRESET |
1701 | * @ap: ATA channel to manipulate | 1720 | * @ap: ATA channel to manipulate |
1702 | * | 1721 | * |
1703 | * Part of this is taken from __sata_phy_reset and modified to | 1722 | * Part of this is taken from __sata_phy_reset and modified to |
@@ -1707,13 +1726,16 @@ static void mv_stop_and_reset(struct ata_port *ap) | |||
1707 | * Inherited from caller. This is coded to safe to call at | 1726 | * Inherited from caller. This is coded to safe to call at |
1708 | * interrupt level, i.e. it does not sleep. | 1727 | * interrupt level, i.e. it does not sleep. |
1709 | */ | 1728 | */ |
1710 | static void mv_phy_reset(struct ata_port *ap) | 1729 | static void __mv_phy_reset(struct ata_port *ap, int can_sleep) |
1711 | { | 1730 | { |
1712 | struct mv_port_priv *pp = ap->private_data; | 1731 | struct mv_port_priv *pp = ap->private_data; |
1732 | struct mv_host_priv *hpriv = ap->host_set->private_data; | ||
1713 | void __iomem *port_mmio = mv_ap_base(ap); | 1733 | void __iomem *port_mmio = mv_ap_base(ap); |
1714 | struct ata_taskfile tf; | 1734 | struct ata_taskfile tf; |
1715 | struct ata_device *dev = &ap->device[0]; | 1735 | struct ata_device *dev = &ap->device[0]; |
1716 | unsigned long timeout; | 1736 | unsigned long timeout; |
1737 | int retry = 5; | ||
1738 | u32 sstatus; | ||
1717 | 1739 | ||
1718 | VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio); | 1740 | VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio); |
1719 | 1741 | ||
@@ -1721,18 +1743,28 @@ static void mv_phy_reset(struct ata_port *ap) | |||
1721 | "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS), | 1743 | "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS), |
1722 | mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL)); | 1744 | mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL)); |
1723 | 1745 | ||
1724 | /* proceed to init communications via the scr_control reg */ | 1746 | /* Issue COMRESET via SControl */ |
1747 | comreset_retry: | ||
1725 | scr_write_flush(ap, SCR_CONTROL, 0x301); | 1748 | scr_write_flush(ap, SCR_CONTROL, 0x301); |
1726 | mdelay(1); | 1749 | __msleep(1, can_sleep); |
1750 | |||
1727 | scr_write_flush(ap, SCR_CONTROL, 0x300); | 1751 | scr_write_flush(ap, SCR_CONTROL, 0x300); |
1728 | timeout = jiffies + (HZ * 1); | 1752 | __msleep(20, can_sleep); |
1753 | |||
1754 | timeout = jiffies + msecs_to_jiffies(200); | ||
1729 | do { | 1755 | do { |
1730 | mdelay(10); | 1756 | sstatus = scr_read(ap, SCR_STATUS) & 0x3; |
1731 | if ((scr_read(ap, SCR_STATUS) & 0xf) != 1) | 1757 | if ((sstatus == 3) || (sstatus == 0)) |
1732 | break; | 1758 | break; |
1759 | |||
1760 | __msleep(1, can_sleep); | ||
1733 | } while (time_before(jiffies, timeout)); | 1761 | } while (time_before(jiffies, timeout)); |
1734 | 1762 | ||
1735 | mv_scr_write(ap, SCR_ERROR, mv_scr_read(ap, SCR_ERROR)); | 1763 | /* work around errata */ |
1764 | if (IS_60XX(hpriv) && | ||
1765 | (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) && | ||
1766 | (retry-- > 0)) | ||
1767 | goto comreset_retry; | ||
1736 | 1768 | ||
1737 | DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x " | 1769 | DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x " |
1738 | "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS), | 1770 | "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS), |
@@ -1748,6 +1780,21 @@ static void mv_phy_reset(struct ata_port *ap) | |||
1748 | } | 1780 | } |
1749 | ap->cbl = ATA_CBL_SATA; | 1781 | ap->cbl = ATA_CBL_SATA; |
1750 | 1782 | ||
1783 | /* even after SStatus reflects that device is ready, | ||
1784 | * it seems to take a while for link to be fully | ||
1785 | * established (and thus Status no longer 0x80/0x7F), | ||
1786 | * so we poll a bit for that, here. | ||
1787 | */ | ||
1788 | retry = 20; | ||
1789 | while (1) { | ||
1790 | u8 drv_stat = ata_check_status(ap); | ||
1791 | if ((drv_stat != 0x80) && (drv_stat != 0x7f)) | ||
1792 | break; | ||
1793 | __msleep(500, can_sleep); | ||
1794 | if (retry-- <= 0) | ||
1795 | break; | ||
1796 | } | ||
1797 | |||
1751 | tf.lbah = readb((void __iomem *) ap->ioaddr.lbah_addr); | 1798 | tf.lbah = readb((void __iomem *) ap->ioaddr.lbah_addr); |
1752 | tf.lbam = readb((void __iomem *) ap->ioaddr.lbam_addr); | 1799 | tf.lbam = readb((void __iomem *) ap->ioaddr.lbam_addr); |
1753 | tf.lbal = readb((void __iomem *) ap->ioaddr.lbal_addr); | 1800 | tf.lbal = readb((void __iomem *) ap->ioaddr.lbal_addr); |
@@ -1766,6 +1813,11 @@ static void mv_phy_reset(struct ata_port *ap) | |||
1766 | VPRINTK("EXIT\n"); | 1813 | VPRINTK("EXIT\n"); |
1767 | } | 1814 | } |
1768 | 1815 | ||
1816 | static void mv_phy_reset(struct ata_port *ap) | ||
1817 | { | ||
1818 | __mv_phy_reset(ap, 1); | ||
1819 | } | ||
1820 | |||
1769 | /** | 1821 | /** |
1770 | * mv_eng_timeout - Routine called by libata when SCSI times out I/O | 1822 | * mv_eng_timeout - Routine called by libata when SCSI times out I/O |
1771 | * @ap: ATA channel to manipulate | 1823 | * @ap: ATA channel to manipulate |