.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /**************************************************************************** |
---|
2 | 3 | * Driver for Solarflare network controllers and boards |
---|
3 | 4 | * Copyright 2005-2006 Fen Systems Ltd. |
---|
4 | 5 | * Copyright 2006-2013 Solarflare Communications Inc. |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify it |
---|
7 | | - * under the terms of the GNU General Public License version 2 as published |
---|
8 | | - * by the Free Software Foundation, incorporated herein by reference. |
---|
9 | 6 | */ |
---|
10 | 7 | |
---|
11 | 8 | #include <linux/bitops.h> |
---|
.. | .. |
---|
23 | 20 | #include "farch_regs.h" |
---|
24 | 21 | #include "io.h" |
---|
25 | 22 | #include "workarounds.h" |
---|
| 23 | +#include "mcdi_pcol.h" |
---|
26 | 24 | |
---|
27 | 25 | /************************************************************************** |
---|
28 | 26 | * |
---|
.. | .. |
---|
34 | 32 | int efx_nic_alloc_buffer(struct efx_nic *efx, struct efx_buffer *buffer, |
---|
35 | 33 | unsigned int len, gfp_t gfp_flags) |
---|
36 | 34 | { |
---|
37 | | - buffer->addr = dma_zalloc_coherent(&efx->pci_dev->dev, len, |
---|
38 | | - &buffer->dma_addr, gfp_flags); |
---|
| 35 | + buffer->addr = dma_alloc_coherent(&efx->pci_dev->dev, len, |
---|
| 36 | + &buffer->dma_addr, gfp_flags); |
---|
39 | 37 | if (!buffer->addr) |
---|
40 | 38 | return -ENOMEM; |
---|
41 | 39 | buffer->len = len; |
---|
.. | .. |
---|
92 | 90 | efx->pci_dev->irq); |
---|
93 | 91 | goto fail1; |
---|
94 | 92 | } |
---|
| 93 | + efx->irqs_hooked = true; |
---|
95 | 94 | return 0; |
---|
96 | 95 | } |
---|
97 | 96 | |
---|
.. | .. |
---|
131 | 130 | #endif |
---|
132 | 131 | } |
---|
133 | 132 | |
---|
| 133 | + efx->irqs_hooked = true; |
---|
134 | 134 | return 0; |
---|
135 | 135 | |
---|
136 | 136 | fail2: |
---|
.. | .. |
---|
156 | 156 | efx->net_dev->rx_cpu_rmap = NULL; |
---|
157 | 157 | #endif |
---|
158 | 158 | |
---|
| 159 | + if (!efx->irqs_hooked) |
---|
| 160 | + return; |
---|
159 | 161 | if (EFX_INT_MODE_USE_MSI(efx)) { |
---|
160 | 162 | /* Disable MSI/MSI-X interrupts */ |
---|
161 | 163 | efx_for_each_channel(channel, efx) |
---|
.. | .. |
---|
165 | 167 | /* Disable legacy interrupt */ |
---|
166 | 168 | free_irq(efx->legacy_irq, efx); |
---|
167 | 169 | } |
---|
| 170 | + efx->irqs_hooked = false; |
---|
168 | 171 | } |
---|
169 | 172 | |
---|
170 | 173 | /* Register dump */ |
---|
.. | .. |
---|
474 | 477 | } |
---|
475 | 478 | |
---|
476 | 479 | /** |
---|
| 480 | + * efx_nic_copy_stats - Copy stats from the DMA buffer in to an |
---|
| 481 | + * intermediate buffer. This is used to get a consistent |
---|
| 482 | + * set of stats while the DMA buffer can be written at any time |
---|
| 483 | + * by the NIC. |
---|
| 484 | + * @efx: The associated NIC. |
---|
| 485 | + * @dest: Destination buffer. Must be the same size as the DMA buffer. |
---|
| 486 | + */ |
---|
| 487 | +int efx_nic_copy_stats(struct efx_nic *efx, __le64 *dest) |
---|
| 488 | +{ |
---|
| 489 | + __le64 *dma_stats = efx->stats_buffer.addr; |
---|
| 490 | + __le64 generation_start, generation_end; |
---|
| 491 | + int rc = 0, retry; |
---|
| 492 | + |
---|
| 493 | + if (!dest) |
---|
| 494 | + return 0; |
---|
| 495 | + |
---|
| 496 | + if (!dma_stats) |
---|
| 497 | + goto return_zeroes; |
---|
| 498 | + |
---|
| 499 | + /* If we're unlucky enough to read statistics during the DMA, wait |
---|
| 500 | + * up to 10ms for it to finish (typically takes <500us) |
---|
| 501 | + */ |
---|
| 502 | + for (retry = 0; retry < 100; ++retry) { |
---|
| 503 | + generation_end = dma_stats[efx->num_mac_stats - 1]; |
---|
| 504 | + if (generation_end == EFX_MC_STATS_GENERATION_INVALID) |
---|
| 505 | + goto return_zeroes; |
---|
| 506 | + rmb(); |
---|
| 507 | + memcpy(dest, dma_stats, efx->num_mac_stats * sizeof(__le64)); |
---|
| 508 | + rmb(); |
---|
| 509 | + generation_start = dma_stats[MC_CMD_MAC_GENERATION_START]; |
---|
| 510 | + if (generation_end == generation_start) |
---|
| 511 | + return 0; /* return good data */ |
---|
| 512 | + udelay(100); |
---|
| 513 | + } |
---|
| 514 | + |
---|
| 515 | + rc = -EIO; |
---|
| 516 | + |
---|
| 517 | +return_zeroes: |
---|
| 518 | + memset(dest, 0, efx->num_mac_stats * sizeof(u64)); |
---|
| 519 | + return rc; |
---|
| 520 | +} |
---|
| 521 | + |
---|
| 522 | +/** |
---|
477 | 523 | * efx_nic_update_stats - Convert statistics DMA buffer to array of u64 |
---|
478 | 524 | * @desc: Array of &struct efx_hw_stat_desc describing the DMA buffer |
---|
479 | 525 | * layout. DMA widths of 0, 16, 32 and 64 are supported; where |
---|