Commit 8dee19e6 authored by Lendacky, Thomas's avatar Lendacky, Thomas Committed by David S. Miller

amd-xgbe: Allow rx-frames coalescing to be changed anytime

Currently the device must be down in order to update the rx-frames
coalescing setting because the interrupt indicator is set in the
descriptor data during initialization. Allow this setting to be changed
while the device is up by moving the interrupt decision into the
descriptor reset function and base the decision off of the supplied
descriptor index value.
Signed-off-by: default avatarTom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1e53d5bb
...@@ -1101,9 +1101,24 @@ static void xgbe_tx_desc_init(struct xgbe_channel *channel) ...@@ -1101,9 +1101,24 @@ static void xgbe_tx_desc_init(struct xgbe_channel *channel)
DBGPR("<--tx_desc_init\n"); DBGPR("<--tx_desc_init\n");
} }
static void xgbe_rx_desc_reset(struct xgbe_ring_data *rdata) static void xgbe_rx_desc_reset(struct xgbe_prv_data *pdata,
struct xgbe_ring_data *rdata, unsigned int index)
{ {
struct xgbe_ring_desc *rdesc = rdata->rdesc; struct xgbe_ring_desc *rdesc = rdata->rdesc;
unsigned int rx_usecs = pdata->rx_usecs;
unsigned int rx_frames = pdata->rx_frames;
unsigned int inte;
if (!rx_usecs && !rx_frames) {
/* No coalescing, interrupt for every descriptor */
inte = 1;
} else {
/* Set interrupt based on Rx frame coalescing setting */
if (rx_frames && !((index + 1) % rx_frames))
inte = 1;
else
inte = 0;
}
/* Reset the Rx descriptor /* Reset the Rx descriptor
* Set buffer 1 (lo) address to header dma address (lo) * Set buffer 1 (lo) address to header dma address (lo)
...@@ -1117,8 +1132,7 @@ static void xgbe_rx_desc_reset(struct xgbe_ring_data *rdata) ...@@ -1117,8 +1132,7 @@ static void xgbe_rx_desc_reset(struct xgbe_ring_data *rdata)
rdesc->desc2 = cpu_to_le32(lower_32_bits(rdata->rx.buf.dma)); rdesc->desc2 = cpu_to_le32(lower_32_bits(rdata->rx.buf.dma));
rdesc->desc3 = cpu_to_le32(upper_32_bits(rdata->rx.buf.dma)); rdesc->desc3 = cpu_to_le32(upper_32_bits(rdata->rx.buf.dma));
XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, INTE, XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, INTE, inte);
rdata->interrupt ? 1 : 0);
/* Since the Rx DMA engine is likely running, make sure everything /* Since the Rx DMA engine is likely running, make sure everything
* is written to the descriptor(s) before setting the OWN bit * is written to the descriptor(s) before setting the OWN bit
...@@ -1138,26 +1152,16 @@ static void xgbe_rx_desc_init(struct xgbe_channel *channel) ...@@ -1138,26 +1152,16 @@ static void xgbe_rx_desc_init(struct xgbe_channel *channel)
struct xgbe_ring *ring = channel->rx_ring; struct xgbe_ring *ring = channel->rx_ring;
struct xgbe_ring_data *rdata; struct xgbe_ring_data *rdata;
unsigned int start_index = ring->cur; unsigned int start_index = ring->cur;
unsigned int rx_coalesce, rx_frames;
unsigned int i; unsigned int i;
DBGPR("-->rx_desc_init\n"); DBGPR("-->rx_desc_init\n");
rx_coalesce = (pdata->rx_riwt || pdata->rx_frames) ? 1 : 0;
rx_frames = pdata->rx_frames;
/* Initialize all descriptors */ /* Initialize all descriptors */
for (i = 0; i < ring->rdesc_count; i++) { for (i = 0; i < ring->rdesc_count; i++) {
rdata = XGBE_GET_DESC_DATA(ring, i); rdata = XGBE_GET_DESC_DATA(ring, i);
/* Set interrupt on completion bit as appropriate */
if (rx_coalesce && (!rx_frames || ((i + 1) % rx_frames)))
rdata->interrupt = 0;
else
rdata->interrupt = 1;
/* Initialize Rx descriptor */ /* Initialize Rx descriptor */
xgbe_rx_desc_reset(rdata); xgbe_rx_desc_reset(pdata, rdata, i);
} }
/* Update the total number of Rx descriptors */ /* Update the total number of Rx descriptors */
......
...@@ -1806,7 +1806,7 @@ static void xgbe_rx_refresh(struct xgbe_channel *channel) ...@@ -1806,7 +1806,7 @@ static void xgbe_rx_refresh(struct xgbe_channel *channel)
if (desc_if->map_rx_buffer(pdata, ring, rdata)) if (desc_if->map_rx_buffer(pdata, ring, rdata))
break; break;
hw_if->rx_desc_reset(rdata); hw_if->rx_desc_reset(pdata, rdata, ring->dirty);
ring->dirty++; ring->dirty++;
} }
......
...@@ -424,16 +424,6 @@ static int xgbe_set_coalesce(struct net_device *netdev, ...@@ -424,16 +424,6 @@ static int xgbe_set_coalesce(struct net_device *netdev,
(ec->rate_sample_interval)) (ec->rate_sample_interval))
return -EOPNOTSUPP; return -EOPNOTSUPP;
/* Can only change rx-frames when interface is down (see
* rx_descriptor_init in xgbe-dev.c)
*/
rx_frames = pdata->rx_frames;
if (rx_frames != ec->rx_max_coalesced_frames && netif_running(netdev)) {
netdev_alert(netdev,
"interface must be down to change rx-frames\n");
return -EINVAL;
}
rx_riwt = hw_if->usec_to_riwt(pdata, ec->rx_coalesce_usecs); rx_riwt = hw_if->usec_to_riwt(pdata, ec->rx_coalesce_usecs);
rx_usecs = ec->rx_coalesce_usecs; rx_usecs = ec->rx_coalesce_usecs;
rx_frames = ec->rx_max_coalesced_frames; rx_frames = ec->rx_max_coalesced_frames;
......
...@@ -325,8 +325,6 @@ struct xgbe_ring_data { ...@@ -325,8 +325,6 @@ struct xgbe_ring_data {
struct xgbe_tx_ring_data tx; /* Tx-related data */ struct xgbe_tx_ring_data tx; /* Tx-related data */
struct xgbe_rx_ring_data rx; /* Rx-related data */ struct xgbe_rx_ring_data rx; /* Rx-related data */
unsigned int interrupt; /* Interrupt indicator */
unsigned int mapped_as_page; unsigned int mapped_as_page;
/* Incomplete receive save location. If the budget is exhausted /* Incomplete receive save location. If the budget is exhausted
...@@ -536,8 +534,9 @@ struct xgbe_hw_if { ...@@ -536,8 +534,9 @@ struct xgbe_hw_if {
int (*dev_read)(struct xgbe_channel *); int (*dev_read)(struct xgbe_channel *);
void (*tx_desc_init)(struct xgbe_channel *); void (*tx_desc_init)(struct xgbe_channel *);
void (*rx_desc_init)(struct xgbe_channel *); void (*rx_desc_init)(struct xgbe_channel *);
void (*rx_desc_reset)(struct xgbe_ring_data *);
void (*tx_desc_reset)(struct xgbe_ring_data *); void (*tx_desc_reset)(struct xgbe_ring_data *);
void (*rx_desc_reset)(struct xgbe_prv_data *, struct xgbe_ring_data *,
unsigned int);
int (*is_last_desc)(struct xgbe_ring_desc *); int (*is_last_desc)(struct xgbe_ring_desc *);
int (*is_context_desc)(struct xgbe_ring_desc *); int (*is_context_desc)(struct xgbe_ring_desc *);
void (*tx_start_xmit)(struct xgbe_channel *, struct xgbe_ring *); void (*tx_start_xmit)(struct xgbe_channel *, struct xgbe_ring *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment