Page MenuHomeFreeBSD

D57436.id180189.diff
No OneTemporary

D57436.id180189.diff

diff --git a/sys/dev/aq/aq_fw2x.c b/sys/dev/aq/aq_fw2x.c
--- a/sys/dev/aq/aq_fw2x.c
+++ b/sys/dev/aq/aq_fw2x.c
@@ -207,8 +207,15 @@
static uint64_t
read64_(struct aq_hw* hw, uint32_t addr)
{
- uint64_t lo = AQ_READ_REG(hw, addr);
- uint64_t hi = AQ_READ_REG(hw, addr + 4);
+ uint64_t lo, hi, hi2;
+
+ hi = AQ_READ_REG(hw, addr + 4);
+ do {
+ hi2 = hi;
+ lo = AQ_READ_REG(hw, addr);
+ hi = AQ_READ_REG(hw, addr + 4);
+ } while (hi != hi2);
+
return (lo | (hi << 32));
}
diff --git a/sys/dev/aq/aq_hw.h b/sys/dev/aq/aq_hw.h
--- a/sys/dev/aq/aq_hw.h
+++ b/sys/dev/aq/aq_hw.h
@@ -37,14 +37,21 @@
#include <sys/types.h>
#include <sys/cdefs.h>
+#include <machine/atomic.h>
#include <machine/cpufunc.h>
+#include <machine/bus.h>
#include <sys/endian.h>
#include <net/ethernet.h>
#include "aq_common.h"
-#define AQ_WRITE_REG(hw, reg, value) writel(((hw)->hw_addr + (reg)), htole32(value))
+#define AQ_WRITE_REG(hw, reg, value) \
+ bus_space_write_4((hw)->hw_tag, (hw)->hw_handle, (reg), htole32(value))
-#define AQ_READ_REG(hw, reg) le32toh(readl((hw)->hw_addr + reg))
+#define AQ_HW_FLAG_ERR_UNPLUG 0x1UL
+
+struct aq_hw;
+extern uint32_t aq_hw_read_reg(struct aq_hw *hw, uint32_t reg);
+#define AQ_READ_REG(hw, reg) aq_hw_read_reg((hw), (reg))
#define AQ_WRITE_REG_BIT(hw, reg, msk, shift, value) do { \
@@ -137,7 +144,8 @@
struct aq_hw {
void *aq_dev;
- uint8_t *hw_addr;
+ bus_space_tag_t hw_tag;
+ bus_space_handle_t hw_handle;
uint32_t regs_size;
uint8_t mac_addr[ETHER_ADDR_LEN];
@@ -170,6 +178,8 @@
uint32_t mbox_addr;
struct aq_hw_fw_mbox mbox;
+ u_long flags;
+
uint32_t tx_rings_count;
};
diff --git a/sys/dev/aq/aq_hw.c b/sys/dev/aq/aq_hw.c
--- a/sys/dev/aq/aq_hw.c
+++ b/sys/dev/aq/aq_hw.c
@@ -51,9 +51,24 @@
int
aq_hw_err_from_flags(struct aq_hw *hw)
{
+ if (atomic_load_acq_long(&hw->flags) & AQ_HW_FLAG_ERR_UNPLUG)
+ return (ENXIO);
return (0);
}
+inline uint32_t
+aq_hw_read_reg(struct aq_hw *hw, uint32_t reg)
+{
+ uint32_t val = le32toh(bus_space_read_4(hw->hw_tag, hw->hw_handle, reg));
+
+ if (__predict_false(val == 0xFFFFFFFFU) &&
+ le32toh(bus_space_read_4(hw->hw_tag, hw->hw_handle, 0x10)) ==
+ 0xFFFFFFFFU)
+ atomic_set_rel_long(&hw->flags, AQ_HW_FLAG_ERR_UNPLUG);
+
+ return (val);
+}
+
static void
aq_hw_chip_features_init(struct aq_hw *hw, uint32_t *p)
{
@@ -123,14 +138,11 @@
{
AQ_DBG_ENTER();
- if (ver_actual->major_version >= ver_expected->major_version)
- return (true);
- if (ver_actual->minor_version >= ver_expected->minor_version)
- return (true);
- if (ver_actual->build_number >= ver_expected->build_number)
- return (true);
-
- return (false);
+ if (ver_actual->major_version != ver_expected->major_version)
+ return (ver_actual->major_version > ver_expected->major_version);
+ if (ver_actual->minor_version != ver_expected->minor_version)
+ return (ver_actual->minor_version > ver_expected->minor_version);
+ return (ver_actual->build_number >= ver_expected->build_number);
}
static int
@@ -660,7 +672,7 @@
reg_gen_irq_map_set(hw, 0x80 | adm_irq, 3);
- aq_hw_offload_set(hw);
+ err = aq_hw_offload_set(hw);
err_exit:
AQ_DBG_EXIT(err);
diff --git a/sys/dev/aq/aq_irq.c b/sys/dev/aq/aq_irq.c
--- a/sys/dev/aq/aq_irq.c
+++ b/sys/dev/aq/aq_irq.c
@@ -163,9 +163,9 @@
struct aq_dev *aq_dev = ring->dev;
struct aq_hw *hw = &aq_dev->hw;
- /* clear interrupt status */
itr_irq_status_clearlsw_set(hw, BIT(ring->msix));
- ring->stats.irq++;
+ AQ_HW_FLUSH();
+ counter_u64_add(ring->stats.irq, 1);
return (FILTER_SCHEDULE_THREAD);
}
@@ -178,8 +178,8 @@
aq_dev_t *aq_dev = arg;
struct aq_hw *hw = &aq_dev->hw;
- /* clear interrupt status */
itr_irq_status_clearlsw_set(hw, BIT(aq_dev->msix));
+ AQ_HW_FLUSH();
iflib_admin_intr_deferred(aq_dev->ctx);
diff --git a/sys/dev/aq/aq_main.c b/sys/dev/aq/aq_main.c
--- a/sys/dev/aq/aq_main.c
+++ b/sys/dev/aq/aq_main.c
@@ -353,7 +353,8 @@
softc->mmio_tag = rman_get_bustag(softc->mmio_res);
softc->mmio_handle = rman_get_bushandle(softc->mmio_res);
softc->mmio_size = rman_get_size(softc->mmio_res);
- softc->hw.hw_addr = (uint8_t*) softc->mmio_handle;
+ softc->hw.hw_tag = softc->mmio_tag;
+ softc->hw.hw_handle = softc->mmio_handle;
hw = &softc->hw;
hw->link_rate = aq_fw_speed_auto;
hw->itr = -1;
@@ -542,6 +543,42 @@
return (0);
}
+_Static_assert(sizeof(struct aq_ring_stats) % sizeof(counter_u64_t) == 0,
+ "aq_ring_stats must contain only counter_u64_t fields");
+
+static int
+aq_ring_stats_alloc(struct aq_ring *ring)
+{
+ counter_u64_t *c = (counter_u64_t *)&ring->stats;
+ int i, n = sizeof(ring->stats) / sizeof(counter_u64_t);
+
+ for (i = 0; i < n; i++) {
+ c[i] = counter_u64_alloc(M_NOWAIT);
+ if (c[i] == NULL) {
+ while (i-- > 0) {
+ counter_u64_free(c[i]);
+ c[i] = NULL;
+ }
+ return (ENOMEM);
+ }
+ }
+ return (0);
+}
+
+static void
+aq_ring_stats_free(struct aq_ring *ring)
+{
+ counter_u64_t *c = (counter_u64_t *)&ring->stats;
+ int i, n = sizeof(ring->stats) / sizeof(counter_u64_t);
+
+ for (i = 0; i < n; i++) {
+ if (c[i] != NULL) {
+ counter_u64_free(c[i]);
+ c[i] = NULL;
+ }
+ }
+}
+
/* Soft queue setup and teardown */
static int
aq_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs,
@@ -571,6 +608,13 @@
ring->dev = softc;
softc->tx_rings_count++;
+
+ rc = aq_ring_stats_alloc(ring);
+ if (rc != 0) {
+ device_printf(softc->dev,
+ "atlantic: tx_ring stats alloc fail\n");
+ goto fail;
+ }
}
AQ_DBG_EXIT(rc);
@@ -621,6 +665,13 @@
}
softc->rx_rings_count++;
+
+ rc = aq_ring_stats_alloc(ring);
+ if (rc != 0) {
+ device_printf(softc->dev,
+ "atlantic: rx_ring stats alloc fail\n");
+ goto fail;
+ }
}
AQ_DBG_EXIT(rc);
@@ -643,6 +694,7 @@
for (i = 0; i < softc->tx_rings_count; i++) {
if (softc->tx_rings[i]) {
+ aq_ring_stats_free(softc->tx_rings[i]);
free(softc->tx_rings[i], M_AQ);
softc->tx_rings[i] = NULL;
}
@@ -650,6 +702,7 @@
softc->tx_rings_count = 0;
for (i = 0; i < softc->rx_rings_count; i++) {
if (softc->rx_rings[i]){
+ aq_ring_stats_free(softc->rx_rings[i]);
free(softc->rx_rings[i], M_AQ);
softc->rx_rings[i] = NULL;
}
@@ -673,6 +726,8 @@
softc = iflib_get_softc(ctx);
hw = &softc->hw;
+ atomic_store_rel_long(&hw->flags, 0);
+
hw->tx_rings_count = softc->tx_rings_count;
err = aq_hw_init(&softc->hw, softc->hw.mac_addr, softc->msix,
@@ -1080,7 +1135,7 @@
aq_vlans[i].location = i;
aq_vlans[i].queue = 0xFF;
aq_vlans[i].vlan_id = vlan_tag;
- bit_pos = vlan_tag;
+ bit_pos = vlan_tag + 1;
} else {
aq_vlans[i].enable = false;
}
@@ -1319,14 +1374,10 @@
CTLFLAG_RD, NULL, "Queue Name");
queue_list = SYSCTL_CHILDREN(queue_node);
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_pkts",
+ SYSCTL_ADD_COUNTER_U64(ctx, queue_list, OID_AUTO, "tx_pkts",
CTLFLAG_RD, &(ring->stats.tx_pkts), "TX Packets");
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_bytes",
+ SYSCTL_ADD_COUNTER_U64(ctx, queue_list, OID_AUTO, "tx_bytes",
CTLFLAG_RD, &(ring->stats.tx_bytes), "TX Octets");
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_drops",
- CTLFLAG_RD, &(ring->stats.tx_drops), "TX Drops");
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_queue_full",
- CTLFLAG_RD, &(ring->stats.tx_queue_full), "TX Queue Full");
SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "tx_head",
CTLTYPE_UINT | CTLFLAG_RD, ring, 0,
aq_sysctl_print_tx_head, "IU", "ring head pointer");
@@ -1342,15 +1393,13 @@
CTLFLAG_RD, NULL, "Queue Name");
queue_list = SYSCTL_CHILDREN(queue_node);
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_pkts",
+ SYSCTL_ADD_COUNTER_U64(ctx, queue_list, OID_AUTO, "rx_pkts",
CTLFLAG_RD, &(ring->stats.rx_pkts), "RX Packets");
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes",
+ SYSCTL_ADD_COUNTER_U64(ctx, queue_list, OID_AUTO, "rx_bytes",
CTLFLAG_RD, &(ring->stats.rx_bytes), "TX Octets");
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "jumbo_pkts",
- CTLFLAG_RD, &(ring->stats.jumbo_pkts), "Jumbo Packets");
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_err",
+ SYSCTL_ADD_COUNTER_U64(ctx, queue_list, OID_AUTO, "rx_err",
CTLFLAG_RD, &(ring->stats.rx_err), "RX Errors");
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irq",
+ SYSCTL_ADD_COUNTER_U64(ctx, queue_list, OID_AUTO, "irq",
CTLFLAG_RD, &(ring->stats.irq), "RX interrupts");
SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rx_head",
CTLTYPE_UINT | CTLFLAG_RD, ring, 0,
diff --git a/sys/dev/aq/aq_media.c b/sys/dev/aq/aq_media.c
--- a/sys/dev/aq/aq_media.c
+++ b/sys/dev/aq/aq_media.c
@@ -203,7 +203,7 @@
// ifconfig eth0 none
ifmedia_add(aq_dev->media, IFM_ETHER | IFM_NONE, 0, NULL);
- // ifconfig eth0 auto
+ ifmedia_add(aq_dev->media, IFM_ETHER | IFM_AUTO, 0, NULL);
aq_add_media_types(aq_dev, IFM_AUTO);
if (AQ_HW_SUPPORT_SPEED(aq_dev, AQ_LINK_100M))
diff --git a/sys/dev/aq/aq_ring.h b/sys/dev/aq/aq_ring.h
--- a/sys/dev/aq/aq_ring.h
+++ b/sys/dev/aq/aq_ring.h
@@ -35,6 +35,8 @@
#ifndef _AQ_RING_H_
#define _AQ_RING_H_
+#include <sys/counter.h>
+
#include "aq_hw.h"
#define REFILL_THRESHOLD 128
@@ -130,16 +132,13 @@
} __attribute__((__packed__)) aq_txc_desc_t;
struct aq_ring_stats {
- uint64_t rx_pkts;
- uint64_t rx_bytes;
- uint64_t jumbo_pkts;
- uint64_t rx_err;
- uint64_t irq;
-
- uint64_t tx_pkts;
- uint64_t tx_bytes;
- uint64_t tx_drops;
- uint64_t tx_queue_full;
+ counter_u64_t rx_pkts;
+ counter_u64_t rx_bytes;
+ counter_u64_t rx_err;
+ counter_u64_t irq;
+
+ counter_u64_t tx_pkts;
+ counter_u64_t tx_bytes;
};
struct aq_dev;
diff --git a/sys/dev/aq/aq_ring.c b/sys/dev/aq/aq_ring.c
--- a/sys/dev/aq/aq_ring.c
+++ b/sys/dev/aq/aq_ring.c
@@ -292,16 +292,10 @@
cnt++;
} else {
- /* LRO/Jumbo: wait for whole packet be in the ring */
- if (rx_desc[i].wb.rsc_cnt) {
- i = rx_desc[i].wb.next_desp;
- iter++;
- continue;
- } else {
- iter++;
- i = aq_next(i, ring->rx_size - 1);
- continue;
- }
+ /* Jumbo frame spans descriptors; advance. */
+ iter++;
+ i = aq_next(i, ring->rx_size - 1);
+ continue;
}
}
@@ -356,13 +350,19 @@
i = 0;
do {
+ if (i >= aq_dev->sctx->isc_rx_nsegments) {
+ counter_u64_add(ring->stats.rx_err, 1);
+ rc = (EBADMSG);
+ goto exit;
+ }
+
rx_desc = (aq_rx_desc_t *) &ring->rx_descs[cidx];
trace_aq_rx_descr(ring->index, cidx,
(volatile uint64_t *)rx_desc);
if ((rx_desc->wb.rx_stat & BIT(0)) != 0) {
- ring->stats.rx_err++;
+ counter_u64_add(ring->stats.rx_err, 1);
rc = (EBADMSG);
goto exit;
}
@@ -397,8 +397,8 @@
ri->iri_len = total_len;
ri->iri_nfrags = i;
- ring->stats.rx_bytes += total_len;
- ring->stats.rx_pkts++;
+ counter_u64_add(ring->stats.rx_bytes, total_len);
+ counter_u64_add(ring->stats.rx_pkts, 1);
exit:
AQ_DBG_EXIT(rc);
@@ -551,8 +551,8 @@
trace_aq_tx_descr(ring->index, pidx, (volatile void*)txd);
ring->tx_tail = pidx;
- ring->stats.tx_pkts++;
- ring->stats.tx_bytes += pay_len;
+ counter_u64_add(ring->stats.tx_pkts, 1);
+ counter_u64_add(ring->stats.tx_bytes, pay_len);
pi->ipi_new_pidx = pidx;
@@ -592,6 +592,11 @@
head = tdm_tx_desc_head_ptr_get(&aq_dev->hw, ring->index);
AQ_DBG_PRINT("swhead %d hwhead %d", ring->tx_head, head);
+ if (head >= ring->tx_size) {
+ /* Malformed HW head; report no completions. */
+ goto done;
+ }
+
if (ring->tx_head == head) {
avail = 0; // ring->tx_size;
goto done;

File Metadata

Mime Type
text/plain
Expires
Sat, Jul 18, 1:16 AM (12 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35129297
Default Alt Text
D57436.id180189.diff (11 KB)

Event Timeline