diff options
Diffstat (limited to 'drivers/spi')
| -rw-r--r-- | drivers/spi/spi-bcm63xx-hsspi.c | 8 | ||||
| -rw-r--r-- | drivers/spi/spi-bcm63xx.c | 6 | ||||
| -rw-r--r-- | drivers/spi/spi-bcmbca-hsspi.c | 8 | ||||
| -rw-r--r-- | drivers/spi/spi.c | 34 |
4 files changed, 37 insertions, 19 deletions
diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index 18261cbd413b..b8bf8b5be2cf 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -921,7 +921,13 @@ static int bcm63xx_hsspi_resume(struct device *dev) } } - spi_controller_resume(host); + ret = spi_controller_resume(host); + if (ret) { + if (bs->pll_clk) + clk_disable_unprepare(bs->pll_clk); + clk_disable_unprepare(bs->clk); + return ret; + } return 0; } diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index cf7eefd39839..8d152e906daa 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -661,7 +661,11 @@ static int bcm63xx_spi_resume(struct device *dev) if (ret) return ret; - spi_controller_resume(host); + ret = spi_controller_resume(host); + if (ret) { + clk_disable_unprepare(bs->clk); + return ret; + } return 0; } diff --git a/drivers/spi/spi-bcmbca-hsspi.c b/drivers/spi/spi-bcmbca-hsspi.c index f0f0e6b29668..a1ff33f6dc09 100644 --- a/drivers/spi/spi-bcmbca-hsspi.c +++ b/drivers/spi/spi-bcmbca-hsspi.c @@ -612,7 +612,13 @@ static int bcmbca_hsspi_resume(struct device *dev) } } - spi_controller_resume(host); + ret = spi_controller_resume(host); + if (ret) { + if (bs->pll_clk) + clk_disable_unprepare(bs->pll_clk); + clk_disable_unprepare(bs->clk); + return ret; + } return 0; } diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 6ea9ac2931cd..6900514e7329 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1216,6 +1216,8 @@ void spi_unmap_buf(struct spi_controller *ctlr, struct device *dev, spi_unmap_buf_attrs(ctlr, dev, sgt, dir, 0); } +static int __spi_unmap_msg(struct spi_controller *ctlr, struct spi_message *msg); + static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg) { struct device *tx_dev, *rx_dev; @@ -1239,7 +1241,13 @@ static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg) else rx_dev = ctlr->dev.parent; - ret = -ENOMSG; + /* + * Store the devices before mapping so partial failures can be unwound + * with the device that created each mapping. + */ + ctlr->cur_tx_dma_dev = tx_dev; + ctlr->cur_rx_dma_dev = rx_dev; + list_for_each_entry(xfer, &msg->transfers, transfer_list) { /* The sync is done before each transfer. */ unsigned long attrs = DMA_ATTR_SKIP_CPU_SYNC; @@ -1252,8 +1260,8 @@ static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg) (void *)xfer->tx_buf, xfer->len, DMA_TO_DEVICE, attrs); - if (ret != 0) - return ret; + if (ret) + goto unwind; xfer->tx_sg_mapped = true; } @@ -1262,25 +1270,19 @@ static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg) ret = spi_map_buf_attrs(ctlr, rx_dev, &xfer->rx_sg, xfer->rx_buf, xfer->len, DMA_FROM_DEVICE, attrs); - if (ret != 0) { - spi_unmap_buf_attrs(ctlr, tx_dev, - &xfer->tx_sg, DMA_TO_DEVICE, - attrs); - - return ret; - } + if (ret) + goto unwind; xfer->rx_sg_mapped = true; } } - /* No transfer has been mapped, bail out with success */ - if (ret) - return 0; - - ctlr->cur_rx_dma_dev = rx_dev; - ctlr->cur_tx_dma_dev = tx_dev; return 0; + +unwind: + __spi_unmap_msg(ctlr, msg); + + return ret; } static int __spi_unmap_msg(struct spi_controller *ctlr, struct spi_message *msg) |
