From: Florian Fainelli <f.fainelli@gmail.com> To: Iyappan Subramanian <isubramanian@apm.com>, davem@davemloft.net, netdev@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, patches@apm.com, kchudgar@apm.com Subject: Re: [PATCH net-next 5/6] drivers: net: xgene-v2: Add transmit and receive Date: Tue, 31 Jan 2017 12:33:04 -0800 [thread overview] Message-ID: <fb8fcd33-4b5b-5999-7662-4165aeb179e1@gmail.com> (raw) In-Reply-To: <1485889401-13909-6-git-send-email-isubramanian@apm.com> On 01/31/2017 11:03 AM, Iyappan Subramanian wrote: > This patch adds, > - Transmit > - Transmit completion poll > - Receive poll > - NAPI handler > > and enables the driver. > > Signed-off-by: Iyappan Subramanian <isubramanian@apm.com> > Signed-off-by: Keyur Chudgar <kchudgar@apm.com> > --- > + > + tx_ring = pdata->tx_ring; > + tail = tx_ring->tail; > + len = skb_headlen(skb); > + raw_desc = &tx_ring->raw_desc[tail]; > + > + /* Tx descriptor not available */ > + if (!GET_BITS(E, le64_to_cpu(raw_desc->m0)) || > + GET_BITS(PKT_SIZE, le64_to_cpu(raw_desc->m0))) > + return NETDEV_TX_BUSY; > + > + /* Packet buffers should be 64B aligned */ > + pkt_buf = dma_alloc_coherent(dev, XGENE_ENET_STD_MTU, &dma_addr, > + GFP_ATOMIC); > + if (unlikely(!pkt_buf)) > + goto out; Can't you obtain a DMA-API mapping for skb->data and pass it down to the hardware? This copy here is inefficient. > + > + memcpy(pkt_buf, skb->data, len); > + > + addr_hi = GET_BITS(NEXT_DESC_ADDRH, le64_to_cpu(raw_desc->m1)); > + addr_lo = GET_BITS(NEXT_DESC_ADDRL, le64_to_cpu(raw_desc->m1)); > + raw_desc->m1 = cpu_to_le64(SET_BITS(NEXT_DESC_ADDRL, addr_lo) | > + SET_BITS(NEXT_DESC_ADDRH, addr_hi) | > + SET_BITS(PKT_ADDRH, > + dma_addr >> PKT_ADDRL_LEN)); > + > + dma_wmb(); > + > + raw_desc->m0 = cpu_to_le64(SET_BITS(PKT_ADDRL, dma_addr) | > + SET_BITS(PKT_SIZE, len) | > + SET_BITS(E, 0)); > + > + skb_tx_timestamp(skb); > + xge_wr_csr(pdata, DMATXCTRL, 1); > + > + pdata->stats.tx_packets++; > + pdata->stats.tx_bytes += skb->len; This is both racy and incorrect. Racy because after you wrote DMATXCTRL, your TX completion can run, and it can do that while interrupting your CPU presumably, and free the SKB, therefore making you access a freed SKB (or it should, if it does not), it's also incorrect, because before you get signaled a TX completion, there is no guarantee that the packets did actually make it through, you must update your stats in the TX completion handler. > + > + tx_ring->skbs[tail] = skb; > + tx_ring->pkt_bufs[tail] = pkt_buf; > + tx_ring->tail = (tail + 1) & (XGENE_ENET_NUM_DESC - 1); > + > +out: > + dev_kfree_skb_any(skb); Don't do this, remember a pointer to the SKB, free the SKB in TX completion handler, preferably in NAPI context. > + > + return NETDEV_TX_OK; > +} > + > +static void xge_txc_poll(struct net_device *ndev, unsigned int budget) > +{ > + struct xge_pdata *pdata = netdev_priv(ndev); > + struct device *dev = &pdata->pdev->dev; > + struct xge_desc_ring *tx_ring; > + struct xge_raw_desc *raw_desc; > + u64 addr_lo, addr_hi; > + dma_addr_t dma_addr; > + void *pkt_buf; > + bool pktsent; > + u32 data; > + u8 head; > + int i; > + > + tx_ring = pdata->tx_ring; > + head = tx_ring->head; > + > + data = xge_rd_csr(pdata, DMATXSTATUS); > + pktsent = data & TX_PKT_SENT; > + if (unlikely(!pktsent)) > + return; > + > + for (i = 0; i < budget; i++) { TX completion handlers should run unbound and free the entire TX ring, don't make it obey to an upper bound. > + raw_desc = &tx_ring->raw_desc[head]; > + > + if (!GET_BITS(E, le64_to_cpu(raw_desc->m0))) > + break; > + > + dma_rmb(); > + > + addr_hi = GET_BITS(PKT_ADDRH, le64_to_cpu(raw_desc->m1)); > + addr_lo = GET_BITS(PKT_ADDRL, le64_to_cpu(raw_desc->m0)); > + dma_addr = (addr_hi << PKT_ADDRL_LEN) | addr_lo; > + > + pkt_buf = tx_ring->pkt_bufs[head]; > + > + /* clear pktstart address and pktsize */ > + raw_desc->m0 = cpu_to_le64(SET_BITS(E, 1) | > + SET_BITS(PKT_SIZE, 0)); > + xge_wr_csr(pdata, DMATXSTATUS, 1); > + > + dma_free_coherent(dev, XGENE_ENET_STD_MTU, pkt_buf, dma_addr); > + > + head = (head + 1) & (XGENE_ENET_NUM_DESC - 1); > + } > + > + tx_ring->head = head; > +} > + > +static int xge_rx_poll(struct net_device *ndev, unsigned int budget) > +{ > + struct xge_pdata *pdata = netdev_priv(ndev); > + struct device *dev = &pdata->pdev->dev; > + dma_addr_t addr_hi, addr_lo, dma_addr; > + struct xge_desc_ring *rx_ring; > + struct xge_raw_desc *raw_desc; > + struct sk_buff *skb; > + int i, npkts, ret = 0; > + bool pktrcvd; > + u32 data; > + u8 head; > + u16 len; > + > + rx_ring = pdata->rx_ring; > + head = rx_ring->head; > + > + data = xge_rd_csr(pdata, DMARXSTATUS); > + pktrcvd = data & RXSTATUS_RXPKTRCVD; > + > + if (unlikely(!pktrcvd)) > + return 0; > + > + npkts = 0; > + for (i = 0; i < budget; i++) { So pktrcvd is not an indication of the produced number of packets, just that there are packets, that's not very convenient, and it's redundant with the very fact of being interrupted. > + raw_desc = &rx_ring->raw_desc[head]; > + > + if (GET_BITS(E, le64_to_cpu(raw_desc->m0))) > + break; > + > + dma_rmb(); > + > + addr_hi = GET_BITS(PKT_ADDRH, le64_to_cpu(raw_desc->m1)); > + addr_lo = GET_BITS(PKT_ADDRL, le64_to_cpu(raw_desc->m0)); > + dma_addr = (addr_hi << PKT_ADDRL_LEN) | addr_lo; > + len = GET_BITS(PKT_SIZE, le64_to_cpu(raw_desc->m0)); Is not there some kind of additional status that would indicate if the packet is possibly invalid (oversize, undersize, etc.)? > + > + dma_unmap_single(dev, dma_addr, XGENE_ENET_STD_MTU, > + DMA_FROM_DEVICE); > + > + skb = rx_ring->skbs[head]; > + skb_put(skb, len); > + > + skb->protocol = eth_type_trans(skb, ndev); > + > + pdata->stats.rx_packets++; > + pdata->stats.rx_bytes += len; > + napi_gro_receive(&pdata->napi, skb); > + npkts++; -- Florian
WARNING: multiple messages have this Message-ID (diff)
From: f.fainelli@gmail.com (Florian Fainelli) To: linux-arm-kernel@lists.infradead.org Subject: [PATCH net-next 5/6] drivers: net: xgene-v2: Add transmit and receive Date: Tue, 31 Jan 2017 12:33:04 -0800 [thread overview] Message-ID: <fb8fcd33-4b5b-5999-7662-4165aeb179e1@gmail.com> (raw) In-Reply-To: <1485889401-13909-6-git-send-email-isubramanian@apm.com> On 01/31/2017 11:03 AM, Iyappan Subramanian wrote: > This patch adds, > - Transmit > - Transmit completion poll > - Receive poll > - NAPI handler > > and enables the driver. > > Signed-off-by: Iyappan Subramanian <isubramanian@apm.com> > Signed-off-by: Keyur Chudgar <kchudgar@apm.com> > --- > + > + tx_ring = pdata->tx_ring; > + tail = tx_ring->tail; > + len = skb_headlen(skb); > + raw_desc = &tx_ring->raw_desc[tail]; > + > + /* Tx descriptor not available */ > + if (!GET_BITS(E, le64_to_cpu(raw_desc->m0)) || > + GET_BITS(PKT_SIZE, le64_to_cpu(raw_desc->m0))) > + return NETDEV_TX_BUSY; > + > + /* Packet buffers should be 64B aligned */ > + pkt_buf = dma_alloc_coherent(dev, XGENE_ENET_STD_MTU, &dma_addr, > + GFP_ATOMIC); > + if (unlikely(!pkt_buf)) > + goto out; Can't you obtain a DMA-API mapping for skb->data and pass it down to the hardware? This copy here is inefficient. > + > + memcpy(pkt_buf, skb->data, len); > + > + addr_hi = GET_BITS(NEXT_DESC_ADDRH, le64_to_cpu(raw_desc->m1)); > + addr_lo = GET_BITS(NEXT_DESC_ADDRL, le64_to_cpu(raw_desc->m1)); > + raw_desc->m1 = cpu_to_le64(SET_BITS(NEXT_DESC_ADDRL, addr_lo) | > + SET_BITS(NEXT_DESC_ADDRH, addr_hi) | > + SET_BITS(PKT_ADDRH, > + dma_addr >> PKT_ADDRL_LEN)); > + > + dma_wmb(); > + > + raw_desc->m0 = cpu_to_le64(SET_BITS(PKT_ADDRL, dma_addr) | > + SET_BITS(PKT_SIZE, len) | > + SET_BITS(E, 0)); > + > + skb_tx_timestamp(skb); > + xge_wr_csr(pdata, DMATXCTRL, 1); > + > + pdata->stats.tx_packets++; > + pdata->stats.tx_bytes += skb->len; This is both racy and incorrect. Racy because after you wrote DMATXCTRL, your TX completion can run, and it can do that while interrupting your CPU presumably, and free the SKB, therefore making you access a freed SKB (or it should, if it does not), it's also incorrect, because before you get signaled a TX completion, there is no guarantee that the packets did actually make it through, you must update your stats in the TX completion handler. > + > + tx_ring->skbs[tail] = skb; > + tx_ring->pkt_bufs[tail] = pkt_buf; > + tx_ring->tail = (tail + 1) & (XGENE_ENET_NUM_DESC - 1); > + > +out: > + dev_kfree_skb_any(skb); Don't do this, remember a pointer to the SKB, free the SKB in TX completion handler, preferably in NAPI context. > + > + return NETDEV_TX_OK; > +} > + > +static void xge_txc_poll(struct net_device *ndev, unsigned int budget) > +{ > + struct xge_pdata *pdata = netdev_priv(ndev); > + struct device *dev = &pdata->pdev->dev; > + struct xge_desc_ring *tx_ring; > + struct xge_raw_desc *raw_desc; > + u64 addr_lo, addr_hi; > + dma_addr_t dma_addr; > + void *pkt_buf; > + bool pktsent; > + u32 data; > + u8 head; > + int i; > + > + tx_ring = pdata->tx_ring; > + head = tx_ring->head; > + > + data = xge_rd_csr(pdata, DMATXSTATUS); > + pktsent = data & TX_PKT_SENT; > + if (unlikely(!pktsent)) > + return; > + > + for (i = 0; i < budget; i++) { TX completion handlers should run unbound and free the entire TX ring, don't make it obey to an upper bound. > + raw_desc = &tx_ring->raw_desc[head]; > + > + if (!GET_BITS(E, le64_to_cpu(raw_desc->m0))) > + break; > + > + dma_rmb(); > + > + addr_hi = GET_BITS(PKT_ADDRH, le64_to_cpu(raw_desc->m1)); > + addr_lo = GET_BITS(PKT_ADDRL, le64_to_cpu(raw_desc->m0)); > + dma_addr = (addr_hi << PKT_ADDRL_LEN) | addr_lo; > + > + pkt_buf = tx_ring->pkt_bufs[head]; > + > + /* clear pktstart address and pktsize */ > + raw_desc->m0 = cpu_to_le64(SET_BITS(E, 1) | > + SET_BITS(PKT_SIZE, 0)); > + xge_wr_csr(pdata, DMATXSTATUS, 1); > + > + dma_free_coherent(dev, XGENE_ENET_STD_MTU, pkt_buf, dma_addr); > + > + head = (head + 1) & (XGENE_ENET_NUM_DESC - 1); > + } > + > + tx_ring->head = head; > +} > + > +static int xge_rx_poll(struct net_device *ndev, unsigned int budget) > +{ > + struct xge_pdata *pdata = netdev_priv(ndev); > + struct device *dev = &pdata->pdev->dev; > + dma_addr_t addr_hi, addr_lo, dma_addr; > + struct xge_desc_ring *rx_ring; > + struct xge_raw_desc *raw_desc; > + struct sk_buff *skb; > + int i, npkts, ret = 0; > + bool pktrcvd; > + u32 data; > + u8 head; > + u16 len; > + > + rx_ring = pdata->rx_ring; > + head = rx_ring->head; > + > + data = xge_rd_csr(pdata, DMARXSTATUS); > + pktrcvd = data & RXSTATUS_RXPKTRCVD; > + > + if (unlikely(!pktrcvd)) > + return 0; > + > + npkts = 0; > + for (i = 0; i < budget; i++) { So pktrcvd is not an indication of the produced number of packets, just that there are packets, that's not very convenient, and it's redundant with the very fact of being interrupted. > + raw_desc = &rx_ring->raw_desc[head]; > + > + if (GET_BITS(E, le64_to_cpu(raw_desc->m0))) > + break; > + > + dma_rmb(); > + > + addr_hi = GET_BITS(PKT_ADDRH, le64_to_cpu(raw_desc->m1)); > + addr_lo = GET_BITS(PKT_ADDRL, le64_to_cpu(raw_desc->m0)); > + dma_addr = (addr_hi << PKT_ADDRL_LEN) | addr_lo; > + len = GET_BITS(PKT_SIZE, le64_to_cpu(raw_desc->m0)); Is not there some kind of additional status that would indicate if the packet is possibly invalid (oversize, undersize, etc.)? > + > + dma_unmap_single(dev, dma_addr, XGENE_ENET_STD_MTU, > + DMA_FROM_DEVICE); > + > + skb = rx_ring->skbs[head]; > + skb_put(skb, len); > + > + skb->protocol = eth_type_trans(skb, ndev); > + > + pdata->stats.rx_packets++; > + pdata->stats.rx_bytes += len; > + napi_gro_receive(&pdata->napi, skb); > + npkts++; -- Florian
next prev parent reply other threads:[~2017-01-31 20:33 UTC|newest] Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top 2017-01-31 19:03 [PATCH net-next 0/6] drivers: net: xgene-v2: Add RGMII based 1G driver Iyappan Subramanian 2017-01-31 19:03 ` Iyappan Subramanian 2017-01-31 19:03 ` [PATCH net-next 1/6] drivers: net: xgene-v2: Add DMA descriptor Iyappan Subramanian 2017-01-31 19:03 ` Iyappan Subramanian 2017-01-31 19:03 ` [PATCH net-next 2/6] drivers: net: xgene-v2: Add mac configuration Iyappan Subramanian 2017-01-31 19:03 ` Iyappan Subramanian 2017-01-31 19:03 ` [PATCH net-next 3/6] drivers: net: xgene-v2: Add ethernet hardware configuration Iyappan Subramanian 2017-01-31 19:03 ` Iyappan Subramanian 2017-01-31 19:03 ` [PATCH net-next 4/6] drivers: net: xgene-v2: Add base driver Iyappan Subramanian 2017-01-31 19:03 ` Iyappan Subramanian 2017-01-31 20:01 ` Andrew Lunn 2017-01-31 20:01 ` Andrew Lunn 2017-02-27 4:33 ` Iyappan Subramanian 2017-02-27 4:33 ` Iyappan Subramanian 2017-01-31 20:31 ` Florian Fainelli 2017-01-31 20:31 ` Florian Fainelli 2017-02-27 5:05 ` Iyappan Subramanian 2017-02-27 5:05 ` Iyappan Subramanian 2017-01-31 19:03 ` [PATCH net-next 5/6] drivers: net: xgene-v2: Add transmit and receive Iyappan Subramanian 2017-01-31 19:03 ` Iyappan Subramanian 2017-01-31 20:33 ` Florian Fainelli [this message] 2017-01-31 20:33 ` Florian Fainelli 2017-02-01 11:09 ` David Laight 2017-02-01 11:09 ` David Laight 2017-02-27 5:11 ` Iyappan Subramanian 2017-02-27 5:11 ` Iyappan Subramanian 2017-02-27 5:08 ` Iyappan Subramanian 2017-02-27 5:08 ` Iyappan Subramanian 2017-01-31 20:44 ` kbuild test robot 2017-01-31 20:49 ` kbuild test robot 2017-01-31 20:49 ` kbuild test robot 2017-01-31 19:03 ` [PATCH net-next 6/6] MAINTAINERS: Add entry for APM X-Gene SoC Ethernet (v2) driver Iyappan Subramanian 2017-01-31 19:03 ` Iyappan Subramanian 2017-01-31 20:06 ` [PATCH net-next 0/6] drivers: net: xgene-v2: Add RGMII based 1G driver Andrew Lunn 2017-01-31 20:06 ` Andrew Lunn
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=fb8fcd33-4b5b-5999-7662-4165aeb179e1@gmail.com \ --to=f.fainelli@gmail.com \ --cc=davem@davemloft.net \ --cc=isubramanian@apm.com \ --cc=kchudgar@apm.com \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=netdev@vger.kernel.org \ --cc=patches@apm.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.