|
@@ -1607,24 +1607,37 @@ void falcon_fini_interrupt(struct efx_nic *efx)
|
|
|
|
|
|
#define FALCON_SPI_MAX_LEN sizeof(efx_oword_t)
|
|
#define FALCON_SPI_MAX_LEN sizeof(efx_oword_t)
|
|
|
|
|
|
|
|
+static int falcon_spi_poll(struct efx_nic *efx)
|
|
|
|
+{
|
|
|
|
+ efx_oword_t reg;
|
|
|
|
+ falcon_read(efx, ®, EE_SPI_HCMD_REG_KER);
|
|
|
|
+ return EFX_OWORD_FIELD(reg, EE_SPI_HCMD_CMD_EN) ? -EBUSY : 0;
|
|
|
|
+}
|
|
|
|
+
|
|
/* Wait for SPI command completion */
|
|
/* Wait for SPI command completion */
|
|
static int falcon_spi_wait(struct efx_nic *efx)
|
|
static int falcon_spi_wait(struct efx_nic *efx)
|
|
{
|
|
{
|
|
- unsigned long timeout = jiffies + DIV_ROUND_UP(HZ, 10);
|
|
|
|
- efx_oword_t reg;
|
|
|
|
- bool cmd_en, timer_active;
|
|
|
|
|
|
+ /* Most commands will finish quickly, so we start polling at
|
|
|
|
+ * very short intervals. Sometimes the command may have to
|
|
|
|
+ * wait for VPD or expansion ROM access outside of our
|
|
|
|
+ * control, so we allow up to 100 ms. */
|
|
|
|
+ unsigned long timeout = jiffies + 1 + DIV_ROUND_UP(HZ, 10);
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < 10; i++) {
|
|
|
|
+ if (!falcon_spi_poll(efx))
|
|
|
|
+ return 0;
|
|
|
|
+ udelay(10);
|
|
|
|
+ }
|
|
|
|
|
|
for (;;) {
|
|
for (;;) {
|
|
- falcon_read(efx, ®, EE_SPI_HCMD_REG_KER);
|
|
|
|
- cmd_en = EFX_OWORD_FIELD(reg, EE_SPI_HCMD_CMD_EN);
|
|
|
|
- timer_active = EFX_OWORD_FIELD(reg, EE_WR_TIMER_ACTIVE);
|
|
|
|
- if (!cmd_en && !timer_active)
|
|
|
|
|
|
+ if (!falcon_spi_poll(efx))
|
|
return 0;
|
|
return 0;
|
|
if (time_after_eq(jiffies, timeout)) {
|
|
if (time_after_eq(jiffies, timeout)) {
|
|
EFX_ERR(efx, "timed out waiting for SPI\n");
|
|
EFX_ERR(efx, "timed out waiting for SPI\n");
|
|
return -ETIMEDOUT;
|
|
return -ETIMEDOUT;
|
|
}
|
|
}
|
|
- cpu_relax();
|
|
|
|
|
|
+ schedule_timeout_uninterruptible(1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1643,8 +1656,8 @@ int falcon_spi_cmd(const struct efx_spi_device *spi,
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
BUG_ON(!mutex_is_locked(&efx->spi_lock));
|
|
BUG_ON(!mutex_is_locked(&efx->spi_lock));
|
|
|
|
|
|
- /* Check SPI not currently being accessed */
|
|
|
|
- rc = falcon_spi_wait(efx);
|
|
|
|
|
|
+ /* Check that previous command is not still running */
|
|
|
|
+ rc = falcon_spi_poll(efx);
|
|
if (rc)
|
|
if (rc)
|
|
return rc;
|
|
return rc;
|
|
|
|
|
|
@@ -1700,26 +1713,29 @@ efx_spi_munge_command(const struct efx_spi_device *spi,
|
|
return command | (((address >> 8) & spi->munge_address) << 3);
|
|
return command | (((address >> 8) & spi->munge_address) << 3);
|
|
}
|
|
}
|
|
|
|
|
|
-int falcon_spi_fast_wait(const struct efx_spi_device *spi)
|
|
|
|
|
|
+/* Wait up to 10 ms for buffered write completion */
|
|
|
|
+int falcon_spi_wait_write(const struct efx_spi_device *spi)
|
|
{
|
|
{
|
|
|
|
+ struct efx_nic *efx = spi->efx;
|
|
|
|
+ unsigned long timeout = jiffies + 1 + DIV_ROUND_UP(HZ, 100);
|
|
u8 status;
|
|
u8 status;
|
|
- int i, rc;
|
|
|
|
-
|
|
|
|
- /* Wait up to 1000us for flash/EEPROM to finish a fast operation. */
|
|
|
|
- for (i = 0; i < 50; i++) {
|
|
|
|
- udelay(20);
|
|
|
|
|
|
+ int rc;
|
|
|
|
|
|
|
|
+ for (;;) {
|
|
rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL,
|
|
rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL,
|
|
&status, sizeof(status));
|
|
&status, sizeof(status));
|
|
if (rc)
|
|
if (rc)
|
|
return rc;
|
|
return rc;
|
|
if (!(status & SPI_STATUS_NRDY))
|
|
if (!(status & SPI_STATUS_NRDY))
|
|
return 0;
|
|
return 0;
|
|
|
|
+ if (time_after_eq(jiffies, timeout)) {
|
|
|
|
+ EFX_ERR(efx, "SPI write timeout on device %d"
|
|
|
|
+ " last status=0x%02x\n",
|
|
|
|
+ spi->device_id, status);
|
|
|
|
+ return -ETIMEDOUT;
|
|
|
|
+ }
|
|
|
|
+ schedule_timeout_uninterruptible(1);
|
|
}
|
|
}
|
|
- EFX_ERR(spi->efx,
|
|
|
|
- "timed out waiting for device %d last status=0x%02x\n",
|
|
|
|
- spi->device_id, status);
|
|
|
|
- return -ETIMEDOUT;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
int falcon_spi_read(const struct efx_spi_device *spi, loff_t start,
|
|
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,
|
|
if (rc)
|
|
if (rc)
|
|
break;
|
|
break;
|
|
|
|
|
|
- rc = falcon_spi_fast_wait(spi);
|
|
|
|
|
|
+ rc = falcon_spi_wait_write(spi);
|
|
if (rc)
|
|
if (rc)
|
|
break;
|
|
break;
|
|
|
|
|