Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab029631 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 50e6f851 c1d926a5
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -7624,7 +7624,7 @@ F: drivers/clk/spear/
SPI SUBSYSTEM
SPI SUBSYSTEM
M:	Mark Brown <broonie@kernel.org>
M:	Mark Brown <broonie@kernel.org>
M:	Grant Likely <grant.likely@linaro.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
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git
Q:	http://patchwork.kernel.org/project/spi-devel-general/list/
Q:	http://patchwork.kernel.org/project/spi-devel-general/list/
S:	Maintained
S:	Maintained
+1 −1
Original line number Original line Diff line number Diff line
@@ -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)
		if ((mask & hspi_read(hspi, SPSR)) == val)
			return 0;
			return 0;


		msleep(20);
		udelay(10);
	}
	}


	dev_err(hspi->dev, "timeout\n");
	dev_err(hspi->dev, "timeout\n");
+2 −1
Original line number Original line Diff line number Diff line
@@ -1487,7 +1487,7 @@ static int pch_spi_pd_probe(struct platform_device *plat_dev)
	return 0;
	return 0;


err_spi_register_master:
err_spi_register_master:
	free_irq(board_dat->pdev->irq, board_dat);
	free_irq(board_dat->pdev->irq, data);
err_request_irq:
err_request_irq:
	pch_spi_free_resources(board_dat, data);
	pch_spi_free_resources(board_dat, data);
err_spi_get_resources:
err_spi_get_resources:
@@ -1667,6 +1667,7 @@ static int pch_spi_probe(struct pci_dev *pdev,
		pd_dev = platform_device_alloc("pch-spi", i);
		pd_dev = platform_device_alloc("pch-spi", i);
		if (!pd_dev) {
		if (!pd_dev) {
			dev_err(&pdev->dev, "platform_device_alloc failed\n");
			dev_err(&pdev->dev, "platform_device_alloc failed\n");
			retval = -ENOMEM;
			goto err_platform_device;
			goto err_platform_device;
		}
		}
		pd_dev_save->pd_save[i] = pd_dev;
		pd_dev_save->pd_save[i] = pd_dev;
+35 −39
Original line number Original line Diff line number Diff line
@@ -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);
	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
	u32 ipif_ier;
	u32 ipif_ier;
	u16 cr;


	/* We get here with transmitter inhibited */
	/* We get here with transmitter inhibited */


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


	xilinx_spi_fill_tx_fifo(xspi);


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


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


		wait_for_completion(&xspi->done);
		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);
		}

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

	/* Disable the transmit empty interrupt */
	/* Disable the transmit empty interrupt */
	xspi->write_fn(ipif_ier, xspi->regs + XIPIF_V123B_IIER_OFFSET);
	xspi->write_fn(ipif_ier, xspi->regs + XIPIF_V123B_IIER_OFFSET);


@@ -314,39 +341,8 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
	xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET);
	xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET);


	if (ipif_isr & XSPI_INTR_TX_EMPTY) {	/* Transmission completed */
	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;
	return IRQ_HANDLED;
}
}