diff options
author | Lendacky, Thomas <Thomas.Lendacky@amd.com> | 2014-07-02 14:04:46 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-07-08 00:38:06 -0400 |
commit | 9867e8fb2c45888cc594457914dcbba599f086c8 (patch) | |
tree | 9a64c6124f280b9368f1f7789ebf1cca855b7886 /drivers/net/ethernet/amd/xgbe/xgbe-drv.c | |
parent | ff42606eed00bc065365f55269d558c06b968594 (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.c | 91 |
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 | ||
1127 | static 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 | |||
1117 | static int xgbe_tx_poll(struct xgbe_channel *channel) | 1143 | static 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 | ||
1200 | read_again: | 1225 | read_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) { |