diff options
Diffstat (limited to 'drivers/net/sfc/siena.c')
-rw-r--r-- | drivers/net/sfc/siena.c | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c index 1619fb5a64f5..727b4228e081 100644 --- a/drivers/net/sfc/siena.c +++ b/drivers/net/sfc/siena.c | |||
@@ -12,6 +12,8 @@ | |||
12 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
13 | #include <linux/pci.h> | 13 | #include <linux/pci.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/slab.h> | ||
16 | #include <linux/random.h> | ||
15 | #include "net_driver.h" | 17 | #include "net_driver.h" |
16 | #include "bitfield.h" | 18 | #include "bitfield.h" |
17 | #include "efx.h" | 19 | #include "efx.h" |
@@ -273,6 +275,9 @@ static int siena_probe_nic(struct efx_nic *efx) | |||
273 | goto fail5; | 275 | goto fail5; |
274 | } | 276 | } |
275 | 277 | ||
278 | get_random_bytes(&nic_data->ipv6_rss_key, | ||
279 | sizeof(nic_data->ipv6_rss_key)); | ||
280 | |||
276 | return 0; | 281 | return 0; |
277 | 282 | ||
278 | fail5: | 283 | fail5: |
@@ -292,6 +297,7 @@ fail1: | |||
292 | */ | 297 | */ |
293 | static int siena_init_nic(struct efx_nic *efx) | 298 | static int siena_init_nic(struct efx_nic *efx) |
294 | { | 299 | { |
300 | struct siena_nic_data *nic_data = efx->nic_data; | ||
295 | efx_oword_t temp; | 301 | efx_oword_t temp; |
296 | int rc; | 302 | int rc; |
297 | 303 | ||
@@ -318,6 +324,20 @@ static int siena_init_nic(struct efx_nic *efx) | |||
318 | EFX_SET_OWORD_FIELD(temp, FRF_BZ_RX_INGR_EN, 1); | 324 | EFX_SET_OWORD_FIELD(temp, FRF_BZ_RX_INGR_EN, 1); |
319 | efx_writeo(efx, &temp, FR_AZ_RX_CFG); | 325 | efx_writeo(efx, &temp, FR_AZ_RX_CFG); |
320 | 326 | ||
327 | /* Enable IPv6 RSS */ | ||
328 | BUILD_BUG_ON(sizeof(nic_data->ipv6_rss_key) != | ||
329 | 2 * sizeof(temp) + FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH / 8 || | ||
330 | FRF_CZ_RX_RSS_IPV6_TKEY_HI_LBN != 0); | ||
331 | memcpy(&temp, nic_data->ipv6_rss_key, sizeof(temp)); | ||
332 | efx_writeo(efx, &temp, FR_CZ_RX_RSS_IPV6_REG1); | ||
333 | memcpy(&temp, nic_data->ipv6_rss_key + sizeof(temp), sizeof(temp)); | ||
334 | efx_writeo(efx, &temp, FR_CZ_RX_RSS_IPV6_REG2); | ||
335 | EFX_POPULATE_OWORD_2(temp, FRF_CZ_RX_RSS_IPV6_THASH_ENABLE, 1, | ||
336 | FRF_CZ_RX_RSS_IPV6_IP_THASH_ENABLE, 1); | ||
337 | memcpy(&temp, nic_data->ipv6_rss_key + 2 * sizeof(temp), | ||
338 | FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH / 8); | ||
339 | efx_writeo(efx, &temp, FR_CZ_RX_RSS_IPV6_REG3); | ||
340 | |||
321 | if (efx_nic_rx_xoff_thresh >= 0 || efx_nic_rx_xon_thresh >= 0) | 341 | if (efx_nic_rx_xoff_thresh >= 0 || efx_nic_rx_xon_thresh >= 0) |
322 | /* No MCDI operation has been defined to set thresholds */ | 342 | /* No MCDI operation has been defined to set thresholds */ |
323 | EFX_ERR(efx, "ignoring RX flow control thresholds\n"); | 343 | EFX_ERR(efx, "ignoring RX flow control thresholds\n"); |
@@ -455,8 +475,17 @@ static int siena_try_update_nic_stats(struct efx_nic *efx) | |||
455 | 475 | ||
456 | static void siena_update_nic_stats(struct efx_nic *efx) | 476 | static void siena_update_nic_stats(struct efx_nic *efx) |
457 | { | 477 | { |
458 | while (siena_try_update_nic_stats(efx) == -EAGAIN) | 478 | int retry; |
459 | cpu_relax(); | 479 | |
480 | /* If we're unlucky enough to read statistics wduring the DMA, wait | ||
481 | * up to 10ms for it to finish (typically takes <500us) */ | ||
482 | for (retry = 0; retry < 100; ++retry) { | ||
483 | if (siena_try_update_nic_stats(efx) == 0) | ||
484 | return; | ||
485 | udelay(100); | ||
486 | } | ||
487 | |||
488 | /* Use the old values instead */ | ||
460 | } | 489 | } |
461 | 490 | ||
462 | static void siena_start_nic_stats(struct efx_nic *efx) | 491 | static void siena_start_nic_stats(struct efx_nic *efx) |