struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv, struct mlx4_en_rx_desc *rx_desc, struct skb_frag_struct *skb_frags, struct mlx4_en_rx_alloc *page_alloc, unsigned int length) { struct mlx4_en_dev *mdev = priv->mdev; struct sk_buff *skb; void *va; int used_frags; dma_addr_t dma; skb = dev_alloc_skb(SMALL_PACKET_SIZE + NET_IP_ALIGN); if (!skb) { mlx4_dbg(RX_ERR, priv, "Failed allocating skb\n"); return NULL; } skb->dev = priv->dev; skb_reserve(skb, NET_IP_ALIGN); skb->len = length; skb->truesize = length + sizeof(struct sk_buff); /* Get pointer to first fragment so we could copy the headers into the * (linear part of the) skb */ va = page_address(skb_frags[0].page) + skb_frags[0].page_offset; if (length <= SMALL_PACKET_SIZE) { /* We are copying all relevant data to the skb - temporarily * synch buffers for the copy */ dma = be64_to_cpu(rx_desc->data[0].addr); dma_sync_single_range_for_cpu(&mdev->pdev->dev, dma, 0, length, DMA_FROM_DEVICE); skb_copy_to_linear_data(skb, va, length); dma_sync_single_range_for_device(&mdev->pdev->dev, dma, 0, length, DMA_FROM_DEVICE); skb->tail += length; } else { /* Move relevant fragments to skb */ used_frags = mlx4_en_complete_rx_desc(priv, rx_desc, skb_frags, skb_shinfo(skb)->frags, page_alloc, length); skb_shinfo(skb)->nr_frags = used_frags; /* Copy headers into the skb linear buffer */ memcpy(skb->data, va, HEADER_COPY_SIZE); skb->tail += HEADER_COPY_SIZE; /* Skip headers in first fragment */ skb_shinfo(skb)->frags[0].page_offset += HEADER_COPY_SIZE; /* Adjust size of first fragment */ skb_shinfo(skb)->frags[0].size -= HEADER_COPY_SIZE; skb->data_len = length - HEADER_COPY_SIZE; } return skb; }
static int ks8842_tx_frame_dma(struct sk_buff *skb, struct net_device *netdev) { struct ks8842_adapter *adapter = netdev_priv(netdev); struct ks8842_tx_dma_ctl *ctl = &adapter->dma_tx; u8 *buf = ctl->buf; if (ctl->adesc) { netdev_dbg(netdev, "%s: TX ongoing\n", __func__); /* transfer ongoing */ return NETDEV_TX_BUSY; } sg_dma_len(&ctl->sg) = skb->len + sizeof(u32); /* copy data to the TX buffer */ /* the control word, enable IRQ, port 1 and the length */ *buf++ = 0x00; *buf++ = 0x01; /* Port 1 */ *buf++ = skb->len & 0xff; *buf++ = (skb->len >> 8) & 0xff; skb_copy_from_linear_data(skb, buf, skb->len); dma_sync_single_range_for_device(adapter->dev, sg_dma_address(&ctl->sg), 0, sg_dma_len(&ctl->sg), DMA_TO_DEVICE); /* make sure the length is a multiple of 4 */ if (sg_dma_len(&ctl->sg) % 4) sg_dma_len(&ctl->sg) += 4 - sg_dma_len(&ctl->sg) % 4; ctl->adesc = ctl->chan->device->device_prep_slave_sg(ctl->chan, &ctl->sg, 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP); if (!ctl->adesc) return NETDEV_TX_BUSY; ctl->adesc->callback_param = netdev; ctl->adesc->callback = ks8842_dma_tx_cb; ctl->adesc->tx_submit(ctl->adesc); netdev->stats.tx_bytes += skb->len; dev_kfree_skb(skb); return NETDEV_TX_OK; }
static __always_inline bool __ixgbe_alloc_rx_buffers_zc(struct ixgbe_ring *rx_ring, u16 cleaned_count, bool alloc(struct ixgbe_ring *rx_ring, struct ixgbe_rx_buffer *bi)) { union ixgbe_adv_rx_desc *rx_desc; struct ixgbe_rx_buffer *bi; u16 i = rx_ring->next_to_use; bool ok = true; /* nothing to do */ if (!cleaned_count) return true; rx_desc = IXGBE_RX_DESC(rx_ring, i); bi = &rx_ring->rx_buffer_info[i]; i -= rx_ring->count; do { if (!alloc(rx_ring, bi)) { ok = false; break; } /* sync the buffer for use by the device */ dma_sync_single_range_for_device(rx_ring->dev, bi->dma, bi->page_offset, rx_ring->rx_buf_len, DMA_BIDIRECTIONAL); /* Refresh the desc even if buffer_addrs didn't change * because each write-back erases this info. */ rx_desc->read.pkt_addr = cpu_to_le64(bi->dma); rx_desc++; bi++; i++; if (unlikely(!i)) { rx_desc = IXGBE_RX_DESC(rx_ring, 0); bi = rx_ring->rx_buffer_info; i -= rx_ring->count; } /* clear the length for the next_to_use descriptor */ rx_desc->wb.upper.length = 0; cleaned_count--; } while (cleaned_count); i += rx_ring->count; if (rx_ring->next_to_use != i) { rx_ring->next_to_use = i; /* update next to alloc since we have filled the ring */ rx_ring->next_to_alloc = i; /* Force memory writes to complete before letting h/w * know there are new descriptors to fetch. (Only * applicable for weak-ordered memory model archs, * such as IA-64). */ wmb(); writel(i, rx_ring->tail); } return ok; }