···499499 }500500501501 /* div doesn't support odd number */502502- div = rs->max_freq / rs->speed;502502+ div = max_t(u32, rs->max_freq / rs->speed, 1);503503 div = (div + 1) & 0xfffe;504504505505 spi_enable_chip(rs, 0);···678678 rs->dma_tx.addr = (dma_addr_t)(mem->start + ROCKCHIP_SPI_TXDR);679679 rs->dma_rx.addr = (dma_addr_t)(mem->start + ROCKCHIP_SPI_RXDR);680680 rs->dma_tx.direction = DMA_MEM_TO_DEV;681681- rs->dma_tx.direction = DMA_DEV_TO_MEM;681681+ rs->dma_rx.direction = DMA_DEV_TO_MEM;682682683683 master->can_dma = rockchip_spi_can_dma;684684 master->dma_tx = rs->dma_tx.ch;
+58-36
drivers/spi/spi-rspi.c
···472472 dma_cookie_t cookie;473473 int ret;474474475475- if (tx) {476476- desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx,477477- tx->sgl, tx->nents, DMA_TO_DEVICE,478478- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);479479- if (!desc_tx)480480- goto no_dma;481481-482482- irq_mask |= SPCR_SPTIE;483483- }475475+ /* First prepare and submit the DMA request(s), as this may fail */484476 if (rx) {485477 desc_rx = dmaengine_prep_slave_sg(rspi->master->dma_rx,486478 rx->sgl, rx->nents, DMA_FROM_DEVICE,487479 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);488488- if (!desc_rx)489489- goto no_dma;480480+ if (!desc_rx) {481481+ ret = -EAGAIN;482482+ goto no_dma_rx;483483+ }484484+485485+ desc_rx->callback = rspi_dma_complete;486486+ desc_rx->callback_param = rspi;487487+ cookie = dmaengine_submit(desc_rx);488488+ if (dma_submit_error(cookie)) {489489+ ret = cookie;490490+ goto no_dma_rx;491491+ }490492491493 irq_mask |= SPCR_SPRIE;494494+ }495495+496496+ if (tx) {497497+ desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx,498498+ tx->sgl, tx->nents, DMA_TO_DEVICE,499499+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);500500+ if (!desc_tx) {501501+ ret = -EAGAIN;502502+ goto no_dma_tx;503503+ }504504+505505+ if (rx) {506506+ /* No callback */507507+ desc_tx->callback = NULL;508508+ } else {509509+ desc_tx->callback = rspi_dma_complete;510510+ desc_tx->callback_param = rspi;511511+ }512512+ cookie = dmaengine_submit(desc_tx);513513+ if (dma_submit_error(cookie)) {514514+ ret = cookie;515515+ goto no_dma_tx;516516+ }517517+518518+ irq_mask |= SPCR_SPTIE;492519 }493520494521 /*···530503 rspi_enable_irq(rspi, irq_mask);531504 rspi->dma_callbacked = 0;532505533533- if (rx) {534534- desc_rx->callback = rspi_dma_complete;535535- desc_rx->callback_param = rspi;536536- cookie = dmaengine_submit(desc_rx);537537- if (dma_submit_error(cookie))538538- return cookie;506506+ /* Now start DMA */507507+ if (rx)539508 dma_async_issue_pending(rspi->master->dma_rx);540540- }541541- if (tx) {542542- if (rx) {543543- /* No callback */544544- desc_tx->callback = NULL;545545- } else {546546- desc_tx->callback = rspi_dma_complete;547547- desc_tx->callback_param = rspi;548548- }549549- cookie = dmaengine_submit(desc_tx);550550- if (dma_submit_error(cookie))551551- return cookie;509509+ if (tx)552510 dma_async_issue_pending(rspi->master->dma_tx);553553- }554511555512 ret = wait_event_interruptible_timeout(rspi->wait,556513 rspi->dma_callbacked, HZ);557514 if (ret > 0 && rspi->dma_callbacked)558515 ret = 0;559559- else if (!ret)516516+ else if (!ret) {517517+ dev_err(&rspi->master->dev, "DMA timeout\n");560518 ret = -ETIMEDOUT;519519+ if (tx)520520+ dmaengine_terminate_all(rspi->master->dma_tx);521521+ if (rx)522522+ dmaengine_terminate_all(rspi->master->dma_rx);523523+ }561524562525 rspi_disable_irq(rspi, irq_mask);563526···558541559542 return ret;560543561561-no_dma:562562- pr_warn_once("%s %s: DMA not available, falling back to PIO\n",563563- dev_driver_string(&rspi->master->dev),564564- dev_name(&rspi->master->dev));565565- return -EAGAIN;544544+no_dma_tx:545545+ if (rx)546546+ dmaengine_terminate_all(rspi->master->dma_rx);547547+no_dma_rx:548548+ if (ret == -EAGAIN) {549549+ pr_warn_once("%s %s: DMA not available, falling back to PIO\n",550550+ dev_driver_string(&rspi->master->dev),551551+ dev_name(&rspi->master->dev));552552+ }553553+ return ret;566554}567555568556static void rspi_receive_init(const struct rspi_data *rspi)
+1
drivers/spi/spi.c
···848848849849/**850850 * spi_finalize_current_transfer - report completion of a transfer851851+ * @master: the master reporting completion851852 *852853 * Called by SPI drivers using the core transfer_one_message()853854 * implementation to notify it that the current interrupt driven
+7
include/linux/spi/spi.h
···253253 * the device whose settings are being modified.254254 * @transfer: adds a message to the controller's transfer queue.255255 * @cleanup: frees controller-specific state256256+ * @can_dma: determine whether this master supports DMA256257 * @queued: whether this master is providing an internal message queue257258 * @kworker: thread struct for message pump258259 * @kworker_task: pointer to task for message pump kworker thread···263262 * @cur_msg: the currently in-flight message264263 * @cur_msg_prepared: spi_prepare_message was called for the currently265264 * in-flight message265265+ * @cur_msg_mapped: message has been mapped for DMA266266 * @xfer_completion: used by core transfer_one_message()267267 * @busy: message pump is busy268268 * @running: message pump is running···301299 * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS302300 * number. Any individual value may be -ENOENT for CS lines that303301 * are not GPIOs (driven by the SPI controller itself).302302+ * @dma_tx: DMA transmit channel303303+ * @dma_rx: DMA receive channel304304+ * @dummy_rx: dummy receive buffer for full-duplex devices305305+ * @dummy_tx: dummy transmit buffer for full-duplex devices304306 *305307 * Each SPI master controller can communicate with one or more @spi_device306308 * children. These make a small bus, sharing MOSI, MISO and SCK signals···638632 * addresses for each transfer buffer639633 * @complete: called to report transaction completions640634 * @context: the argument to complete() when it's called635635+ * @frame_length: the total number of bytes in the message641636 * @actual_length: the total number of bytes that were transferred in all642637 * successful segments643638 * @status: zero for success, else negative errno