Merge remote-tracking branches 'spi/topic/s3c64xx', 'spi/topic/sg', 'spi/topic/sh...
[cascardo/linux.git] / drivers / spi / spi.c
index 07476ca..3abb390 100644 (file)
@@ -609,21 +609,30 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
                       enum dma_data_direction dir)
 {
        const bool vmalloced_buf = is_vmalloc_addr(buf);
-       const int desc_len = vmalloced_buf ? PAGE_SIZE : master->max_dma_len;
-       const int sgs = DIV_ROUND_UP(len, desc_len);
+       int desc_len;
+       int sgs;
        struct page *vm_page;
        void *sg_buf;
        size_t min;
        int i, ret;
 
+       if (vmalloced_buf) {
+               desc_len = PAGE_SIZE;
+               sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len);
+       } else {
+               desc_len = master->max_dma_len;
+               sgs = DIV_ROUND_UP(len, desc_len);
+       }
+
        ret = sg_alloc_table(sgt, sgs, GFP_KERNEL);
        if (ret != 0)
                return ret;
 
        for (i = 0; i < sgs; i++) {
-               min = min_t(size_t, len, desc_len);
 
                if (vmalloced_buf) {
+                       min = min_t(size_t,
+                                   len, desc_len - offset_in_page(buf));
                        vm_page = vmalloc_to_page(buf);
                        if (!vm_page) {
                                sg_free_table(sgt);
@@ -632,6 +641,7 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
                        sg_set_page(&sgt->sgl[i], vm_page,
                                    min, offset_in_page(buf));
                } else {
+                       min = min_t(size_t, len, desc_len);
                        sg_buf = buf;
                        sg_set_buf(&sgt->sgl[i], sg_buf, min);
                }
@@ -672,8 +682,15 @@ static int __spi_map_msg(struct spi_master *master, struct spi_message *msg)
        if (!master->can_dma)
                return 0;
 
-       tx_dev = master->dma_tx->device->dev;
-       rx_dev = master->dma_rx->device->dev;
+       if (master->dma_tx)
+               tx_dev = master->dma_tx->device->dev;
+       else
+               tx_dev = &master->dev;
+
+       if (master->dma_rx)
+               rx_dev = master->dma_rx->device->dev;
+       else
+               rx_dev = &master->dev;
 
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
                if (!master->can_dma(master, msg->spi, xfer))
@@ -712,8 +729,15 @@ static int __spi_unmap_msg(struct spi_master *master, struct spi_message *msg)
        if (!master->cur_msg_mapped || !master->can_dma)
                return 0;
 
-       tx_dev = master->dma_tx->device->dev;
-       rx_dev = master->dma_rx->device->dev;
+       if (master->dma_tx)
+               tx_dev = master->dma_tx->device->dev;
+       else
+               tx_dev = &master->dev;
+
+       if (master->dma_rx)
+               rx_dev = master->dma_rx->device->dev;
+       else
+               rx_dev = &master->dev;
 
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
                if (!master->can_dma(master, msg->spi, xfer))
@@ -1891,6 +1915,20 @@ EXPORT_SYMBOL_GPL(spi_busnum_to_master);
  * other core methods are currently defined as inline functions.
  */
 
+static int __spi_validate_bits_per_word(struct spi_master *master, u8 bits_per_word)
+{
+       if (master->bits_per_word_mask) {
+               /* Only 32 bits fit in the mask */
+               if (bits_per_word > 32)
+                       return -EINVAL;
+               if (!(master->bits_per_word_mask &
+                               SPI_BPW_MASK(bits_per_word)))
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
 /**
  * spi_setup - setup SPI mode and clock rate
  * @spi: the device whose settings are being modified
@@ -1949,6 +1987,9 @@ int spi_setup(struct spi_device *spi)
        if (!spi->bits_per_word)
                spi->bits_per_word = 8;
 
+       if (__spi_validate_bits_per_word(spi->master, spi->bits_per_word))
+               return -EINVAL;
+
        if (!spi->max_speed_hz)
                spi->max_speed_hz = spi->master->max_speed_hz;
 
@@ -2011,19 +2052,15 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
 
                if (!xfer->speed_hz)
                        xfer->speed_hz = spi->max_speed_hz;
+               if (!xfer->speed_hz)
+                       xfer->speed_hz = master->max_speed_hz;
 
                if (master->max_speed_hz &&
                    xfer->speed_hz > master->max_speed_hz)
                        xfer->speed_hz = master->max_speed_hz;
 
-               if (master->bits_per_word_mask) {
-                       /* Only 32 bits fit in the mask */
-                       if (xfer->bits_per_word > 32)
-                               return -EINVAL;
-                       if (!(master->bits_per_word_mask &
-                                       BIT(xfer->bits_per_word - 1)))
-                               return -EINVAL;
-               }
+               if (__spi_validate_bits_per_word(master, xfer->bits_per_word))
+                       return -EINVAL;
 
                /*
                 * SPI transfer length should be multiple of SPI word size