Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F164253991
D58434.id182897.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
31 KB
Referenced Files
None
Subscribers
None
D58434.id182897.diff
View Options
diff --git a/sys/dev/aq/aq2_fw.c b/sys/dev/aq/aq2_fw.c
--- a/sys/dev/aq/aq2_fw.c
+++ b/sys/dev/aq/aq2_fw.c
@@ -32,6 +32,7 @@
#include "aq_hw_llh.h"
#include "aq2_hw.h"
#include "aq_fw.h"
+#include "aq_dbg.h"
static int aq2_fw_reset(struct aq_hw *hw);
static int aq2_fw_set_mode(struct aq_hw *hw, enum aq_hw_fw_mpi_state mode,
@@ -40,6 +41,7 @@
enum aq_fw_link_speed *speed, enum aq_fw_link_fc *fc);
static int aq2_fw_get_mac_addr(struct aq_hw *hw, uint8_t *mac);
static int aq2_fw_get_stats(struct aq_hw *hw, struct aq_hw_stats *stats);
+static int aq2_fw_get_temp(struct aq_hw *hw, int *temp_mc);
/* Coherent OUT-window read, bracketed by the transaction id. */
static int
@@ -97,6 +99,7 @@
device_printf(hw->dev, "A2 firmware reboot timeout\n");
return (ETIMEDOUT);
}
+ trace(hw, dbg_init, "aq2> F/W boot started, %d ms", (20000 - timo) / 100);
for (timo = 200000; timo > 0; timo--) {
v = AQ_READ_REG(hw, AQ2_MIF_BOOT_REG);
@@ -111,6 +114,8 @@
device_printf(hw->dev, "A2 firmware restart timeout\n");
return (ETIMEDOUT);
}
+ trace(hw, dbg_init, "aq2> F/W boot complete, %d ms",
+ (200000 - timo) / 100);
v = AQ_READ_REG(hw, AQ2_MIF_BOOT_REG);
if (v & AQ2_MIF_BOOT_FAILED) {
@@ -152,9 +157,12 @@
iface = "unknown";
break;
}
- device_printf(hw->dev, "Atlantic 2 %s, firmware %u.%u.%u\n", iface,
- hw->fw_version.major_version, hw->fw_version.minor_version,
- hw->fw_version.build_number);
+ if (!hw->fw_announced || bootverbose) {
+ device_printf(hw->dev, "Atlantic 2 %s, firmware %u.%u.%u\n",
+ iface, hw->fw_version.major_version,
+ hw->fw_version.minor_version, hw->fw_version.build_number);
+ hw->fw_announced = true;
+ }
/* Base row added to every action-resolver-table index. */
err = aq2_fw_interface_buffer_read(hw,
@@ -165,6 +173,8 @@
hw->art_filter_base_index = ((filter_caps[2] &
AQ2_FW_INTERFACE_OUT_FILTER_CAPS3_RESOLVER_BASE_INDEX) >>
AQ2_FW_INTERFACE_OUT_FILTER_CAPS3_RESOLVER_BASE_INDEX_SHIFT) * 8;
+ trace(hw, dbg_init, "aq2> ART filter base index = %u",
+ hw->art_filter_base_index);
return (0);
}
@@ -173,11 +183,17 @@
static int
aq2_fw_wait_shared_ack(struct aq_hw *hw)
{
+ int err;
+
AQ_WRITE_REG(hw, AQ2_MIF_HOST_FINISHED_STATUS_WRITE_REG,
AQ2_MIF_HOST_FINISHED_STATUS_ACK);
- return (AQ_HW_WAIT_FOR((AQ_READ_REG(hw,
+ err = AQ_HW_WAIT_FOR((AQ_READ_REG(hw,
AQ2_MIF_HOST_FINISHED_STATUS_READ_REG) &
- AQ2_MIF_HOST_FINISHED_STATUS_ACK) == 0, 100, 1000));
+ AQ2_MIF_HOST_FINISHED_STATUS_ACK) == 0, 100, 1000);
+ if (err != 0)
+ trace_error(hw, dbg_fw, "aq2> shared buffer ack timed out");
+
+ return (err);
}
static int
@@ -203,6 +219,9 @@
v &= ~AQ2_FW_INTERFACE_IN_REQUEST_POLICY_PROMISC_RX_QUEUE_TX_INDEX;
AQ_WRITE_REG(hw, AQ2_FW_INTERFACE_IN_REQUEST_POLICY_REG, v);
+ trace(hw, dbg_init, "aq2> reset: mtu %u, request policy %#x",
+ HW_ATL_B0_MTU_JUMBO, v);
+
err = aq2_fw_wait_shared_ack(hw);
if (err != 0)
device_printf(hw->dev, "A2 firmware reset timed out\n");
@@ -225,9 +244,11 @@
mac_addr[0] = htole32(mac_addr[0]);
mac_addr[1] = htole32(mac_addr[1]);
memcpy(mac, (uint8_t *)mac_addr, ETHER_ADDR_LEN);
+ trace(hw, dbg_init, "aq2> MAC addr %6D", mac, ":");
return (0);
}
+/* No fw_mtx: the IN window is written only from iflib-serialised paths. */
static int
aq2_fw_set_mode(struct aq_hw *hw, enum aq_hw_fw_mpi_state mode,
enum aq_fw_link_speed speed)
@@ -279,6 +300,9 @@
AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE_SHUTDOWN);
}
+ trace(hw, dbg_init, "aq2> set mode %d, speed mask %#x, link options %#x",
+ mode, speed, v);
+
/* Options acked before ACTIVE so bring-up negotiates the new mask. */
AQ_WRITE_REG(hw, AQ2_FW_INTERFACE_IN_LINK_OPTIONS_REG, v);
if (mode == MPI_INIT) {
@@ -338,6 +362,9 @@
if (fcp != NULL)
*fcp = fc;
+ trace_detail(hw, dbg_init,
+ "aq2> get mode: link status %#x, speed %d, fc %d", v, speed, fc);
+
return (0);
}
@@ -400,8 +427,11 @@
err = aq2_fw_interface_buffer_read(hw, AQ2_FW_INTERFACE_OUT_STATS_REG,
(uint32_t *)&u, sizeof(u));
- if (err != 0)
+ if (err != 0) {
+ trace_error(hw, dbg_fw,
+ "aq2> statistics read FAILED, error %d", err);
return (err);
+ }
if (hw->aq2_iface == AQ2_FW_INTERFACE_OUT_VERSION_IFACE_VER_A0) {
stats->uprc = u.a0.rx_unicast_frames;
@@ -434,16 +464,46 @@
stats->bptc = u.b0.tx_broadcast_frames;
stats->erpt = u.b0.tx_errors;
stats->ptc = u.b0.tx_good_frames;
+ } else {
+ trace_warn(hw, dbg_fw,
+ "aq2> unknown F/W interface version %u, no statistics",
+ hw->aq2_iface);
}
return (0);
}
+static int
+aq2_fw_get_temp(struct aq_hw *hw, int *temp_mc)
+{
+ uint32_t raw;
+ int err;
+
+ err = aq2_fw_interface_buffer_read(hw,
+ AQ2_FW_INTERFACE_OUT_PHY_HEALTH_MONITOR_REG, &raw, sizeof(raw));
+ if (err != 0)
+ return (err);
+
+ /* The F/W zeroes the block until the PHY reports in. */
+ if ((raw & AQ2_FW_INTERFACE_OUT_PHY_HEALTH_MONITOR_READY) == 0) {
+ trace_detail(hw, dbg_fw, "aq2> PHY health monitor not ready");
+ return (ENXIO);
+ }
+
+ /* F/W reports whole degrees Celsius. */
+ *temp_mc = (int)(int8_t)((raw &
+ AQ2_FW_INTERFACE_OUT_PHY_TEMPERATURE) >>
+ AQ2_FW_INTERFACE_OUT_PHY_TEMPERATURE_S) * 1000;
+
+ return (0);
+}
+
const struct aq_firmware_ops aq2_fw_ops = {
.reset = aq2_fw_reset,
.set_mode = aq2_fw_set_mode,
.get_mode = aq2_fw_get_mode,
.get_mac_addr = aq2_fw_get_mac_addr,
.get_stats = aq2_fw_get_stats,
+ .get_temp = aq2_fw_get_temp,
.led_control = NULL,
};
diff --git a/sys/dev/aq/aq2_hw.h b/sys/dev/aq/aq2_hw.h
--- a/sys/dev/aq/aq2_hw.h
+++ b/sys/dev/aq/aq2_hw.h
@@ -229,6 +229,11 @@
#define AQ2_FW_INTERFACE_OUT_VERSION_IFACE_VER_A0 0
#define AQ2_FW_INTERFACE_OUT_VERSION_IFACE_VER_B0 1
+#define AQ2_FW_INTERFACE_OUT_PHY_HEALTH_MONITOR_REG 0x13620
+#define AQ2_FW_INTERFACE_OUT_PHY_HEALTH_MONITOR_READY 0x00000001
+#define AQ2_FW_INTERFACE_OUT_PHY_TEMPERATURE 0x0000ff00
+#define AQ2_FW_INTERFACE_OUT_PHY_TEMPERATURE_S 8
+
#define AQ2_FW_INTERFACE_OUT_STATS_REG 0x13700
#define AQ2_FW_INTERFACE_OUT_LINK_STATUS_REG 0x13014
diff --git a/sys/dev/aq/aq_dbg.h b/sys/dev/aq/aq_dbg.h
--- a/sys/dev/aq/aq_dbg.h
+++ b/sys/dev/aq/aq_dbg.h
@@ -40,6 +40,8 @@
#include <sys/systm.h>
#include <sys/syslog.h>
+
+#include "aq_device.h"
/*
Debug levels:
0 - no debug
@@ -109,24 +111,50 @@
#define __FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
-extern int aq_dbg_level;
-extern uint32_t aq_dbg_categories;
-
-#define aq_log_base(_lvl, _fmt, args...) do { if (aq_dbg_level >= (_lvl)) printf( "atlantic: " _fmt "\n", ##args); } while (0)
-
-#define aq_trace_base(_lvl, _cat, _fmt, args...) do { if (aq_dbg_level >= (_lvl) && ((_cat) & aq_dbg_categories)) { printf( "atlantic: " _fmt " @%s,%d\n", ##args, __FILENAME__, __LINE__); }} while (0)
-
-#define aq_log_warn(_fmt, args...) aq_log_base(lvl_warn, "/!\\ " _fmt, ##args)
-#define aq_log(_fmt, args...) aq_log_base(lvl_trace, _fmt, ##args)
-#define aq_log_detail(_fmt, args...) aq_log_base(lvl_detail, _fmt, ##args)
-
-#define trace_error(_cat,_fmt, args...) aq_trace_base(lvl_error, _cat, "[!] " _fmt, ##args)
-#define trace_warn(_cat, _fmt, args...) aq_trace_base(lvl_warn, _cat, "/!\\ " _fmt, ##args)
-#define trace(_cat, _fmt, args...) aq_trace_base(lvl_trace, _cat, _fmt, ##args)
-#define trace_detail(_cat, _fmt, args...) aq_trace_base(lvl_detail, _cat, _fmt, ##args)
-
-void trace_aq_tx_descr(int ring_idx, unsigned int pointer, volatile uint64_t descr[2]);
-void trace_aq_rx_descr(int ring_idx, unsigned int pointer, volatile uint64_t descr[2]);
-void trace_aq_tx_context_descr(int ring_idx, unsigned int pointer, volatile uint64_t descr[2]);
+#define AQ_DBG_LEVEL_DEFAULT lvl_error
+#define AQ_DBG_CATEGORIES_DEFAULT (dbg_init | dbg_config | dbg_tx | \
+ dbg_rx | dbg_intr | dbg_fw)
+
+/* NULL until aq_if_attach_pre() wires it up; traces run before that. */
+#define AQ_DBG_SOFTC(_hw) ((struct aq_dev *)(_hw)->aq_dev)
+
+#define aq_log_base(_hw, _lvl, _fmt, args...) do { \
+ const struct aq_dev *_sc = AQ_DBG_SOFTC(_hw); \
+ \
+ if (_sc != NULL && _sc->dbg_level >= (_lvl)) \
+ device_printf((_hw)->dev, _fmt "\n", ##args); \
+} while (0)
+
+#define aq_trace_base(_hw, _lvl, _cat, _fmt, args...) do { \
+ const struct aq_dev *_sc = AQ_DBG_SOFTC(_hw); \
+ \
+ if (_sc != NULL && _sc->dbg_level >= (_lvl) && \
+ ((_cat) & _sc->dbg_categories)) \
+ device_printf((_hw)->dev, _fmt " @%s,%d\n", ##args, \
+ __FILENAME__, __LINE__); \
+} while (0)
+
+#define aq_log_warn(_hw, _fmt, args...) \
+ aq_log_base(_hw, lvl_warn, "/!\\ " _fmt, ##args)
+#define aq_log(_hw, _fmt, args...) \
+ aq_log_base(_hw, lvl_trace, _fmt, ##args)
+#define aq_log_detail(_hw, _fmt, args...) \
+ aq_log_base(_hw, lvl_detail, _fmt, ##args)
+
+#define trace_error(_hw, _cat, _fmt, args...) \
+ aq_trace_base(_hw, lvl_error, _cat, "[!] " _fmt, ##args)
+#define trace_warn(_hw, _cat, _fmt, args...) \
+ aq_trace_base(_hw, lvl_warn, _cat, "/!\\ " _fmt, ##args)
+#define trace(_hw, _cat, _fmt, args...) \
+ aq_trace_base(_hw, lvl_trace, _cat, _fmt, ##args)
+#define trace_detail(_hw, _cat, _fmt, args...) \
+ aq_trace_base(_hw, lvl_detail, _cat, _fmt, ##args)
+
+void trace_aq_tx_descr(struct aq_hw *hw, int ring_idx, unsigned int pointer,
+ volatile uint64_t descr[2]);
+void trace_aq_rx_descr(struct aq_hw *hw, int ring_idx, unsigned int pointer,
+ volatile uint64_t descr[2]);
+void trace_aq_tx_context_descr(struct aq_hw *hw, int ring_idx,
+ unsigned int pointer, volatile uint64_t descr[2]);
#endif // AQ_DBG_H
diff --git a/sys/dev/aq/aq_dbg.c b/sys/dev/aq/aq_dbg.c
--- a/sys/dev/aq/aq_dbg.c
+++ b/sys/dev/aq/aq_dbg.c
@@ -45,18 +45,13 @@
#include "aq_dbg.h"
-int aq_dbg_level = lvl_error;
-uint32_t aq_dbg_categories = dbg_init | dbg_config | dbg_tx | dbg_rx | dbg_intr | dbg_fw;
-
-
-
#define DESCR_FIELD(DESCR, BIT_BEGIN, BIT_END) \
((DESCR >> BIT_END) &\
(BIT(BIT_BEGIN - BIT_END + 1) -1))
#define __field(TYPE, VAR) TYPE VAR;
void
-trace_aq_tx_descr(int ring_idx, unsigned int pointer,
+trace_aq_tx_descr(struct aq_hw *hw, int ring_idx, unsigned int pointer,
volatile uint64_t descr[2])
{
#if AQ_CFG_DEBUG_LVL > 2
@@ -92,7 +87,7 @@
entry.des_typ = DESCR_FIELD(descr[1], 2, 0);
- aq_log_detail("trace_aq_tx_descr ring=%d descr=%u pay_len=%u ct_en=%u ct_idx=%u rsvd2=0x%x tx_cmd=0x%x eop=%u dd=%u buf_len=%u rsvd1=%u des_typ=0x%x",
+ aq_log_detail(hw, "trace_aq_tx_descr ring=%d descr=%u pay_len=%u ct_en=%u ct_idx=%u rsvd2=0x%x tx_cmd=0x%x eop=%u dd=%u buf_len=%u rsvd1=%u des_typ=0x%x",
entry.ring_idx, entry.pointer, entry.pay_len,
entry.ct_en, entry.ct_idx, entry.rsvd2,
entry.tx_cmd, entry.eop, entry.dd, entry.buf_len,
@@ -101,7 +96,8 @@
}
void
-trace_aq_rx_descr(int ring_idx, unsigned int pointer, volatile uint64_t descr[2])
+trace_aq_rx_descr(struct aq_hw *hw, int ring_idx, unsigned int pointer,
+ volatile uint64_t descr[2])
{
#if AQ_CFG_DEBUG_LVL > 2
uint8_t dd;
@@ -142,7 +138,7 @@
eop = DESCR_FIELD(descr[1], 1, 1);
dd = DESCR_FIELD(descr[1], 0, 0);
- printf("trace_aq_rx_descr ring=%d descr=%u rss_hash=0x%x hdr_len=%u sph=%u rx_cntl=%u rsvd=0x%x avb_ts=%u rdm_err=%u pkt_type=%u rss_type=%u vlan_tag=%u next_desp=%u pkt_len=%u rsc_cnt=%u rx_estat=0x%x rx_stat=0x%x eop=%u dd=%u\n",
+ aq_log_detail(hw, "trace_aq_rx_descr ring=%d descr=%u rss_hash=0x%x hdr_len=%u sph=%u rx_cntl=%u rsvd=0x%x avb_ts=%u rdm_err=%u pkt_type=%u rss_type=%u vlan_tag=%u next_desp=%u pkt_len=%u rsc_cnt=%u rx_estat=0x%x rx_stat=0x%x eop=%u dd=%u",
ring_idx, pointer, rss_hash,
hdr_len, sph, rx_cntl,
rsvd, avb_ts, rdm_err,
@@ -153,7 +149,7 @@
}
void
-trace_aq_tx_context_descr(int ring_idx, unsigned int pointer,
+trace_aq_tx_context_descr(struct aq_hw *hw, int ring_idx, unsigned int pointer,
volatile uint64_t descr[2])
{
#if AQ_CFG_DEBUG_LVL > 2
@@ -188,7 +184,7 @@
__entry->ct_idx = DESCR_FIELD(descr[1], 3, 3);
__entry->des_typ = DESCR_FIELD(descr[1], 2, 0);
- printf("trace_aq_tx_context_descr ring=%d descr=%u out_len=%u tun_len=%u resvd3=%lu mss_len=%u l4_len=%u l3_len=%u l2_len=%d ct_cmd=%u vlan_tag=%u ct_idx=%u des_typ=0x%x\n",
+ aq_log_detail(hw, "trace_aq_tx_context_descr ring=%d descr=%u out_len=%u tun_len=%u resvd3=%lu mss_len=%u l4_len=%u l3_len=%u l2_len=%d ct_cmd=%u vlan_tag=%u ct_idx=%u des_typ=0x%x",
__entry->ring_idx, __entry->pointer, __entry->out_len,
__entry->tun_len, __entry->resvd3, __entry->mss_len,
__entry->l4_len, __entry->l3_len, __entry->l2_len,
diff --git a/sys/dev/aq/aq_device.h b/sys/dev/aq/aq_device.h
--- a/sys/dev/aq/aq_device.h
+++ b/sys/dev/aq/aq_device.h
@@ -35,6 +35,17 @@
#ifndef _AQ_DEVICE_H_
#define _AQ_DEVICE_H_
+#include <sys/bitstring.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_media.h>
+#include <net/if_var.h>
+#include <net/iflib.h>
+
#include "aq_hw.h"
enum aq_media_type {
@@ -138,6 +149,11 @@
uint8_t rss_key[HW_ATL_RSS_HASHKEY_SIZE];
uint8_t rss_table[HW_ATL_RSS_INDIRECTION_TABLE_MAX];
+
+ int dbg_level;
+ uint32_t dbg_categories;
+
+ struct sysctl_ctx_list aq_sysctl_ctx;
};
int aq_update_hw_stats(struct aq_dev *aq_dev);
diff --git a/sys/dev/aq/aq_fw.h b/sys/dev/aq/aq_fw.h
--- a/sys/dev/aq/aq_fw.h
+++ b/sys/dev/aq/aq_fw.h
@@ -68,6 +68,9 @@
int (*get_mac_addr)(struct aq_hw* hw, uint8_t* mac_addr);
int (*get_stats)(struct aq_hw* hw, struct aq_hw_stats* stats);
+ /* Reports millidegrees Celsius. */
+ int (*get_temp)(struct aq_hw* hw, int* temp_mc);
+
int (*led_control)(struct aq_hw* hw, uint32_t mode);
};
diff --git a/sys/dev/aq/aq_fw.c b/sys/dev/aq/aq_fw.c
--- a/sys/dev/aq/aq_fw.c
+++ b/sys/dev/aq/aq_fw.c
@@ -112,7 +112,7 @@
hw->rbl_enabled = boot_exit_code != 0;
- trace(dbg_init, "RBL enabled = %d", hw->rbl_enabled);
+ trace(hw, dbg_init, "RBL enabled = %d", hw->rbl_enabled);
/* Having FW version 0 is an indicator that cold start
* is in progress. This means two things:
@@ -135,12 +135,12 @@
switch (mode) {
case boot_mode_flb:
- aq_log("FLB> F/W successfully loaded from flash.");
+ aq_log(hw, "FLB> F/W successfully loaded from flash.");
hw->flash_present = true;
return wait_init_mac_firmware(hw);
case boot_mode_rbl_flash:
- aq_log("RBL> F/W loaded from flash. Host Bootload disabled.");
+ aq_log(hw, "RBL> F/W loaded from flash. Host Bootload disabled.");
hw->flash_present = true;
return wait_init_mac_firmware(hw);
@@ -153,7 +153,7 @@
device_printf(hw->dev, "RBL> Host Bootload mode: this driver does not support Host Boot\n");
return (ENOTSUP);
#else
- trace(dbg_init, "RBL> Host Bootload mode");
+ trace(hw, dbg_init, "RBL> Host Bootload mode");
break;
#endif // HOST_BOOT_DISABLE
}
@@ -172,16 +172,16 @@
if (hw->fw_version.raw == 0)
hw->fw_version.raw = AQ_READ_REG(hw, 0x18);
- aq_log("MAC F/W version is %d.%d.%d",
+ aq_log(hw, "MAC F/W version is %d.%d.%d",
hw->fw_version.major_version, hw->fw_version.minor_version,
hw->fw_version.build_number);
if (hw->fw_version.major_version == 1) {
- trace(dbg_init, "using F/W ops v1.x");
+ trace(hw, dbg_init, "using F/W ops v1.x");
hw->fw_ops = &aq_fw1x_ops;
return (0);
} else if (hw->fw_version.major_version >= 2) {
- trace(dbg_init, "using F/W ops v2.x");
+ trace(hw, dbg_init, "using F/W ops v2.x");
hw->fw_ops = &aq_fw2x_ops;
return (0);
}
@@ -253,12 +253,12 @@
}
if (flb_status == 0) {
- trace_error(dbg_init,
+ trace_error(hw, dbg_init,
"FLB> MAC kickstart failed: timed out");
return (ETIMEDOUT);
}
- trace(dbg_init, "FLB> MAC kickstart done, %d ms", k);
+ trace(hw, dbg_init, "FLB> MAC kickstart done, %d ms", k);
/* FW reset */
reg_global_ctl2_set(hw, 0x80e0);
// Let Felicity hardware complete SMBUS transaction before
@@ -284,18 +284,18 @@
}
if (!restart_completed) {
- trace_error(dbg_init, "FLB> Global Soft Reset failed");
+ trace_error(hw, dbg_init, "FLB> Global Soft Reset failed");
return (ETIMEDOUT);
}
- trace(dbg_init, "FLB> F/W restart: %d ms", k * 10);
+ trace(hw, dbg_init, "FLB> F/W restart: %d ms", k * 10);
return (0);
}
static int
mac_soft_reset_rbl(struct aq_hw* hw, enum aq_fw_bootloader_mode* mode)
{
- trace(dbg_init, "RBL> MAC reset STARTED!");
+ trace(hw, dbg_init, "RBL> MAC reset STARTED!");
reg_global_ctl2_set(hw, 0x40e1);
reg_glb_cpu_sem_set(hw, 1, 0);
@@ -329,20 +329,20 @@
}
if (rbl_status == 0 || rbl_status == 0xDEAD) {
- trace_error(dbg_init, "RBL> RBL restart failed: timeout");
+ trace_error(hw, dbg_init, "RBL> RBL restart failed: timeout");
return (EBUSY);
}
if (rbl_status == RBL_STATUS_SUCCESS) {
if (mode)
*mode = boot_mode_rbl_flash;
- trace(dbg_init, "RBL> reset complete! [Flash]");
+ trace(hw, dbg_init, "RBL> reset complete! [Flash]");
} else if (rbl_status == RBL_STATUS_HOST_BOOT) {
if (mode)
*mode = boot_mode_rbl_host_bootload;
- trace(dbg_init, "RBL> reset complete! [Host Bootload]");
+ trace(hw, dbg_init, "RBL> reset complete! [Host Bootload]");
} else {
- trace_error(dbg_init, "unknown RBL status 0x%x", rbl_status);
+ trace_error(hw, dbg_init, "unknown RBL status 0x%x", rbl_status);
return (EBUSY);
}
@@ -359,7 +359,7 @@
DELAY((1) * 1000);
}
- trace_error(dbg_init,
+ trace_error(hw, dbg_init,
"timeout waiting for reg 0x18. MAC f/w NOT READY");
return (EBUSY);
}
diff --git a/sys/dev/aq/aq_fw1x.c b/sys/dev/aq/aq_fw1x.c
--- a/sys/dev/aq/aq_fw1x.c
+++ b/sys/dev/aq/aq_fw1x.c
@@ -194,10 +194,11 @@
DELAY(10);
}
- trace_error(dbg_init, "F/W 1.x reset finalize timeout");
+ trace_error(hw, dbg_init, "F/W 1.x reset finalize timeout");
return (EBUSY);
}
+/* No fw_mtx here: the control register is written whole, never modified. */
static int
aq_fw1x_set_mode(struct aq_hw* hw, enum aq_hw_fw_mpi_state mode,
enum aq_fw_link_speed speed)
@@ -206,7 +207,7 @@
state.mode = mpi_mode_to_fw1x(mode);
state.speed = link_speed_mask_to_fw1x(speed);
- trace(dbg_init, "fw1x> set mode %d, rate mask = %#x; raw = %#x",
+ trace(hw, dbg_init, "fw1x> set mode %d, rate mask = %#x; raw = %#x",
state.mode, state.speed, state.val);
AQ_WRITE_REG(hw, AQ_HW_MPI_CONTROL_ADR, state.val);
@@ -220,7 +221,7 @@
{
union aq_fw1x_state_reg state = { .val = AQ_READ_REG(hw, AQ_HW_MPI_STATE_ADR) };
- trace(dbg_init, "fw1x> get_mode(): 0x36c -> %x, 0x368 -> %x",
+ trace(hw, dbg_init, "fw1x> get_mode(): 0x36c -> %x, 0x368 -> %x",
state.val, AQ_READ_REG(hw, AQ_HW_MPI_CONTROL_ADR));
enum aq_hw_fw_mpi_state md = MPI_DEINIT;
@@ -263,7 +264,7 @@
uint32_t efuse_shadow_addr = AQ_READ_REG(hw, 0x374);
if (efuse_shadow_addr == 0) {
- trace_error(dbg_init, "couldn't read eFUSE Shadow Address");
+ trace_error(hw, dbg_init, "couldn't read eFUSE Shadow Address");
AQ_DBG_EXIT(EFAULT);
return (EFAULT);
}
@@ -282,7 +283,7 @@
memcpy(mac, (uint8_t*)mac_addr, ETHER_ADDR_LEN);
- trace(dbg_init, "fw1x> eFUSE MAC addr -> %02x-%02x-%02x-%02x-%02x-%02x",
+ trace(hw, dbg_init, "fw1x> eFUSE MAC addr -> %02x-%02x-%02x-%02x-%02x-%02x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
AQ_DBG_EXIT(0);
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
@@ -177,6 +177,7 @@
// MSM Statistics
#define FW2X_CAP_STATISTICS (1ull << (32 + CAPS_HI_STATISTICS))
+#define FW2X_CAP_TEMPERATURE (1ull << (32 + CAPS_HI_TEMPERATURE))
#define FW2X_RATE_MASK (FW2X_RATE_100M | FW2X_RATE_1G | FW2X_RATE_2G5 | FW2X_RATE_5G | FW2X_RATE_10G)
@@ -249,11 +250,11 @@
(uint32_t*)&caps, sizeof caps/sizeof(uint32_t));
if (err == 0) {
hw->fw_caps = caps.caps_lo | ((uint64_t)caps.caps_hi << 32);
- trace(dbg_init,
+ trace(hw, dbg_init,
"fw2x> F/W capabilities mask = %llx",
(unsigned long long)hw->fw_caps);
} else {
- trace_error(dbg_init,
+ trace_error(hw, dbg_init,
"fw2x> can't get F/W capabilities mask, error %d", err);
}
@@ -292,9 +293,12 @@
aq_fw2x_set_mode(struct aq_hw* hw, enum aq_hw_fw_mpi_state mode,
enum aq_fw_link_speed speed)
{
- uint64_t mpi_ctrl = get_mpi_ctrl(hw);
+ uint64_t mpi_ctrl;
AQ_DBG_ENTERA("speed=%d", speed);
+
+ mtx_lock(&hw->fw_mtx);
+ mpi_ctrl = get_mpi_ctrl(hw);
switch (mode) {
case MPI_INIT:
mpi_ctrl &= ~FW2X_RATE_MASK;
@@ -316,11 +320,14 @@
break;
default:
- trace_error(dbg_init, "fw2x> unknown MPI state %d", mode);
+ mtx_unlock(&hw->fw_mtx);
+ trace_error(hw, dbg_init, "fw2x> unknown MPI state %d", mode);
return (EINVAL);
}
set_mpi_ctrl(hw, mpi_ctrl);
+ mtx_unlock(&hw->fw_mtx);
+
AQ_DBG_EXIT(0);
return (0);
}
@@ -329,10 +336,11 @@
aq_fw2x_get_mode(struct aq_hw* hw, enum aq_hw_fw_mpi_state* mode,
enum aq_fw_link_speed* link_speed, enum aq_fw_link_fc* fc)
{
- uint64_t mpi_state = get_mpi_state(hw);
- uint32_t rates = mpi_state & FW2X_RATE_MASK;
-
+ uint64_t mpi_state;
+ uint32_t rates;
+ mtx_lock(&hw->fw_mtx);
+ mpi_state = get_mpi_state(hw);
if (mode) {
uint64_t mpi_ctrl = get_mpi_ctrl(hw);
if (mpi_ctrl & FW2X_RATE_MASK)
@@ -340,6 +348,9 @@
else
*mode = MPI_DEINIT;
}
+ mtx_unlock(&hw->fw_mtx);
+
+ rates = mpi_state & FW2X_RATE_MASK;
enum aq_fw_link_speed speed = aq_fw_none;
@@ -374,7 +385,7 @@
uint32_t efuse_shadow_addr = AQ_READ_REG(hw, 0x364);
if (efuse_shadow_addr == 0) {
- trace_error(dbg_init, "couldn't read eFUSE Shadow Address");
+ trace_error(hw, dbg_init, "couldn't read eFUSE Shadow Address");
AQ_DBG_EXIT(EFAULT);
return (EFAULT);
}
@@ -428,26 +439,64 @@
int err;
if ((hw->fw_caps & FW2X_CAP_STATISTICS) == 0) {
- trace_warn(dbg_fw, "fw2x> statistics not supported by F/W");
+ trace_warn(hw, dbg_fw, "fw2x> statistics not supported by F/W");
return (ENOTSUP);
}
/* Kick-and-read: take the F/W's previous snapshot, request the next. */
+ mtx_lock(&hw->fw_mtx);
err = aq_hw_fw_downld_dwords(hw,
hw->mbox_addr + offsetof(struct aq_fw2x_mailbox, msm),
(uint32_t*)&aq_fw2x_stats, sizeof aq_fw2x_stats/sizeof(uint32_t));
+ mpi_ctrl = get_mpi_ctrl(hw);
+ mpi_ctrl ^= FW2X_CAP_STATISTICS;
+ set_mpi_ctrl(hw, mpi_ctrl);
+ mtx_unlock(&hw->fw_mtx);
+
aq_fw2x_stats_to_fw_stats(stats, &aq_fw2x_stats);
if (err != 0)
- trace_error(dbg_fw,
+ trace_error(hw, dbg_fw,
"fw2x> download statistics data FAILED, error %d", err);
+ return (err);
+}
+
+static int
+aq_fw2x_get_temp(struct aq_hw* hw, int* temp_mc)
+{
+ uint64_t mpi_ctrl, req_bit;
+ uint32_t raw;
+ int err;
+
+ if ((hw->fw_caps & FW2X_CAP_TEMPERATURE) == 0)
+ return (ENOTSUP);
+
+ /* Toggle the request bit and wait for the F/W to echo it back. */
+ mtx_lock(&hw->fw_mtx);
mpi_ctrl = get_mpi_ctrl(hw);
- mpi_ctrl ^= FW2X_CAP_STATISTICS;
- set_mpi_ctrl(hw, mpi_ctrl);
+ req_bit = mpi_ctrl & FW2X_CAP_TEMPERATURE;
+ set_mpi_ctrl(hw, mpi_ctrl ^ FW2X_CAP_TEMPERATURE);
- return (err);
+ err = AQ_HW_WAIT_FOR((get_mpi_state(hw) & FW2X_CAP_TEMPERATURE) !=
+ req_bit, 1, 10000);
+ if (err == 0)
+ err = aq_hw_fw_downld_dwords(hw, hw->mbox_addr +
+ offsetof(struct aq_fw2x_mailbox, phy_temperature),
+ &raw, 1);
+ mtx_unlock(&hw->fw_mtx);
+
+ if (err != 0) {
+ trace_error(hw, dbg_fw,
+ "fw2x> temperature read FAILED, error %d", err);
+ return (err);
+ }
+
+ /* F/W reports 1/256 degree Celsius. */
+ *temp_mc = (int)(int16_t)(raw & 0xffff) * 1000 / 256;
+
+ return (0);
}
static int
@@ -476,6 +525,7 @@
.get_mac_addr = aq_fw2x_get_mac_addr,
.get_stats = aq_fw2x_get_stats,
+ .get_temp = aq_fw2x_get_temp,
.led_control = aq_fw2x_led_control,
};
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
@@ -38,6 +38,8 @@
#include <sys/types.h>
#include <sys/cdefs.h>
#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <machine/atomic.h>
#include <machine/cpufunc.h>
#include <machine/bus.h>
@@ -207,6 +209,12 @@
/* Atlantic 2: firmware statistics interface version (A0/B0). */
uint32_t aq2_iface;
+
+ /* Atlantic 2: firmware banner already announced for this attach. */
+ bool fw_announced;
+
+ /* Serialises the F/W MPI control register and mailbox. */
+ struct mtx fw_mtx;
};
#define AQ_HW_MAC 0U
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
@@ -332,7 +332,7 @@
struct aq_dev *softc;
struct aq_hw *hw;
if_softc_ctx_t scctx;
- int rc;
+ int dbg, rc;
AQ_DBG_ENTER();
softc = iflib_get_softc(ctx);
@@ -345,6 +345,9 @@
softc->sctx = iflib_get_sctx(ctx);
scctx = softc->scctx;
+ mtx_init(&softc->hw.fw_mtx, device_get_nameunit(softc->dev),
+ "aq firmware", MTX_DEF);
+
softc->mmio_rid = PCIR_BAR(0);
softc->mmio_res = bus_alloc_resource_any(softc->dev, SYS_RES_MEMORY,
&softc->mmio_rid, RF_ACTIVE|RF_SHAREABLE);
@@ -361,6 +364,7 @@
softc->hw.hw_tag = softc->mmio_tag;
softc->hw.hw_handle = softc->mmio_handle;
softc->hw.dev = softc->dev;
+ softc->hw.aq_dev = softc;
softc->hw.device_id = pci_get_device(softc->dev);
if (aq_is_atlantic2(softc->hw.device_id))
softc->hw.chip_features |= AQ_HW_CHIP_ATLANTIC2;
@@ -371,6 +375,15 @@
hw->fc.fc_tx = 1;
softc->linkup = 0U;
+ softc->dbg_level = AQ_DBG_LEVEL_DEFAULT;
+ softc->dbg_categories = AQ_DBG_CATEGORIES_DEFAULT;
+ if (resource_int_value(device_get_name(softc->dev),
+ device_get_unit(softc->dev), "debug", &dbg) == 0)
+ softc->dbg_level = dbg;
+ if (resource_int_value(device_get_name(softc->dev),
+ device_get_unit(softc->dev), "debug_categories", &dbg) == 0)
+ softc->dbg_categories = dbg;
+
/* Look up ops and caps. */
rc = aq_hw_mpi_create(hw);
if (rc != 0) {
@@ -438,6 +451,8 @@
if (softc->mmio_res != NULL)
bus_release_resource(softc->dev, SYS_RES_MEMORY,
softc->mmio_rid, softc->mmio_res);
+ /* iflib skips ifdi_detach when ifdi_attach_pre fails. */
+ mtx_destroy(&softc->hw.fw_mtx);
AQ_DBG_EXIT(rc);
return (rc);
@@ -503,6 +518,12 @@
AQ_DBG_ENTER();
softc = iflib_get_softc(ctx);
+ /*
+ * Remove the driver's sysctls (and drain in-flight readers) before
+ * tearing down the state they reference; a no-op if never registered.
+ */
+ sysctl_ctx_free(&softc->aq_sysctl_ctx);
+
aq_hw_deinit(&softc->hw);
for (i = 0; i < softc->rx_rings_count; i++)
@@ -516,6 +537,8 @@
free(softc->vlan_tags, M_AQ);
+ mtx_destroy(&softc->hw.fw_mtx);
+
AQ_DBG_EXIT(0);
return (0);
}
@@ -851,7 +874,7 @@
mac_addr = LLADDR(dl);
aq_hw_mac_addr_set(hw, mac_addr, count + 1);
- aq_log_detail("set %d mc address %6D", count + 1, mac_addr, ":");
+ aq_log_detail(hw, "set %d mc address %6D", count + 1, mac_addr, ":");
return (1);
}
@@ -1055,13 +1078,14 @@
rc = iflib_irq_alloc_generic(ctx, &softc->rx_rings[i]->irq,
vector + 1, IFLIB_INTR_RXTX, aq_isr_rx, softc->rx_rings[i],
softc->rx_rings[i]->index, irq_name);
- device_printf(softc->dev, "Assign IRQ %u to rx ring %u\n",
- vector, softc->rx_rings[i]->index);
-
if (rc) {
device_printf(softc->dev, "failed to set up RX handler\n");
goto fail;
}
+ if (bootverbose)
+ device_printf(softc->dev,
+ "Assign IRQ %u to rx ring %u\n", vector,
+ softc->rx_rings[i]->index);
softc->rx_rings[i]->msix = vector;
}
@@ -1075,20 +1099,24 @@
&softc->rx_rings[softc->tx_rings[i]->msix]->irq,
IFLIB_INTR_TX, softc->tx_rings[i],
softc->tx_rings[i]->index, irq_name);
- device_printf(softc->dev, "Assign IRQ %u to tx ring %u\n",
- softc->tx_rings[i]->msix, softc->tx_rings[i]->index);
+ if (bootverbose)
+ device_printf(softc->dev,
+ "tx ring %u shares IRQ %u\n",
+ softc->tx_rings[i]->index,
+ softc->tx_rings[i]->msix);
}
rc = iflib_irq_alloc_generic(ctx, &softc->irq, rx_vectors + 1,
IFLIB_INTR_ADMIN, aq_linkstat_isr, softc, 0, "aq");
- softc->msix = rx_vectors;
- device_printf(softc->dev, "Assign IRQ %u to admin proc \n",
- rx_vectors);
if (rc) {
device_printf(iflib_get_dev(ctx),
"Failed to register admin handler\n");
goto fail;
}
+ softc->msix = rx_vectors;
+ if (bootverbose)
+ device_printf(softc->dev, "Assign IRQ %u to admin proc\n",
+ rx_vectors);
AQ_DBG_EXIT(0);
return (0);
@@ -1367,32 +1395,61 @@
return (0);
}
+static int
+aq_sysctl_temperature(SYSCTL_HANDLER_ARGS)
+{
+ struct aq_dev *softc = arg1;
+ int error, temp_mc, val;
+
+ if (softc->hw.fw_ops == NULL || softc->hw.fw_ops->get_temp == NULL)
+ return (ENOTSUP);
+
+ error = softc->hw.fw_ops->get_temp(&softc->hw, &temp_mc);
+ if (error != 0)
+ return (error);
+
+ /* millidegrees Celsius -> decikelvin */
+ val = temp_mc / 100 + 2732;
+
+ return (sysctl_handle_int(oidp, &val, 0, req));
+}
+
static void
aq_add_stats_sysctls(struct aq_dev *softc)
{
device_t dev = softc->dev;
- struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
+ struct sysctl_ctx_list *ctx = &softc->aq_sysctl_ctx;
struct sysctl_oid *tree = device_get_sysctl_tree(dev);
struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
struct aq_stats *stats = &softc->curr_stats;
struct sysctl_oid *stat_node, *queue_node;
struct sysctl_oid_list *stat_list, *queue_list;
+ int temp_mc;
#define QUEUE_NAME_LEN 32
char namebuf[QUEUE_NAME_LEN];
+
+ /* Own these oids so aq_if_detach can drain and free them in order. */
+ sysctl_ctx_init(ctx);
/* RSS configuration */
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "print_rss_config",
CTLTYPE_STRING | CTLFLAG_RD, softc, 0,
aq_sysctl_print_rss_config, "A", "Prints RSS Configuration");
- /* Runtime trace controls (global) */
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "debug",
- CTLFLAG_RW, &aq_dbg_level, 0,
+ CTLFLAG_RW, &softc->dbg_level, 0,
"Trace verbosity: 0=off, 3=err, 4=+warn, 5=+trace, 6=+detail");
SYSCTL_ADD_U32(ctx, child, OID_AUTO, "debug_categories",
- CTLFLAG_RW, &aq_dbg_categories, 0,
+ CTLFLAG_RW, &softc->dbg_categories, 0,
"Trace category mask: init=1 config=2 tx=4 rx=8 intr=16 fw=32");
+ /* ENOTSUP means no sensor; other errors may just be a cold PHY. */
+ if (softc->hw.fw_ops != NULL && softc->hw.fw_ops->get_temp != NULL &&
+ softc->hw.fw_ops->get_temp(&softc->hw, &temp_mc) != ENOTSUP)
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "temperature",
+ CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, softc, 0,
+ aq_sysctl_temperature, "IK", "PHY temperature");
+
/* Driver Statistics */
for (int i = 0; i < softc->tx_rings_count; i++) {
struct aq_ring *ring = softc->tx_rings[i];
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
@@ -268,7 +268,7 @@
for (iter = 0, cnt = 0, i = idx;
iter < ring->rx_size && cnt <= budget;) {
- trace_aq_rx_descr(ring->index, i,
+ trace_aq_rx_descr(&aq_dev->hw, ring->index, i,
(volatile uint64_t*)&rx_desc[i]);
if (!rx_desc[i].wb.dd)
break;
@@ -337,7 +337,7 @@
rx_desc = (volatile struct aq_rx_desc *) &ring->rx_descs[cidx];
- trace_aq_rx_descr(ring->index, cidx,
+ trace_aq_rx_descr(&aq_dev->hw, ring->index, cidx,
(volatile uint64_t *)rx_desc);
/* MAC error (rx_stat) or RX-DMA fault (rdm_err) -> drop. */
@@ -498,7 +498,7 @@
AQ_DBG_PRINT("tx_cmd = 0x%x", tx_cmd);
if (tx_cmd) {
- trace_aq_tx_context_descr(ring->index, pidx,
+ trace_aq_tx_context_descr(&aq_dev->hw, ring->index, pidx,
(volatile void*)txc);
/* We've consumed the first desc, adjust counters */
pidx = aq_next(pidx, ring->tx_size - 1);
@@ -537,7 +537,7 @@
txd->len = segs[i].ds_len;
txd->pay_len = pay_len;
if (i < pi->ipi_nsegs - 1)
- trace_aq_tx_descr(ring->index, pidx,
+ trace_aq_tx_descr(&aq_dev->hw, ring->index, pidx,
(volatile void*)txd);
pidx = aq_next(pidx, ring->tx_size - 1);
@@ -548,7 +548,7 @@
txd->eop = 1U;
AQ_DBG_DUMP_DESC(txd);
- trace_aq_tx_descr(ring->index, pidx, (volatile void*)txd);
+ trace_aq_tx_descr(&aq_dev->hw, ring->index, pidx, (volatile void*)txd);
ring->tx_tail = pidx;
counter_u64_add(ring->stats.tx_pkts, 1);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jul 31, 3:36 AM (8 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35764682
Default Alt Text
D58434.id182897.diff (31 KB)
Attached To
Mode
D58434: aq(4): observability controls and sysctl/header hygiene
Attached
Detach File
Event Timeline
Log In to Comment