summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/freescale
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/freescale')
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth_sg.c27
1 files changed, 15 insertions, 12 deletions
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth_sg.c
index a624e9a..0104790 100644
--- a/drivers/net/ethernet/freescale/dpa/dpaa_eth_sg.c
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_sg.c
@@ -198,7 +198,8 @@ struct sk_buff *_dpa_cleanup_tx_fd(const struct dpa_priv_s *priv,
if (fd->format == qm_fd_sg) {
/*
- * The sgt page is guaranteed to reside in lowmem.
+ * The sgt buffer has been allocated with netdev_alloc_frag(),
+ * it's from lowmem.
*/
sgt = phys_to_virt(addr + dpa_fd_offset(fd));
#ifdef CONFIG_FSL_DPAA_1588
@@ -234,8 +235,8 @@ struct sk_buff *_dpa_cleanup_tx_fd(const struct dpa_priv_s *priv,
* and we know they're not used by anyone else
*/
- /* Free separately the pages that we allocated on Tx */
- free_page((unsigned long)phys_to_virt(addr));
+ /* Free the page frag that we allocated on Tx */
+ put_page(virt_to_head_page(sgt));
}
#if defined(CONFIG_FSL_DPAA_1588) || defined(CONFIG_FSL_DPAA_TS)
else {
@@ -539,18 +540,20 @@ static int __hot skb_to_sg_fd(struct dpa_priv_s *priv,
int err;
struct qm_sg_entry *sgt;
- unsigned long sgt_page;
+ void *sgt_buf;
void *buffer_start;
skb_frag_t *frag;
int i, j;
const enum dma_data_direction dma_dir = DMA_TO_DEVICE;
+ const int nr_frags = skb_shinfo(skb)->nr_frags;
fd->format = qm_fd_sg;
- /* get a new page to store the SGTable */
- sgt_page = __get_free_page(GFP_ATOMIC);
- if (unlikely(!sgt_page)) {
- dev_err(dpa_bp->dev, "__get_free_page() failed\n");
+ /* get a page frag to store the SGTable */
+ sgt_buf = netdev_alloc_frag(priv->tx_headroom +
+ sizeof(struct qm_sg_entry) * (1 + nr_frags));
+ if (unlikely(!sgt_buf)) {
+ dev_err(dpa_bp->dev, "netdev_alloc_frag() failed\n");
return -ENOMEM;
}
@@ -561,14 +564,14 @@ static int __hot skb_to_sg_fd(struct dpa_priv_s *priv,
* need to write into the skb.
*/
err = dpa_enable_tx_csum(priv, skb, fd,
- (void *)sgt_page + DPA_TX_PRIV_DATA_SIZE);
+ sgt_buf + DPA_TX_PRIV_DATA_SIZE);
if (unlikely(err < 0)) {
if (netif_msg_tx_err(priv) && net_ratelimit())
netdev_err(net_dev, "HW csum error: %d\n", err);
goto csum_failed;
}
- sgt = (struct qm_sg_entry *)(sgt_page + priv->tx_headroom);
+ sgt = (struct qm_sg_entry *)(sgt_buf + priv->tx_headroom);
sgt[0].bpid = dpa_bp->bpid;
sgt[0].offset = 0;
sgt[0].length = skb_headlen(skb);
@@ -585,7 +588,7 @@ static int __hot skb_to_sg_fd(struct dpa_priv_s *priv,
sgt[0].addr_lo = lower_32_bits(addr);
/* populate the rest of SGT entries */
- for (i = 1; i <= skb_shinfo(skb)->nr_frags; i++) {
+ for (i = 1; i <= nr_frags; i++) {
frag = &skb_shinfo(skb)->frags[i - 1];
sgt[i].bpid = dpa_bp->bpid;
sgt[i].offset = 0;
@@ -637,7 +640,7 @@ sg_map_failed:
dpa_bp->size, dma_dir);
sg0_map_failed:
csum_failed:
- free_page(sgt_page);
+ put_page(virt_to_head_page(sgt_buf));
return err;
}