Hikey Spi dma_map_single usage?


#1

Hi, I’m trying to use dma_map_single, but it failed.
I always get 0xffffffffffffffff when call dma_map_single.

Below is my code

void dmarw1(void) {
	int nIdx   = 0;
	int nCount = 0;
	int nRet   = 0;
	int nSendSize = 16384;

	char *txbuf;
	char *rxbuf;
	dma_addr_t txdma;
	dma_addr_t rxdma;

	struct spi_master *master = g_ghserial_spi_dev->master;
	struct device *dev = &master->dev;

	struct spi_transfer transfer;
	struct spi_message  msg;

	spi_message_init(&msg);

    // allocate memory by kmalloc.
	txbuf = (char *)kmalloc(nSendSize, GFP_KERNEL | GFP_DMA);
	rxbuf = (char *)kmalloc(nSendSize, GFP_KERNEL | GFP_DMA);

	if(!txbuf) {
		printk("txbuf NULL\n");
		return;
	}
	if(!rxbuf) {
		printk("rxbuf NULL\n");
		return;
	}

	for(nIdx = 0;nIdx < nSendSize;nIdx++) {
		txbuf[nIdx] = nCount;
		rxbuf[nIdx] = 0x00;
		nCount++;
		nCount = (nCount > 0xFF) ? 0 : nCount;
	}

	txbuf[nSendSize - 1] = 0x99;

    // dma_map_single to dma_addr_t, but it will return 0xffffffffffffffff.
	txdma = dma_map_single(dev, txbuf, nSendSize, DMA_TO_DEVICE);
	nRet = dma_mapping_error(dev, txdma);
	if(nRet) {
		printk("ret: %d, txdma mapping error..., txbuf: 0x%llx, txdma: 0x%llx\n", nRet, txbuf, txdma);
		goto handle_dma_mapping_error;
	}
	rxdma = dma_map_single(dev, rxbuf, nSendSize, DMA_FROM_DEVICE);
	nRet = dma_mapping_error(dev, rxdma);
	if(nRet) {
		printk("ret: %d, txdma mapping error..., rxbuf: 0x%llx, rxdma: 0x%llx\n", nRet, rxbuf, rxdma);
		goto handle_dma_mapping_error;
	}
	memset(&transfer, 0x00, sizeof(struct spi_transfer));

	transfer.tx_buf = txbuf;
	transfer.rx_buf = rxbuf;
	transfer.tx_dma = txdma;
	transfer.rx_dma = rxdma;
	transfer.len    = nSendSize;

	spi_message_add_tail(&transfer, &msg);
	msg.is_dma_mapped = 1;

	nRet = spi_sync(g_ghserial_spi_dev, &msg);
	printk("ret: %d, rx[0]: %d, rx[1]: %d, rx[2]: %d, rx[3]: %d\n", nRet, rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3]);

	dma_unmap_single(dev, txdma, nSendSize, DMA_TO_DEVICE);
	dma_unmap_single(dev, rxdma, nSendSize, DMA_TO_DEVICE);

handle_dma_mapping_error:
	kfree(txbuf);
	kfree(rxbuf);
}


#2

So here means txdma equals 0xfffffffffffffff? What’s the value for nRet?

I checked a bit for function dma_map_single(), for most failure case, it returns back 0.


#3

Thanks for your reply.

dma_map_single should return a value as dma handle(dma_addr_t), neither 0xffffffffffffffff nor zero.

When called dma_map_single, we should call dma_mapping_error to check, and I get failure value as 1.
In dma_mapping_error, if it equals 0xffffffffffffffff, it will treat as fail, then return 1.