in bcm-pdc-mailbox.c [706:774]
static int pdc_tx_list_sg_add(struct pdc_state *pdcs, struct scatterlist *sg)
{
u32 flags = 0;
u32 eot;
u32 tx_avail;
/*
* Num descriptors needed. Conservatively assume we need a descriptor
* for every entry in sg.
*/
u32 num_desc;
u32 desc_w = 0; /* Number of tx descriptors written */
u32 bufcnt; /* Number of bytes of buffer pointed to by descriptor */
dma_addr_t databufptr; /* DMA address to put in descriptor */
num_desc = (u32)sg_nents(sg);
/* check whether enough tx descriptors are available */
tx_avail = pdcs->ntxpost - NTXDACTIVE(pdcs->txin, pdcs->txout,
pdcs->ntxpost);
if (unlikely(num_desc > tx_avail)) {
pdcs->txnobuf++;
return -ENOSPC;
}
/* build tx descriptors */
if (pdcs->tx_msg_start == pdcs->txout) {
/* Start of frame */
pdcs->txin_numd[pdcs->tx_msg_start] = 0;
pdcs->src_sg[pdcs->txout] = sg;
flags = D64_CTRL1_SOF;
}
while (sg) {
if (unlikely(pdcs->txout == (pdcs->ntxd - 1)))
eot = D64_CTRL1_EOT;
else
eot = 0;
/*
* If sg buffer larger than PDC limit, split across
* multiple descriptors
*/
bufcnt = sg_dma_len(sg);
databufptr = sg_dma_address(sg);
while (bufcnt > PDC_DMA_BUF_MAX) {
pdc_build_txd(pdcs, databufptr, PDC_DMA_BUF_MAX,
flags | eot);
desc_w++;
bufcnt -= PDC_DMA_BUF_MAX;
databufptr += PDC_DMA_BUF_MAX;
if (unlikely(pdcs->txout == (pdcs->ntxd - 1)))
eot = D64_CTRL1_EOT;
else
eot = 0;
}
sg = sg_next(sg);
if (!sg)
/* Writing last descriptor for frame */
flags |= (D64_CTRL1_EOF | D64_CTRL1_IOC);
pdc_build_txd(pdcs, databufptr, bufcnt, flags | eot);
desc_w++;
/* Clear start of frame after first descriptor */
flags &= ~D64_CTRL1_SOF;
}
pdcs->txin_numd[pdcs->tx_msg_start] += desc_w;
return PDC_SUCCESS;
}