From patchwork Sat Apr 13 00:25:07 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tony Lindgren X-Patchwork-Id: 2439961 Return-Path: X-Original-To: patchwork-spi-devel-general@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from lists.sourceforge.net (lists.sourceforge.net [216.34.181.88]) by patchwork2.kernel.org (Postfix) with ESMTP id F234CDF2A1 for ; Sat, 13 Apr 2013 01:28:55 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=sfs-ml-3.v29.ch3.sourceforge.com) by sfs-ml-3.v29.ch3.sourceforge.com with esmtp (Exim 4.76) (envelope-from ) id 1UQpGw-0005xH-55; Sat, 13 Apr 2013 01:28:54 +0000 Received: from sog-mx-2.v43.ch3.sourceforge.com ([172.29.43.192] helo=mx.sourceforge.net) by sfs-ml-3.v29.ch3.sourceforge.com with esmtp (Exim 4.76) (envelope-from ) id 1UQpGt-0005xB-VO for spi-devel-general@lists.sourceforge.net; Sat, 13 Apr 2013 01:28:52 +0000 X-ACL-Warn: Received: from mho-02-ewr.mailhop.org ([204.13.248.72]) by sog-mx-2.v43.ch3.sourceforge.com with esmtps (TLSv1:AES256-SHA:256) (Exim 4.76) id 1UQpGs-0004A2-Q5 for spi-devel-general@lists.sourceforge.net; Sat, 13 Apr 2013 01:28:51 +0000 Received: from c-50-131-214-131.hsd1.ca.comcast.net ([50.131.214.131] helo=localhost.localdomain) by mho-02-ewr.mailhop.org with esmtpa (Exim 4.72) (envelope-from ) id 1UQoHF-000D2F-ES; Sat, 13 Apr 2013 00:25:09 +0000 Received: from Mutt by mutt-smtp-wrapper.pl 1.2 (www.zdo.com/articles/mutt-smtp-wrapper.shtml) X-Mail-Handler: Dyn Standard SMTP by Dyn X-Originating-IP: 50.131.214.131 X-Report-Abuse-To: abuse@dyndns.com (see http://www.dyndns.com/services/sendlabs/outbound_abuse.html for abuse reporting information) X-MHO-User: U2FsdGVkX1/zYfgamX2dJhMm64xW4Yix Date: Fri, 12 Apr 2013 17:25:07 -0700 From: Tony Lindgren To: Grant Likely , Mark Brown Subject: [PATCH] spi: omap2-mcspi: Fix transfers if DMADEVICES is not set Message-ID: <20130413002506.GG10155@atomide.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-06-14) X-Spam-Score: 0.0 (/) X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [204.13.248.72 listed in list.dnswl.org] 0.0 UNPARSEABLE_RELAY Informational: message has unparseable relay lines X-Headers-End: 1UQpGs-0004A2-Q5 Cc: spi-devel-general@lists.sourceforge.net, linux-omap@vger.kernel.org, Jon Hunter X-BeenThere: spi-devel-general@lists.sourceforge.net X-Mailman-Version: 2.1.9 Precedence: list List-Id: Linux SPI core/device drivers discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: spi-devel-general-bounces@lists.sourceforge.net Selecting CONFIG_DMADEVICES is optional, and we must be able to continue even without DMA. Otherwise things like omap4430sdp nfsroot will fail if DMA is not selected. Note that the driver already supports PIO mode, but we fail to fall back to PIO if requesting DMA channels fails. Signed-off-by: Tony Lindgren --- Does this look OK to get in for v3.10? There should not be any urgent need for this for v3.9-rc. ------------------------------------------------------------------------------ Precog is a next-generation analytics platform capable of advanced analytics on semi-structured data. The platform includes APIs for building apps and a phenomenal toolset for data science. Developers can use our toolset for easy data analysis & visualization. Get a free account! http://www2.precog.com/precogplatform/slashdotnewsletter --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -809,6 +809,10 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, return 0; } +/* + * Note that we currently allow DMA only if we get a channel + * for both rx and tx. Otherwise we'll do PIO for both rx and tx. + */ static int omap2_mcspi_request_dma(struct spi_device *spi) { struct spi_master *master = spi->master; @@ -827,21 +831,22 @@ static int omap2_mcspi_request_dma(struct spi_device *spi) dma_cap_set(DMA_SLAVE, mask); sig = mcspi_dma->dma_rx_sync_dev; mcspi_dma->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig); - if (!mcspi_dma->dma_rx) { - dev_err(&spi->dev, "no RX DMA engine channel for McSPI\n"); - return -EAGAIN; - } + if (!mcspi_dma->dma_rx) + goto no_dma; sig = mcspi_dma->dma_tx_sync_dev; mcspi_dma->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig); if (!mcspi_dma->dma_tx) { - dev_err(&spi->dev, "no TX DMA engine channel for McSPI\n"); dma_release_channel(mcspi_dma->dma_rx); mcspi_dma->dma_rx = NULL; - return -EAGAIN; + goto no_dma; } return 0; + +no_dma: + dev_warn(&spi->dev, "not using DMA for McSPI\n"); + return -EAGAIN; } static int omap2_mcspi_setup(struct spi_device *spi) @@ -874,7 +879,7 @@ static int omap2_mcspi_setup(struct spi_device *spi) if (!mcspi_dma->dma_rx || !mcspi_dma->dma_tx) { ret = omap2_mcspi_request_dma(spi); - if (ret < 0) + if (ret < 0 && ret != -EAGAIN) return ret; } @@ -932,6 +937,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) struct spi_device *spi; struct spi_transfer *t = NULL; struct spi_master *master; + struct omap2_mcspi_dma *mcspi_dma; int cs_active = 0; struct omap2_mcspi_cs *cs; struct omap2_mcspi_device_config *cd; @@ -941,6 +947,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) spi = m->spi; master = spi->master; + mcspi_dma = mcspi->dma_channels + spi->chip_select; cs = spi->controller_state; cd = spi->controller_data; @@ -997,7 +1004,8 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) __raw_writel(0, cs->base + OMAP2_MCSPI_TX0); - if (m->is_dma_mapped || t->len >= DMA_MIN_BYTES) + if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) && + (m->is_dma_mapped || t->len >= DMA_MIN_BYTES)) count = omap2_mcspi_txrx_dma(spi, t); else count = omap2_mcspi_txrx_pio(spi, t); @@ -1044,10 +1052,14 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) static int omap2_mcspi_transfer_one_message(struct spi_master *master, struct spi_message *m) { + struct spi_device *spi; struct omap2_mcspi *mcspi; + struct omap2_mcspi_dma *mcspi_dma; struct spi_transfer *t; + spi = m->spi; mcspi = spi_master_get_devdata(master); + mcspi_dma = mcspi->dma_channels + spi->chip_select; m->actual_length = 0; m->status = 0; @@ -1082,7 +1094,7 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master, if (m->is_dma_mapped || len < DMA_MIN_BYTES) continue; - if (tx_buf != NULL) { + if (mcspi_dma->dma_tx && tx_buf != NULL) { t->tx_dma = dma_map_single(mcspi->dev, (void *) tx_buf, len, DMA_TO_DEVICE); if (dma_mapping_error(mcspi->dev, t->tx_dma)) { @@ -1091,7 +1103,7 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master, return -EINVAL; } } - if (rx_buf != NULL) { + if (mcspi_dma->dma_rx && rx_buf != NULL) { t->rx_dma = dma_map_single(mcspi->dev, rx_buf, t->len, DMA_FROM_DEVICE); if (dma_mapping_error(mcspi->dev, t->rx_dma)) {