diff options
| author | Ben Hutchings <bhutchings@solarflare.com> | 2008-12-13 00:33:50 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2008-12-13 00:57:35 -0500 |
| commit | be4ea89c8df06f48d0d64cf1d9d20009e83c77c8 (patch) | |
| tree | fb48f89ea32ef55e336242e33d6ccfd1f5ff4295 /drivers/net/sfc | |
| parent | 1ab00629f06fb3c47de6373cd92d086f33775444 (diff) | |
sfc: Clean up waits for flash/EEPROM operations
Make falcon_spi_wait() ignore the write timer - it is only relevant to
write commands, it only works for the device that contains VPD, and it
might not be initialised properly at all.
Rename falcon_spi_fast_wait() to falcon_spi_wait_write(), reflecting
its use, and make it wait up to 10 ms (not 1 ms) since buffered writes
to EEPROM may take this long to complete.
Make both wait functions sleep instead of busy-waiting.
Replace wait for command completion at top of falcon_spi_cmd() with a
single poll; no command should be running when the function starts.
Correct some comments.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc')
| -rw-r--r-- | drivers/net/sfc/falcon.c | 58 | ||||
| -rw-r--r-- | drivers/net/sfc/mtd.c | 2 | ||||
| -rw-r--r-- | drivers/net/sfc/spi.h | 2 |
3 files changed, 39 insertions, 23 deletions
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 1d160daf83bb..511308560487 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c | |||
| @@ -1607,24 +1607,37 @@ void falcon_fini_interrupt(struct efx_nic *efx) | |||
| 1607 | 1607 | ||
| 1608 | #define FALCON_SPI_MAX_LEN sizeof(efx_oword_t) | 1608 | #define FALCON_SPI_MAX_LEN sizeof(efx_oword_t) |
| 1609 | 1609 | ||
| 1610 | static int falcon_spi_poll(struct efx_nic *efx) | ||
| 1611 | { | ||
| 1612 | efx_oword_t reg; | ||
| 1613 | falcon_read(efx, ®, EE_SPI_HCMD_REG_KER); | ||
| 1614 | return EFX_OWORD_FIELD(reg, EE_SPI_HCMD_CMD_EN) ? -EBUSY : 0; | ||
| 1615 | } | ||
| 1616 | |||
| 1610 | /* Wait for SPI command completion */ | 1617 | /* Wait for SPI command completion */ |
| 1611 | static int falcon_spi_wait(struct efx_nic *efx) | 1618 | static int falcon_spi_wait(struct efx_nic *efx) |
| 1612 | { | 1619 | { |
| 1613 | unsigned long timeout = jiffies + DIV_ROUND_UP(HZ, 10); | 1620 | /* Most commands will finish quickly, so we start polling at |
| 1614 | efx_oword_t reg; | 1621 | * very short intervals. Sometimes the command may have to |
| 1615 | bool cmd_en, timer_active; | 1622 | * wait for VPD or expansion ROM access outside of our |
| 1623 | * control, so we allow up to 100 ms. */ | ||
| 1624 | unsigned long timeout = jiffies + 1 + DIV_ROUND_UP(HZ, 10); | ||
| 1625 | int i; | ||
| 1626 | |||
| 1627 | for (i = 0; i < 10; i++) { | ||
| 1628 | if (!falcon_spi_poll(efx)) | ||
| 1629 | return 0; | ||
| 1630 | udelay(10); | ||
| 1631 | } | ||
| 1616 | 1632 | ||
| 1617 | for (;;) { | 1633 | for (;;) { |
| 1618 | falcon_read(efx, ®, EE_SPI_HCMD_REG_KER); | 1634 | if (!falcon_spi_poll(efx)) |
| 1619 | cmd_en = EFX_OWORD_FIELD(reg, EE_SPI_HCMD_CMD_EN); | ||
| 1620 | timer_active = EFX_OWORD_FIELD(reg, EE_WR_TIMER_ACTIVE); | ||
| 1621 | if (!cmd_en && !timer_active) | ||
| 1622 | return 0; | 1635 | return 0; |
| 1623 | if (time_after_eq(jiffies, timeout)) { | 1636 | if (time_after_eq(jiffies, timeout)) { |
| 1624 | EFX_ERR(efx, "timed out waiting for SPI\n"); | 1637 | EFX_ERR(efx, "timed out waiting for SPI\n"); |
| 1625 | return -ETIMEDOUT; | 1638 | return -ETIMEDOUT; |
| 1626 | } | 1639 | } |
| 1627 | cpu_relax(); | 1640 | schedule_timeout_uninterruptible(1); |
| 1628 | } | 1641 | } |
| 1629 | } | 1642 | } |
| 1630 | 1643 | ||
| @@ -1643,8 +1656,8 @@ int falcon_spi_cmd(const struct efx_spi_device *spi, | |||
| 1643 | return -EINVAL; | 1656 | return -EINVAL; |
| 1644 | BUG_ON(!mutex_is_locked(&efx->spi_lock)); | 1657 | BUG_ON(!mutex_is_locked(&efx->spi_lock)); |
| 1645 | 1658 | ||
| 1646 | /* Check SPI not currently being accessed */ | 1659 | /* Check that previous command is not still running */ |
| 1647 | rc = falcon_spi_wait(efx); | 1660 | rc = falcon_spi_poll(efx); |
| 1648 | if (rc) | 1661 | if (rc) |
| 1649 | return rc; | 1662 | return rc; |
| 1650 | 1663 | ||
| @@ -1700,26 +1713,29 @@ efx_spi_munge_command(const struct efx_spi_device *spi, | |||
| 1700 | return command | (((address >> 8) & spi->munge_address) << 3); | 1713 | return command | (((address >> 8) & spi->munge_address) << 3); |
| 1701 | } | 1714 | } |
| 1702 | 1715 | ||
| 1703 | int falcon_spi_fast_wait(const struct efx_spi_device *spi) | 1716 | /* Wait up to 10 ms for buffered write completion */ |
| 1717 | int falcon_spi_wait_write(const struct efx_spi_device *spi) | ||
| 1704 | { | 1718 | { |
| 1719 | struct efx_nic *efx = spi->efx; | ||
| 1720 | unsigned long timeout = jiffies + 1 + DIV_ROUND_UP(HZ, 100); | ||
| 1705 | u8 status; | 1721 | u8 status; |
| 1706 | int i, rc; | 1722 | int rc; |
| 1707 | |||
| 1708 | /* Wait up to 1000us for flash/EEPROM to finish a fast operation. */ | ||
| 1709 | for (i = 0; i < 50; i++) { | ||
| 1710 | udelay(20); | ||
| 1711 | 1723 | ||
| 1724 | for (;;) { | ||
| 1712 | rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL, | 1725 | rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL, |
| 1713 | &status, sizeof(status)); | 1726 | &status, sizeof(status)); |
| 1714 | if (rc) | 1727 | if (rc) |
| 1715 | return rc; | 1728 | return rc; |
| 1716 | if (!(status & SPI_STATUS_NRDY)) | 1729 | if (!(status & SPI_STATUS_NRDY)) |
| 1717 | return 0; | 1730 | return 0; |
| 1731 | if (time_after_eq(jiffies, timeout)) { | ||
| 1732 | EFX_ERR(efx, "SPI write timeout on device %d" | ||
| 1733 | " last status=0x%02x\n", | ||
| 1734 | spi->device_id, status); | ||
| 1735 | return -ETIMEDOUT; | ||
| 1736 | } | ||
| 1737 | schedule_timeout_uninterruptible(1); | ||
| 1718 | } | 1738 | } |
| 1719 | EFX_ERR(spi->efx, | ||
| 1720 | "timed out waiting for device %d last status=0x%02x\n", | ||
| 1721 | spi->device_id, status); | ||
| 1722 | return -ETIMEDOUT; | ||
| 1723 | } | 1739 | } |
| 1724 | 1740 | ||
| 1725 | int falcon_spi_read(const struct efx_spi_device *spi, loff_t start, | 1741 | int falcon_spi_read(const struct efx_spi_device *spi, loff_t start, |
| @@ -1773,7 +1789,7 @@ int falcon_spi_write(const struct efx_spi_device *spi, loff_t start, | |||
| 1773 | if (rc) | 1789 | if (rc) |
| 1774 | break; | 1790 | break; |
| 1775 | 1791 | ||
| 1776 | rc = falcon_spi_fast_wait(spi); | 1792 | rc = falcon_spi_wait_write(spi); |
| 1777 | if (rc) | 1793 | if (rc) |
| 1778 | break; | 1794 | break; |
| 1779 | 1795 | ||
diff --git a/drivers/net/sfc/mtd.c b/drivers/net/sfc/mtd.c index a1e6c2875fc0..665cafb88d6a 100644 --- a/drivers/net/sfc/mtd.c +++ b/drivers/net/sfc/mtd.c | |||
| @@ -76,7 +76,7 @@ static int efx_spi_unlock(const struct efx_spi_device *spi) | |||
| 76 | rc = falcon_spi_cmd(spi, SPI_WRSR, -1, &status, NULL, sizeof(status)); | 76 | rc = falcon_spi_cmd(spi, SPI_WRSR, -1, &status, NULL, sizeof(status)); |
| 77 | if (rc) | 77 | if (rc) |
| 78 | return rc; | 78 | return rc; |
| 79 | rc = falcon_spi_fast_wait(spi); | 79 | rc = falcon_spi_wait_write(spi); |
| 80 | if (rc) | 80 | if (rc) |
| 81 | return rc; | 81 | return rc; |
| 82 | 82 | ||
diff --git a/drivers/net/sfc/spi.h b/drivers/net/sfc/spi.h index 38e22ff4d7af..1b1ceb411671 100644 --- a/drivers/net/sfc/spi.h +++ b/drivers/net/sfc/spi.h | |||
| @@ -69,7 +69,7 @@ struct efx_spi_device { | |||
| 69 | 69 | ||
| 70 | int falcon_spi_cmd(const struct efx_spi_device *spi, unsigned int command, | 70 | int falcon_spi_cmd(const struct efx_spi_device *spi, unsigned int command, |
| 71 | int address, const void* in, void *out, size_t len); | 71 | int address, const void* in, void *out, size_t len); |
| 72 | int falcon_spi_fast_wait(const struct efx_spi_device *spi); | 72 | int falcon_spi_wait_write(const struct efx_spi_device *spi); |
| 73 | int falcon_spi_read(const struct efx_spi_device *spi, loff_t start, | 73 | int falcon_spi_read(const struct efx_spi_device *spi, loff_t start, |
| 74 | size_t len, size_t *retlen, u8 *buffer); | 74 | size_t len, size_t *retlen, u8 *buffer); |
| 75 | int falcon_spi_write(const struct efx_spi_device *spi, loff_t start, | 75 | int falcon_spi_write(const struct efx_spi_device *spi, loff_t start, |
