static void xgbe_free_ring(struct xgbe_prv_data *pdata, struct xgbe_ring *ring) { struct xgbe_ring_data *rdata; unsigned int i; if (!ring) return; if (ring->rdata) { for (i = 0; i < ring->rdesc_count; i++) { rdata = XGBE_GET_DESC_DATA(ring, i); xgbe_unmap_skb(pdata, rdata); } kfree(ring->rdata); ring->rdata = NULL; } if (ring->rdesc) { dma_free_coherent(pdata->dev, (sizeof(struct xgbe_ring_desc) * ring->rdesc_count), ring->rdesc, ring->rdesc_dma); ring->rdesc = NULL; } }
static void xgbe_wrapper_rx_descriptor_init(struct xgbe_prv_data *pdata) { struct xgbe_hw_if *hw_if = &pdata->hw_if; struct xgbe_channel *channel; struct xgbe_ring *ring; struct xgbe_ring_desc *rdesc; struct xgbe_ring_data *rdata; dma_addr_t rdesc_dma, skb_dma; struct sk_buff *skb = NULL; unsigned int i, j; DBGPR("-->xgbe_wrapper_rx_descriptor_init\n"); channel = pdata->channel; for (i = 0; i < pdata->channel_count; i++, channel++) { ring = channel->rx_ring; if (!ring) break; rdesc = ring->rdesc; rdesc_dma = ring->rdesc_dma; for (j = 0; j < ring->rdesc_count; j++) { rdata = XGBE_GET_DESC_DATA(ring, j); rdata->rdesc = rdesc; rdata->rdesc_dma = rdesc_dma; /* Allocate skb & assign to each rdesc */ skb = dev_alloc_skb(pdata->rx_buf_size); if (skb == NULL) break; skb_dma = dma_map_single(pdata->dev, skb->data, pdata->rx_buf_size, DMA_FROM_DEVICE); if (dma_mapping_error(pdata->dev, skb_dma)) { netdev_alert(pdata->netdev, "failed to do the dma map\n"); dev_kfree_skb_any(skb); break; } rdata->skb = skb; rdata->skb_dma = skb_dma; rdata->skb_dma_len = pdata->rx_buf_size; rdesc++; rdesc_dma += sizeof(struct xgbe_ring_desc); } ring->cur = 0; ring->dirty = 0; ring->rx.realloc_index = 0; ring->rx.realloc_threshold = 0; hw_if->rx_desc_init(channel); } DBGPR("<--xgbe_wrapper_rx_descriptor_init\n"); }
static void xgbe_free_ring(struct xgbe_prv_data *pdata, struct xgbe_ring *ring) { struct xgbe_ring_data *rdata; unsigned int i; if (!ring) return; if (ring->rdata) { for (i = 0; i < ring->rdesc_count; i++) { rdata = XGBE_GET_DESC_DATA(ring, i); xgbe_unmap_rdata(pdata, rdata); } kfree(ring->rdata); ring->rdata = NULL; } if (ring->rx_hdr_pa.pages) { dma_unmap_page(pdata->dev, ring->rx_hdr_pa.pages_dma, ring->rx_hdr_pa.pages_len, DMA_FROM_DEVICE); put_page(ring->rx_hdr_pa.pages); ring->rx_hdr_pa.pages = NULL; ring->rx_hdr_pa.pages_len = 0; ring->rx_hdr_pa.pages_offset = 0; ring->rx_hdr_pa.pages_dma = 0; } if (ring->rx_buf_pa.pages) { dma_unmap_page(pdata->dev, ring->rx_buf_pa.pages_dma, ring->rx_buf_pa.pages_len, DMA_FROM_DEVICE); put_page(ring->rx_buf_pa.pages); ring->rx_buf_pa.pages = NULL; ring->rx_buf_pa.pages_len = 0; ring->rx_buf_pa.pages_offset = 0; ring->rx_buf_pa.pages_dma = 0; } if (ring->rdesc) { dma_free_coherent(pdata->dev, (sizeof(struct xgbe_ring_desc) * ring->rdesc_count), ring->rdesc, ring->rdesc_dma); ring->rdesc = NULL; } }
static void xgbe_realloc_skb(struct xgbe_channel *channel) { struct xgbe_prv_data *pdata = channel->pdata; struct xgbe_hw_if *hw_if = &pdata->hw_if; struct xgbe_ring *ring = channel->rx_ring; struct xgbe_ring_data *rdata; struct sk_buff *skb = NULL; dma_addr_t skb_dma; int i; DBGPR("-->xgbe_realloc_skb: rx_ring->rx.realloc_index = %u\n", ring->rx.realloc_index); for (i = 0; i < ring->dirty; i++) { rdata = XGBE_GET_DESC_DATA(ring, ring->rx.realloc_index); /* Reset rdata values */ xgbe_unmap_skb(pdata, rdata); /* Allocate skb & assign to each rdesc */ skb = dev_alloc_skb(pdata->rx_buf_size); if (skb == NULL) break; skb_dma = dma_map_single(pdata->dev, skb->data, pdata->rx_buf_size, DMA_FROM_DEVICE); if (dma_mapping_error(pdata->dev, skb_dma)) { netdev_alert(pdata->netdev, "failed to do the dma map\n"); dev_kfree_skb_any(skb); break; } rdata->skb = skb; rdata->skb_dma = skb_dma; rdata->skb_dma_len = pdata->rx_buf_size; hw_if->rx_desc_reset(rdata); ring->rx.realloc_index++; } ring->dirty = 0; DBGPR("<--xgbe_realloc_skb\n"); }
static void xgbe_wrapper_tx_descriptor_init(struct xgbe_prv_data *pdata) { struct xgbe_hw_if *hw_if = &pdata->hw_if; struct xgbe_channel *channel; struct xgbe_ring *ring; struct xgbe_ring_data *rdata; struct xgbe_ring_desc *rdesc; dma_addr_t rdesc_dma; unsigned int i, j; DBGPR("-->xgbe_wrapper_tx_descriptor_init\n"); channel = pdata->channel; for (i = 0; i < pdata->channel_count; i++, channel++) { ring = channel->tx_ring; if (!ring) break; rdesc = ring->rdesc; rdesc_dma = ring->rdesc_dma; for (j = 0; j < ring->rdesc_count; j++) { rdata = XGBE_GET_DESC_DATA(ring, j); rdata->rdesc = rdesc; rdata->rdesc_dma = rdesc_dma; rdesc++; rdesc_dma += sizeof(struct xgbe_ring_desc); } ring->cur = 0; ring->dirty = 0; ring->tx.queue_stopped = 0; hw_if->tx_desc_init(channel); } DBGPR("<--xgbe_wrapper_tx_descriptor_init\n"); }
static int xgbe_map_tx_skb(struct xgbe_channel *channel, struct sk_buff *skb) { struct xgbe_prv_data *pdata = channel->pdata; struct xgbe_ring *ring = channel->tx_ring; struct xgbe_ring_data *rdata; struct xgbe_packet_data *packet; struct skb_frag_struct *frag; dma_addr_t skb_dma; unsigned int start_index, cur_index; unsigned int offset, tso, vlan, datalen, len; unsigned int i; DBGPR("-->xgbe_map_tx_skb: cur = %d\n", ring->cur); offset = 0; start_index = ring->cur; cur_index = ring->cur; packet = &ring->packet_data; packet->rdesc_count = 0; packet->length = 0; tso = XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, TSO_ENABLE); vlan = XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, VLAN_CTAG); /* Save space for a context descriptor if needed */ if ((tso && (packet->mss != ring->tx.cur_mss)) || (vlan && (packet->vlan_ctag != ring->tx.cur_vlan_ctag))) cur_index++; rdata = XGBE_GET_DESC_DATA(ring, cur_index); if (tso) { DBGPR(" TSO packet\n"); /* Map the TSO header */ skb_dma = dma_map_single(pdata->dev, skb->data, packet->header_len, DMA_TO_DEVICE); if (dma_mapping_error(pdata->dev, skb_dma)) { netdev_alert(pdata->netdev, "dma_map_single failed\n"); goto err_out; } rdata->skb_dma = skb_dma; rdata->skb_dma_len = packet->header_len; rdata->tso_header = 1; offset = packet->header_len; packet->length += packet->header_len; cur_index++; rdata = XGBE_GET_DESC_DATA(ring, cur_index); } /* Map the (remainder of the) packet */ for (datalen = skb_headlen(skb) - offset; datalen; ) { len = min_t(unsigned int, datalen, XGBE_TX_MAX_BUF_SIZE); skb_dma = dma_map_single(pdata->dev, skb->data + offset, len, DMA_TO_DEVICE); if (dma_mapping_error(pdata->dev, skb_dma)) { netdev_alert(pdata->netdev, "dma_map_single failed\n"); goto err_out; } rdata->skb_dma = skb_dma; rdata->skb_dma_len = len; DBGPR(" skb data: index=%u, dma=0x%llx, len=%u\n", cur_index, skb_dma, len); datalen -= len; offset += len; packet->length += len; cur_index++; rdata = XGBE_GET_DESC_DATA(ring, cur_index); } for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { DBGPR(" mapping frag %u\n", i); frag = &skb_shinfo(skb)->frags[i]; offset = 0; for (datalen = skb_frag_size(frag); datalen; ) { len = min_t(unsigned int, datalen, XGBE_TX_MAX_BUF_SIZE); skb_dma = skb_frag_dma_map(pdata->dev, frag, offset, len, DMA_TO_DEVICE); if (dma_mapping_error(pdata->dev, skb_dma)) { netdev_alert(pdata->netdev, "skb_frag_dma_map failed\n"); goto err_out; } rdata->skb_dma = skb_dma; rdata->skb_dma_len = len; rdata->mapped_as_page = 1; DBGPR(" skb data: index=%u, dma=0x%llx, len=%u\n", cur_index, skb_dma, len); datalen -= len; offset += len; packet->length += len; cur_index++; rdata = XGBE_GET_DESC_DATA(ring, cur_index); } } /* Save the skb address in the last entry */ rdata->skb = skb; /* Save the number of descriptor entries used */ packet->rdesc_count = cur_index - start_index; DBGPR("<--xgbe_map_tx_skb: count=%u\n", packet->rdesc_count); return packet->rdesc_count; err_out: while (start_index < cur_index) { rdata = XGBE_GET_DESC_DATA(ring, start_index++); xgbe_unmap_skb(pdata, rdata); } DBGPR("<--xgbe_map_tx_skb: count=0\n"); return 0; }