ftgmac100: Simplify rx pointer handling in the rx path
We don't handle fragmented RX packets, so the "looping" helpers to locate the first segment of a packet or to drop a packet aren't actually helping. Take them out and simplify ftgmac100_rx_packet() further as a result. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
eb50af2044
commit
01dd70b52a
@@ -431,34 +431,6 @@ static int ftgmac100_next_rx_pointer(int pointer)
|
|||||||
return (pointer + 1) & (RX_QUEUE_ENTRIES - 1);
|
return (pointer + 1) & (RX_QUEUE_ENTRIES - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ftgmac100_rx_pointer_advance(struct ftgmac100 *priv)
|
|
||||||
{
|
|
||||||
priv->rx_pointer = ftgmac100_next_rx_pointer(priv->rx_pointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct ftgmac100_rxdes *ftgmac100_current_rxdes(struct ftgmac100 *priv)
|
|
||||||
{
|
|
||||||
return &priv->descs->rxdes[priv->rx_pointer];
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct ftgmac100_rxdes *
|
|
||||||
ftgmac100_rx_locate_first_segment(struct ftgmac100 *priv)
|
|
||||||
{
|
|
||||||
struct ftgmac100_rxdes *rxdes = ftgmac100_current_rxdes(priv);
|
|
||||||
|
|
||||||
while (ftgmac100_rxdes_packet_ready(rxdes)) {
|
|
||||||
if (ftgmac100_rxdes_first_segment(rxdes))
|
|
||||||
return rxdes;
|
|
||||||
|
|
||||||
ftgmac100_rxdes_set_dma_own(priv, rxdes);
|
|
||||||
ftgmac100_rx_pointer_advance(priv);
|
|
||||||
rxdes = ftgmac100_current_rxdes(priv);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void ftgmac100_rx_packet_error(struct ftgmac100 *priv,
|
static void ftgmac100_rx_packet_error(struct ftgmac100 *priv,
|
||||||
struct ftgmac100_rxdes *rxdes)
|
struct ftgmac100_rxdes *rxdes)
|
||||||
{
|
{
|
||||||
@@ -476,51 +448,32 @@ static void ftgmac100_rx_packet_error(struct ftgmac100 *priv,
|
|||||||
netdev->stats.rx_length_errors++;
|
netdev->stats.rx_length_errors++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ftgmac100_rx_drop_packet(struct ftgmac100 *priv)
|
|
||||||
{
|
|
||||||
struct net_device *netdev = priv->netdev;
|
|
||||||
struct ftgmac100_rxdes *rxdes = ftgmac100_current_rxdes(priv);
|
|
||||||
bool done = false;
|
|
||||||
|
|
||||||
if (net_ratelimit())
|
|
||||||
netdev_dbg(netdev, "drop packet %p\n", rxdes);
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (ftgmac100_rxdes_last_segment(rxdes))
|
|
||||||
done = true;
|
|
||||||
|
|
||||||
ftgmac100_rxdes_set_dma_own(priv, rxdes);
|
|
||||||
ftgmac100_rx_pointer_advance(priv);
|
|
||||||
rxdes = ftgmac100_current_rxdes(priv);
|
|
||||||
} while (!done && ftgmac100_rxdes_packet_ready(rxdes));
|
|
||||||
|
|
||||||
netdev->stats.rx_dropped++;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
|
static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
|
||||||
{
|
{
|
||||||
struct net_device *netdev = priv->netdev;
|
struct net_device *netdev = priv->netdev;
|
||||||
struct ftgmac100_rxdes *rxdes;
|
struct ftgmac100_rxdes *rxdes;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
struct page *page;
|
struct page *page;
|
||||||
unsigned int size;
|
unsigned int pointer, size;
|
||||||
dma_addr_t map;
|
dma_addr_t map;
|
||||||
|
|
||||||
rxdes = ftgmac100_rx_locate_first_segment(priv);
|
/* Grab next RX descriptor */
|
||||||
if (!rxdes)
|
pointer = priv->rx_pointer;
|
||||||
|
rxdes = &priv->descs->rxdes[pointer];
|
||||||
|
|
||||||
|
/* Do we have a packet ? */
|
||||||
|
if (!ftgmac100_rxdes_packet_ready(rxdes))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* We don't support segmented rx frames, so drop these
|
/* We don't cope with fragmented RX packets */
|
||||||
* along with packets with errors.
|
if (unlikely(!ftgmac100_rxdes_first_segment(rxdes) ||
|
||||||
*/
|
!ftgmac100_rxdes_last_segment(rxdes)))
|
||||||
if (unlikely(!ftgmac100_rxdes_last_segment(rxdes))) {
|
goto drop;
|
||||||
ftgmac100_rx_drop_packet(priv);
|
|
||||||
return true;
|
/* Any error (other than csum offload) flagged ? */
|
||||||
}
|
|
||||||
if (unlikely(ftgmac100_rxdes_any_error(rxdes))) {
|
if (unlikely(ftgmac100_rxdes_any_error(rxdes))) {
|
||||||
ftgmac100_rx_packet_error(priv, rxdes);
|
ftgmac100_rx_packet_error(priv, rxdes);
|
||||||
ftgmac100_rx_drop_packet(priv);
|
goto drop;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the packet had no buffer (failed to allocate earlier)
|
/* If the packet had no buffer (failed to allocate earlier)
|
||||||
@@ -529,8 +482,7 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
|
|||||||
page = ftgmac100_rxdes_get_page(priv, rxdes);
|
page = ftgmac100_rxdes_get_page(priv, rxdes);
|
||||||
if (!page) {
|
if (!page) {
|
||||||
ftgmac100_alloc_rx_page(priv, rxdes, GFP_ATOMIC);
|
ftgmac100_alloc_rx_page(priv, rxdes, GFP_ATOMIC);
|
||||||
ftgmac100_rx_pointer_advance(priv);
|
goto drop;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* start processing */
|
/* start processing */
|
||||||
@@ -538,9 +490,7 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
|
|||||||
if (unlikely(!skb)) {
|
if (unlikely(!skb)) {
|
||||||
if (net_ratelimit())
|
if (net_ratelimit())
|
||||||
netdev_err(netdev, "rx skb alloc failed\n");
|
netdev_err(netdev, "rx skb alloc failed\n");
|
||||||
|
goto drop;
|
||||||
ftgmac100_rx_drop_packet(priv);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(ftgmac100_rxdes_multicast(rxdes)))
|
if (unlikely(ftgmac100_rxdes_multicast(rxdes)))
|
||||||
@@ -577,8 +527,7 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
|
|||||||
|
|
||||||
ftgmac100_alloc_rx_page(priv, rxdes, GFP_ATOMIC);
|
ftgmac100_alloc_rx_page(priv, rxdes, GFP_ATOMIC);
|
||||||
|
|
||||||
ftgmac100_rx_pointer_advance(priv);
|
priv->rx_pointer = ftgmac100_next_rx_pointer(pointer);
|
||||||
rxdes = ftgmac100_current_rxdes(priv);
|
|
||||||
|
|
||||||
/* Small frames are copied into linear part of skb to free one page */
|
/* Small frames are copied into linear part of skb to free one page */
|
||||||
if (skb->len <= 128) {
|
if (skb->len <= 128) {
|
||||||
@@ -601,6 +550,13 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
|
|||||||
|
|
||||||
(*processed)++;
|
(*processed)++;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
drop:
|
||||||
|
/* Clean rxdes0 (which resets own bit) */
|
||||||
|
rxdes->rxdes0 &= cpu_to_le32(priv->rxdes0_edorr_mask);
|
||||||
|
priv->rx_pointer = ftgmac100_next_rx_pointer(pointer);
|
||||||
|
netdev->stats.rx_dropped++;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ftgmac100_txdes_reset(const struct ftgmac100 *priv,
|
static void ftgmac100_txdes_reset(const struct ftgmac100 *priv,
|
||||||
|
|||||||
Reference in New Issue
Block a user