Page MenuHomeFreeBSD

D58434.id182904.diff
No OneTemporary

D58434.id182904.diff

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,8 @@
AQ_DBG_ENTER();
softc = iflib_get_softc(ctx);
+ sysctl_ctx_free(&softc->aq_sysctl_ctx);
+
aq_hw_deinit(&softc->hw);
for (i = 0; i < softc->rx_rings_count; i++)
@@ -516,6 +533,8 @@
free(softc->vlan_tags, M_AQ);
+ mtx_destroy(&softc->hw.fw_mtx);
+
AQ_DBG_EXIT(0);
return (0);
}
@@ -851,7 +870,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 +1074,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 +1095,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 +1391,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

Mime Type
text/plain
Expires
Fri, Jul 31, 6:33 AM (9 h, 33 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35707688
Default Alt Text
D58434.id182904.diff (31 KB)

Event Timeline