Skip to content

Commit

Permalink
Merge tag 'spi-v3.10-rc4' of git://git.kernel.org/pub/scm/linux/kerne…
Browse files Browse the repository at this point in the history
…l/git/broonie/spi

Pull spi fixes from Mark Brown:
 "A few nasty issues, particularly a race with the interrupt controller
  in the xilinx driver, together with a couple of more minor fixes and a
  much needed move of the mailing list away from sourceforge."

* tag 'spi-v3.10-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi:
  spi: hspi: fixup long delay time
  spi: spi-xilinx: Remove ISR race condition
  spi: topcliff-pch: fix error return code in pch_spi_probe()
  spi: topcliff-pch: Pass correct pointer to free_irq()
  spi: Move mailing list to vger
  • Loading branch information
Linus Torvalds committed Jun 10, 2013
2 parents 50e6f85 + c1d926a commit ab02963
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 42 deletions.
2 changes: 1 addition & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -7624,7 +7624,7 @@ F: drivers/clk/spear/
SPI SUBSYSTEM
M: Mark Brown <broonie@kernel.org>
M: Grant Likely <grant.likely@linaro.org>
L: spi-devel-general@lists.sourceforge.net
L: linux-spi@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git
Q: http://patchwork.kernel.org/project/spi-devel-general/list/
S: Maintained
Expand Down
2 changes: 1 addition & 1 deletion drivers/spi/spi-sh-hspi.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ static int hspi_status_check_timeout(struct hspi_priv *hspi, u32 mask, u32 val)
if ((mask & hspi_read(hspi, SPSR)) == val)
return 0;

msleep(20);
udelay(10);
}

dev_err(hspi->dev, "timeout\n");
Expand Down
3 changes: 2 additions & 1 deletion drivers/spi/spi-topcliff-pch.c
Original file line number Diff line number Diff line change
Expand Up @@ -1487,7 +1487,7 @@ static int pch_spi_pd_probe(struct platform_device *plat_dev)
return 0;

err_spi_register_master:
free_irq(board_dat->pdev->irq, board_dat);
free_irq(board_dat->pdev->irq, data);
err_request_irq:
pch_spi_free_resources(board_dat, data);
err_spi_get_resources:
Expand Down Expand Up @@ -1667,6 +1667,7 @@ static int pch_spi_probe(struct pci_dev *pdev,
pd_dev = platform_device_alloc("pch-spi", i);
if (!pd_dev) {
dev_err(&pdev->dev, "platform_device_alloc failed\n");
retval = -ENOMEM;
goto err_platform_device;
}
pd_dev_save->pd_save[i] = pd_dev;
Expand Down
74 changes: 35 additions & 39 deletions drivers/spi/spi-xilinx.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,6 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
{
struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
u32 ipif_ier;
u16 cr;

/* We get here with transmitter inhibited */

Expand All @@ -276,7 +275,6 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
xspi->remaining_bytes = t->len;
INIT_COMPLETION(xspi->done);

xilinx_spi_fill_tx_fifo(xspi);

/* Enable the transmit empty interrupt, which we use to determine
* progress on the transmission.
Expand All @@ -285,12 +283,41 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
xspi->write_fn(ipif_ier | XSPI_INTR_TX_EMPTY,
xspi->regs + XIPIF_V123B_IIER_OFFSET);

/* Start the transfer by not inhibiting the transmitter any longer */
cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) &
~XSPI_CR_TRANS_INHIBIT;
xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
for (;;) {
u16 cr;
u8 sr;

xilinx_spi_fill_tx_fifo(xspi);

/* Start the transfer by not inhibiting the transmitter any
* longer
*/
cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) &
~XSPI_CR_TRANS_INHIBIT;
xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);

wait_for_completion(&xspi->done);

/* A transmit has just completed. Process received data and
* check for more data to transmit. Always inhibit the
* transmitter while the Isr refills the transmit register/FIFO,
* or make sure it is stopped if we're done.
*/
cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
xspi->regs + XSPI_CR_OFFSET);

/* Read out all the data from the Rx FIFO */
sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) {
xspi->rx_fn(xspi);
sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
}

wait_for_completion(&xspi->done);
/* See if there is more data to send */
if (!xspi->remaining_bytes > 0)
break;
}

/* Disable the transmit empty interrupt */
xspi->write_fn(ipif_ier, xspi->regs + XIPIF_V123B_IIER_OFFSET);
Expand All @@ -314,38 +341,7 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET);

if (ipif_isr & XSPI_INTR_TX_EMPTY) { /* Transmission completed */
u16 cr;
u8 sr;

/* A transmit has just completed. Process received data and
* check for more data to transmit. Always inhibit the
* transmitter while the Isr refills the transmit register/FIFO,
* or make sure it is stopped if we're done.
*/
cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
xspi->regs + XSPI_CR_OFFSET);

/* Read out all the data from the Rx FIFO */
sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) {
xspi->rx_fn(xspi);
sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
}

/* See if there is more data to send */
if (xspi->remaining_bytes > 0) {
xilinx_spi_fill_tx_fifo(xspi);
/* Start the transfer by not inhibiting the
* transmitter any longer
*/
xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
} else {
/* No more data to send.
* Indicate the transfer is completed.
*/
complete(&xspi->done);
}
complete(&xspi->done);
}

return IRQ_HANDLED;
Expand Down

0 comments on commit ab02963

Please sign in to comment.