int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data, int len, int directed) { struct cpdma_ctlr *ctlr = chan->ctlr; struct cpdma_desc __iomem *desc; dma_addr_t buffer; unsigned long flags; u32 mode; int ret = 0; spin_lock_irqsave(&chan->lock, flags); if (chan->state == CPDMA_STATE_TEARDOWN) { ret = -EINVAL; goto unlock_ret; } desc = cpdma_desc_alloc(ctlr->pool, 1, is_rx_chan(chan)); if (!desc) { chan->stats.desc_alloc_fail++; ret = -ENOMEM; goto unlock_ret; } if (len < ctlr->params.min_packet_size) { len = ctlr->params.min_packet_size; chan->stats.runt_transmit_buff++; } buffer = dma_map_single(ctlr->dev, data, len, chan->dir); ret = dma_mapping_error(ctlr->dev, buffer); if (ret) { cpdma_desc_free(ctlr->pool, desc, 1); ret = -EINVAL; goto unlock_ret; } mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP; cpdma_desc_to_port(chan, mode, directed); desc_write(desc, hw_next, 0); desc_write(desc, hw_buffer, buffer); desc_write(desc, hw_len, len); desc_write(desc, hw_mode, mode | len); desc_write(desc, sw_token, token); desc_write(desc, sw_buffer, buffer); desc_write(desc, sw_len, len); __cpdma_chan_submit(chan, desc); if (chan->state == CPDMA_STATE_ACTIVE && chan->rxfree) chan_write(chan, rxfree, 1); chan->count++; unlock_ret: spin_unlock_irqrestore(&chan->lock, flags); return ret; }
int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data, int len, gfp_t gfp_mask) { struct cpdma_ctlr *ctlr = chan->ctlr; struct cpdma_desc __iomem *desc; dma_addr_t buffer; rtdm_lockctx_t context; u32 mode; int ret = 0; rtdm_lock_get_irqsave(&chan->lock, context); if (chan->state == CPDMA_STATE_TEARDOWN) { ret = -EINVAL; goto unlock_ret; } desc = cpdma_desc_alloc(ctlr->pool, 1); if (!desc) { chan->stats.desc_alloc_fail++; ret = -ENOMEM; goto unlock_ret; } if (len < ctlr->params.min_packet_size) { len = ctlr->params.min_packet_size; chan->stats.runt_transmit_buff++; } buffer = dma_map_single(ctlr->dev, data, len, chan->dir); mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP; desc_write(desc, hw_next, 0); desc_write(desc, hw_buffer, buffer); desc_write(desc, hw_len, len); desc_write(desc, hw_mode, mode | len); desc_write(desc, sw_token, token); desc_write(desc, sw_buffer, buffer); desc_write(desc, sw_len, len); __cpdma_chan_submit(chan, desc); if (chan->state == CPDMA_STATE_ACTIVE && chan->rxfree) chan_write(chan, rxfree, 1); chan->count++; unlock_ret: rtdm_lock_put_irqrestore(&chan->lock, context); return ret; }