hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/net/ethernet/sfc/nic.c
....@@ -1,11 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /****************************************************************************
23 * Driver for Solarflare network controllers and boards
34 * Copyright 2005-2006 Fen Systems Ltd.
45 * 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.
96 */
107
118 #include <linux/bitops.h>
....@@ -23,6 +20,7 @@
2320 #include "farch_regs.h"
2421 #include "io.h"
2522 #include "workarounds.h"
23
+#include "mcdi_pcol.h"
2624
2725 /**************************************************************************
2826 *
....@@ -34,8 +32,8 @@
3432 int efx_nic_alloc_buffer(struct efx_nic *efx, struct efx_buffer *buffer,
3533 unsigned int len, gfp_t gfp_flags)
3634 {
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);
3937 if (!buffer->addr)
4038 return -ENOMEM;
4139 buffer->len = len;
....@@ -92,6 +90,7 @@
9290 efx->pci_dev->irq);
9391 goto fail1;
9492 }
93
+ efx->irqs_hooked = true;
9594 return 0;
9695 }
9796
....@@ -131,6 +130,7 @@
131130 #endif
132131 }
133132
133
+ efx->irqs_hooked = true;
134134 return 0;
135135
136136 fail2:
....@@ -156,6 +156,8 @@
156156 efx->net_dev->rx_cpu_rmap = NULL;
157157 #endif
158158
159
+ if (!efx->irqs_hooked)
160
+ return;
159161 if (EFX_INT_MODE_USE_MSI(efx)) {
160162 /* Disable MSI/MSI-X interrupts */
161163 efx_for_each_channel(channel, efx)
....@@ -165,6 +167,7 @@
165167 /* Disable legacy interrupt */
166168 free_irq(efx->legacy_irq, efx);
167169 }
170
+ efx->irqs_hooked = false;
168171 }
169172
170173 /* Register dump */
....@@ -474,6 +477,49 @@
474477 }
475478
476479 /**
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
+/**
477523 * efx_nic_update_stats - Convert statistics DMA buffer to array of u64
478524 * @desc: Array of &struct efx_hw_stat_desc describing the DMA buffer
479525 * layout. DMA widths of 0, 16, 32 and 64 are supported; where