aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
diff options
context:
space:
mode:
authorLendacky, Thomas <Thomas.Lendacky@amd.com>2014-07-02 14:04:46 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-08 00:38:06 -0400
commit9867e8fb2c45888cc594457914dcbba599f086c8 (patch)
tree9a64c6124f280b9368f1f7789ebf1cca855b7886 /drivers/net/ethernet/amd/xgbe/xgbe-drv.c
parentff42606eed00bc065365f55269d558c06b968594 (diff)
amd-xgbe: Performance enhancements
This patch provides some general performance enhancements for the driver: - Modify the default coalescing settings (reduce usec, increase frames) - Change the AXI burst length to 256 bytes (default was 16 bytes which was smaller than a cache line) - Change the AXI cache settings to write-back/write-allocate which allocate cache entries for received packets during the DMA since the packet will be processed soon afterwards - Combine ioread/iowrite when disabling both the Tx and Rx interrupts - Change to processing the Tx/Rx channels in pairs - Only recycle the Rx descriptors when a threshold of dirty descriptors is reached Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/amd/xgbe/xgbe-drv.c')
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-drv.c91
1 files changed, 58 insertions, 33 deletions
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index b5fdf66f9a56..344e6b19ec0e 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -156,16 +156,21 @@ static void xgbe_enable_rx_tx_ints(struct xgbe_prv_data *pdata)
156{ 156{
157 struct xgbe_hw_if *hw_if = &pdata->hw_if; 157 struct xgbe_hw_if *hw_if = &pdata->hw_if;
158 struct xgbe_channel *channel; 158 struct xgbe_channel *channel;
159 enum xgbe_int int_id;
159 unsigned int i; 160 unsigned int i;
160 161
161 channel = pdata->channel; 162 channel = pdata->channel;
162 for (i = 0; i < pdata->channel_count; i++, channel++) { 163 for (i = 0; i < pdata->channel_count; i++, channel++) {
163 if (channel->tx_ring) 164 if (channel->tx_ring && channel->rx_ring)
164 hw_if->enable_int(channel, 165 int_id = XGMAC_INT_DMA_CH_SR_TI_RI;
165 XGMAC_INT_DMA_CH_SR_TI); 166 else if (channel->tx_ring)
166 if (channel->rx_ring) 167 int_id = XGMAC_INT_DMA_CH_SR_TI;
167 hw_if->enable_int(channel, 168 else if (channel->rx_ring)
168 XGMAC_INT_DMA_CH_SR_RI); 169 int_id = XGMAC_INT_DMA_CH_SR_RI;
170 else
171 continue;
172
173 hw_if->enable_int(channel, int_id);
169 } 174 }
170} 175}
171 176
@@ -173,16 +178,21 @@ static void xgbe_disable_rx_tx_ints(struct xgbe_prv_data *pdata)
173{ 178{
174 struct xgbe_hw_if *hw_if = &pdata->hw_if; 179 struct xgbe_hw_if *hw_if = &pdata->hw_if;
175 struct xgbe_channel *channel; 180 struct xgbe_channel *channel;
181 enum xgbe_int int_id;
176 unsigned int i; 182 unsigned int i;
177 183
178 channel = pdata->channel; 184 channel = pdata->channel;
179 for (i = 0; i < pdata->channel_count; i++, channel++) { 185 for (i = 0; i < pdata->channel_count; i++, channel++) {
180 if (channel->tx_ring) 186 if (channel->tx_ring && channel->rx_ring)
181 hw_if->disable_int(channel, 187 int_id = XGMAC_INT_DMA_CH_SR_TI_RI;
182 XGMAC_INT_DMA_CH_SR_TI); 188 else if (channel->tx_ring)
183 if (channel->rx_ring) 189 int_id = XGMAC_INT_DMA_CH_SR_TI;
184 hw_if->disable_int(channel, 190 else if (channel->rx_ring)
185 XGMAC_INT_DMA_CH_SR_RI); 191 int_id = XGMAC_INT_DMA_CH_SR_RI;
192 else
193 continue;
194
195 hw_if->disable_int(channel, int_id);
186 } 196 }
187} 197}
188 198
@@ -1114,6 +1124,22 @@ struct net_device_ops *xgbe_get_netdev_ops(void)
1114 return (struct net_device_ops *)&xgbe_netdev_ops; 1124 return (struct net_device_ops *)&xgbe_netdev_ops;
1115} 1125}
1116 1126
1127static void xgbe_rx_refresh(struct xgbe_channel *channel)
1128{
1129 struct xgbe_prv_data *pdata = channel->pdata;
1130 struct xgbe_desc_if *desc_if = &pdata->desc_if;
1131 struct xgbe_ring *ring = channel->rx_ring;
1132 struct xgbe_ring_data *rdata;
1133
1134 desc_if->realloc_skb(channel);
1135
1136 /* Update the Rx Tail Pointer Register with address of
1137 * the last cleaned entry */
1138 rdata = XGBE_GET_DESC_DATA(ring, ring->rx.realloc_index - 1);
1139 XGMAC_DMA_IOWRITE(channel, DMA_CH_RDTR_LO,
1140 lower_32_bits(rdata->rdesc_dma));
1141}
1142
1117static int xgbe_tx_poll(struct xgbe_channel *channel) 1143static int xgbe_tx_poll(struct xgbe_channel *channel)
1118{ 1144{
1119 struct xgbe_prv_data *pdata = channel->pdata; 1145 struct xgbe_prv_data *pdata = channel->pdata;
@@ -1171,7 +1197,6 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget)
1171{ 1197{
1172 struct xgbe_prv_data *pdata = channel->pdata; 1198 struct xgbe_prv_data *pdata = channel->pdata;
1173 struct xgbe_hw_if *hw_if = &pdata->hw_if; 1199 struct xgbe_hw_if *hw_if = &pdata->hw_if;
1174 struct xgbe_desc_if *desc_if = &pdata->desc_if;
1175 struct xgbe_ring *ring = channel->rx_ring; 1200 struct xgbe_ring *ring = channel->rx_ring;
1176 struct xgbe_ring_data *rdata; 1201 struct xgbe_ring_data *rdata;
1177 struct xgbe_packet_data *packet; 1202 struct xgbe_packet_data *packet;
@@ -1198,6 +1223,9 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget)
1198 cur_len = 0; 1223 cur_len = 0;
1199 1224
1200read_again: 1225read_again:
1226 if (ring->dirty > (XGBE_RX_DESC_CNT >> 3))
1227 xgbe_rx_refresh(channel);
1228
1201 rdata = XGBE_GET_DESC_DATA(ring, ring->cur); 1229 rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
1202 1230
1203 if (hw_if->dev_read(channel)) 1231 if (hw_if->dev_read(channel))
@@ -1285,16 +1313,6 @@ read_again:
1285 napi_gro_receive(&pdata->napi, skb); 1313 napi_gro_receive(&pdata->napi, skb);
1286 } 1314 }
1287 1315
1288 if (received) {
1289 desc_if->realloc_skb(channel);
1290
1291 /* Update the Rx Tail Pointer Register with address of
1292 * the last cleaned entry */
1293 rdata = XGBE_GET_DESC_DATA(ring, ring->rx.realloc_index - 1);
1294 XGMAC_DMA_IOWRITE(channel, DMA_CH_RDTR_LO,
1295 lower_32_bits(rdata->rdesc_dma));
1296 }
1297
1298 DBGPR("<--xgbe_rx_poll: received = %d\n", received); 1316 DBGPR("<--xgbe_rx_poll: received = %d\n", received);
1299 1317
1300 return received; 1318 return received;
@@ -1305,21 +1323,28 @@ static int xgbe_poll(struct napi_struct *napi, int budget)
1305 struct xgbe_prv_data *pdata = container_of(napi, struct xgbe_prv_data, 1323 struct xgbe_prv_data *pdata = container_of(napi, struct xgbe_prv_data,
1306 napi); 1324 napi);
1307 struct xgbe_channel *channel; 1325 struct xgbe_channel *channel;
1308 int processed; 1326 int ring_budget;
1327 int processed, last_processed;
1309 unsigned int i; 1328 unsigned int i;
1310 1329
1311 DBGPR("-->xgbe_poll: budget=%d\n", budget); 1330 DBGPR("-->xgbe_poll: budget=%d\n", budget);
1312 1331
1313 /* Cleanup Tx ring first */
1314 channel = pdata->channel;
1315 for (i = 0; i < pdata->channel_count; i++, channel++)
1316 xgbe_tx_poll(channel);
1317
1318 /* Process Rx ring next */
1319 processed = 0; 1332 processed = 0;
1320 channel = pdata->channel; 1333 ring_budget = budget / pdata->rx_ring_count;
1321 for (i = 0; i < pdata->channel_count; i++, channel++) 1334 do {
1322 processed += xgbe_rx_poll(channel, budget - processed); 1335 last_processed = processed;
1336
1337 channel = pdata->channel;
1338 for (i = 0; i < pdata->channel_count; i++, channel++) {
1339 /* Cleanup Tx ring first */
1340 xgbe_tx_poll(channel);
1341
1342 /* Process Rx ring next */
1343 if (ring_budget > (budget - processed))
1344 ring_budget = budget - processed;
1345 processed += xgbe_rx_poll(channel, ring_budget);
1346 }
1347 } while ((processed < budget) && (processed != last_processed));
1323 1348
1324 /* If we processed everything, we are done */ 1349 /* If we processed everything, we are done */
1325 if (processed < budget) { 1350 if (processed < budget) {