diff options
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r-- | drivers/spi/spi.c | 46 |
1 files changed, 26 insertions, 20 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 965dd8ac5939..63613a96233c 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -695,7 +695,7 @@ static void spi_pump_messages(struct kthread_work *work) | |||
695 | } | 695 | } |
696 | /* Extract head of queue */ | 696 | /* Extract head of queue */ |
697 | master->cur_msg = | 697 | master->cur_msg = |
698 | list_entry(master->queue.next, struct spi_message, queue); | 698 | list_first_entry(&master->queue, struct spi_message, queue); |
699 | 699 | ||
700 | list_del_init(&master->cur_msg->queue); | 700 | list_del_init(&master->cur_msg->queue); |
701 | if (master->busy) | 701 | if (master->busy) |
@@ -803,11 +803,8 @@ struct spi_message *spi_get_next_queued_message(struct spi_master *master) | |||
803 | 803 | ||
804 | /* get a pointer to the next message, if any */ | 804 | /* get a pointer to the next message, if any */ |
805 | spin_lock_irqsave(&master->queue_lock, flags); | 805 | spin_lock_irqsave(&master->queue_lock, flags); |
806 | if (list_empty(&master->queue)) | 806 | next = list_first_entry_or_null(&master->queue, struct spi_message, |
807 | next = NULL; | 807 | queue); |
808 | else | ||
809 | next = list_entry(master->queue.next, | ||
810 | struct spi_message, queue); | ||
811 | spin_unlock_irqrestore(&master->queue_lock, flags); | 808 | spin_unlock_irqrestore(&master->queue_lock, flags); |
812 | 809 | ||
813 | return next; | 810 | return next; |
@@ -1608,15 +1605,11 @@ int spi_setup(struct spi_device *spi) | |||
1608 | } | 1605 | } |
1609 | EXPORT_SYMBOL_GPL(spi_setup); | 1606 | EXPORT_SYMBOL_GPL(spi_setup); |
1610 | 1607 | ||
1611 | static int __spi_async(struct spi_device *spi, struct spi_message *message) | 1608 | static int __spi_validate(struct spi_device *spi, struct spi_message *message) |
1612 | { | 1609 | { |
1613 | struct spi_master *master = spi->master; | 1610 | struct spi_master *master = spi->master; |
1614 | struct spi_transfer *xfer; | 1611 | struct spi_transfer *xfer; |
1615 | 1612 | ||
1616 | message->spi = spi; | ||
1617 | |||
1618 | trace_spi_message_submit(message); | ||
1619 | |||
1620 | if (list_empty(&message->transfers)) | 1613 | if (list_empty(&message->transfers)) |
1621 | return -EINVAL; | 1614 | return -EINVAL; |
1622 | if (!message->complete) | 1615 | if (!message->complete) |
@@ -1679,9 +1672,8 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) | |||
1679 | if (xfer->rx_buf && !xfer->rx_nbits) | 1672 | if (xfer->rx_buf && !xfer->rx_nbits) |
1680 | xfer->rx_nbits = SPI_NBITS_SINGLE; | 1673 | xfer->rx_nbits = SPI_NBITS_SINGLE; |
1681 | /* check transfer tx/rx_nbits: | 1674 | /* check transfer tx/rx_nbits: |
1682 | * 1. keep the value is not out of single, dual and quad | 1675 | * 1. check the value matches one of single, dual and quad |
1683 | * 2. keep tx/rx_nbits is contained by mode in spi_device | 1676 | * 2. check tx/rx_nbits match the mode in spi_device |
1684 | * 3. if SPI_3WIRE, tx/rx_nbits should be in single | ||
1685 | */ | 1677 | */ |
1686 | if (xfer->tx_buf) { | 1678 | if (xfer->tx_buf) { |
1687 | if (xfer->tx_nbits != SPI_NBITS_SINGLE && | 1679 | if (xfer->tx_nbits != SPI_NBITS_SINGLE && |
@@ -1694,9 +1686,6 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) | |||
1694 | if ((xfer->tx_nbits == SPI_NBITS_QUAD) && | 1686 | if ((xfer->tx_nbits == SPI_NBITS_QUAD) && |
1695 | !(spi->mode & SPI_TX_QUAD)) | 1687 | !(spi->mode & SPI_TX_QUAD)) |
1696 | return -EINVAL; | 1688 | return -EINVAL; |
1697 | if ((spi->mode & SPI_3WIRE) && | ||
1698 | (xfer->tx_nbits != SPI_NBITS_SINGLE)) | ||
1699 | return -EINVAL; | ||
1700 | } | 1689 | } |
1701 | /* check transfer rx_nbits */ | 1690 | /* check transfer rx_nbits */ |
1702 | if (xfer->rx_buf) { | 1691 | if (xfer->rx_buf) { |
@@ -1710,13 +1699,22 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) | |||
1710 | if ((xfer->rx_nbits == SPI_NBITS_QUAD) && | 1699 | if ((xfer->rx_nbits == SPI_NBITS_QUAD) && |
1711 | !(spi->mode & SPI_RX_QUAD)) | 1700 | !(spi->mode & SPI_RX_QUAD)) |
1712 | return -EINVAL; | 1701 | return -EINVAL; |
1713 | if ((spi->mode & SPI_3WIRE) && | ||
1714 | (xfer->rx_nbits != SPI_NBITS_SINGLE)) | ||
1715 | return -EINVAL; | ||
1716 | } | 1702 | } |
1717 | } | 1703 | } |
1718 | 1704 | ||
1719 | message->status = -EINPROGRESS; | 1705 | message->status = -EINPROGRESS; |
1706 | |||
1707 | return 0; | ||
1708 | } | ||
1709 | |||
1710 | static int __spi_async(struct spi_device *spi, struct spi_message *message) | ||
1711 | { | ||
1712 | struct spi_master *master = spi->master; | ||
1713 | |||
1714 | message->spi = spi; | ||
1715 | |||
1716 | trace_spi_message_submit(message); | ||
1717 | |||
1720 | return master->transfer(spi, message); | 1718 | return master->transfer(spi, message); |
1721 | } | 1719 | } |
1722 | 1720 | ||
@@ -1755,6 +1753,10 @@ int spi_async(struct spi_device *spi, struct spi_message *message) | |||
1755 | int ret; | 1753 | int ret; |
1756 | unsigned long flags; | 1754 | unsigned long flags; |
1757 | 1755 | ||
1756 | ret = __spi_validate(spi, message); | ||
1757 | if (ret != 0) | ||
1758 | return ret; | ||
1759 | |||
1758 | spin_lock_irqsave(&master->bus_lock_spinlock, flags); | 1760 | spin_lock_irqsave(&master->bus_lock_spinlock, flags); |
1759 | 1761 | ||
1760 | if (master->bus_lock_flag) | 1762 | if (master->bus_lock_flag) |
@@ -1803,6 +1805,10 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message) | |||
1803 | int ret; | 1805 | int ret; |
1804 | unsigned long flags; | 1806 | unsigned long flags; |
1805 | 1807 | ||
1808 | ret = __spi_validate(spi, message); | ||
1809 | if (ret != 0) | ||
1810 | return ret; | ||
1811 | |||
1806 | spin_lock_irqsave(&master->bus_lock_spinlock, flags); | 1812 | spin_lock_irqsave(&master->bus_lock_spinlock, flags); |
1807 | 1813 | ||
1808 | ret = __spi_async(spi, message); | 1814 | ret = __spi_async(spi, message); |