Module Name: src
Committed By: ryo
Date: Sat Jan 14 13:20:15 UTC 2023
Modified Files:
src/sys/dev/pci: if_aq.c
Log Message:
Added support for the Aquantia (Marvell) AQC113 10G Network Adapter and the
variants, to aq(4)
To generate a diff of this commit:
cvs rdiff -u -r1.42 -r1.43 src/sys/dev/pci/if_aq.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/pci/if_aq.c
diff -u src/sys/dev/pci/if_aq.c:1.42 src/sys/dev/pci/if_aq.c:1.43
--- src/sys/dev/pci/if_aq.c:1.42 Sat Jan 14 13:17:50 2023
+++ src/sys/dev/pci/if_aq.c Sat Jan 14 13:20:15 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: if_aq.c,v 1.42 2023/01/14 13:17:50 ryo Exp $ */
+/* $NetBSD: if_aq.c,v 1.43 2023/01/14 13:20:15 ryo Exp $ */
/**
* aQuantia Corporation Network Driver
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.42 2023/01/14 13:17:50 ryo Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.43 2023/01/14 13:20:15 ryo Exp $");
#ifdef _KERNEL_OPT
#include "opt_if_aq.h"
@@ -116,19 +116,29 @@ __KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.
#define AQ_RSS_HASHKEY_SIZE 40
#define AQ_RSS_INDIRECTION_TABLE_MAX 64
-#define AQ_JUMBO_MTU_REV_A 9000
-#define AQ_JUMBO_MTU_REV_B 16338
+#define AQ1_JUMBO_MTU_REV_A 9000
+#define AQ1_JUMBO_MTU_REV_B 16338
+#define AQ2_JUMBO_MTU 16338
/*
* TERMINOLOGY
+ * ATL (AQ1) = Atlantic. AQC100,107-109,111,112.
+ * ATL2 (AQ2) = Atlantic2. AQC113-116.
* MPI = MAC PHY INTERFACE?
* RPO = RX Protocol Offloading
* TPO = TX Protocol Offloading
* RPF = RX Packet Filter
* TPB = TX Packet buffer
* RPB = RX Packet buffer
+ * ART = Action Resolver Table
+ * TC = Traffic Class
*/
+enum aq_hwtype {
+ HWTYPE_AQ1,
+ HWTYPE_AQ2
+};
+
/* registers */
#define AQ_FW_SOFTRESET_REG 0x0000
#define AQ_FW_SOFTRESET_RESET __BIT(15) /* soft reset bit */
@@ -136,6 +146,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.
#define AQ_FW_VERSION_REG 0x0018
#define AQ_HW_REVISION_REG 0x001c
+#define AQ2_HW_FPGA_VERSION_REG 0x00f4 /* AQ2 */
#define AQ_GLB_NVR_INTERFACE1_REG 0x0100
#define AQ_FW_MBOX_CMD_REG 0x0200
@@ -182,7 +193,8 @@ __KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.
#define RBL_STATUS_HOST_BOOT 0x0000f1a7
#define AQ_FW_GLB_CPU_SEM_REG(i) (0x03a0 + (i) * 4)
-#define AQ_FW_SEM_RAM_REG AQ_FW_GLB_CPU_SEM_REG(2)
+#define AQ1_FW_SEM_RAM_REG AQ_FW_GLB_CPU_SEM_REG(2)
+#define AQ2_ART_SEM_REG AQ_FW_GLB_CPU_SEM_REG(3)
#define AQ_FW_GLB_CTL2_REG 0x0404
#define AQ_FW_GLB_CTL2_MCP_UP_FORCE_INTERRUPT __BIT(1)
@@ -194,7 +206,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.
#define AQ_PCI_REG_CONTROL_6_REG 0x1014
-// msix bitmap */
+/* msix bitmap */
#define AQ_INTR_STATUS_REG 0x2000 /* intr status */
#define AQ_INTR_STATUS_CLR_REG 0x2050 /* intr status clear */
#define AQ_INTR_MASK_REG 0x2060 /* intr mask set */
@@ -212,7 +224,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.
/* AQ_GEN_INTR_MAP_REG[AQ_RINGS_NUM] 0x2180-0x2200 */
#define AQ_GEN_INTR_MAP_REG(i) (0x2180 + (i) * 4)
-#define AQ_B0_ERR_INT 8U
+#define AQ_B0_ERR_INT 8
#define AQ_INTR_CTRL_REG 0x2300
#define AQ_INTR_CTRL_IRQMODE __BITS(1,0)
@@ -231,8 +243,9 @@ __KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.
#define FW_MPI_RESETCTRL_RESET_DIS __BIT(29)
#define RX_SYSCONTROL_REG 0x5000
-#define RX_SYSCONTROL_RPB_DMA_LOOPBACK __BIT(6)
-#define RX_SYSCONTROL_RPF_TPO_LOOPBACK __BIT(8)
+#define RX_SYSCONTROL_RPF_TPO_SYS_LOOPBACK __BIT(8)
+#define RX_SYSCONTROL_RPB_DMA_SYS_LOOPBACK __BIT(6)
+#define RX_SYSCONTROL_RPB_DMA_NET_LOOPBACK __BIT(4)
#define RX_SYSCONTROL_RESET_DIS __BIT(29)
#define RX_TCP_RSS_HASH_REG 0x5040
@@ -252,14 +265,19 @@ __KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.
#define RPF_L2BC_ACTION __BITS(12,14)
#define RPF_L2BC_THRESHOLD __BITS(31,16)
-/* RPF_L2UC_*_REG[34] (actual [38]?) */
+/* RPF_L2UC_*_REG[34] (AQ2 has [38]) */
#define RPF_L2UC_LSW_REG(i) (0x5110 + (i) * 8)
#define RPF_L2UC_MSW_REG(i) (0x5114 + (i) * 8)
#define RPF_L2UC_MSW_MACADDR_HI __BITS(15,0)
#define RPF_L2UC_MSW_ACTION __BITS(18,16)
+#define RPF_L2UC_MSW_TAG __BITS(27,22) /* AQ2 */
#define RPF_L2UC_MSW_EN __BIT(31)
-#define AQ_HW_MAC_OWN 0 /* index of own address */
-#define AQ_HW_MAC_NUM 34
+
+#define AQ_HW_MAC_OWN 0 /* index of own address */
+#define AQ1_HW_MAC_NUM 34
+#define AQ2_HW_MAC_NUM 38
+#define AQ_HW_MAC_NUM(sc) \
+ (HWTYPE_AQ2_P((sc)) ? AQ2_HW_MAC_NUM : AQ1_HW_MAC_NUM)
/* RPF_MCAST_FILTER_REG[8] 0x5250-0x5270 */
#define RPF_MCAST_FILTER_REG(i) (0x5250 + (i) * 4)
@@ -283,6 +301,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.
#define RPF_VLAN_FILTER_RXQ_EN __BIT(28)
#define RPF_VLAN_FILTER_RXQ __BITS(24,20)
#define RPF_VLAN_FILTER_ACTION __BITS(18,16)
+#define RPF_VLAN_FILTER_TAG __BITS(15,12) /* AQ2 */
#define RPF_VLAN_FILTER_ID __BITS(11,0)
/* RPF_ETHERTYPE_FILTER_REG[AQ_RINGS_NUM] 0x5300-0x5380 */
@@ -423,8 +442,9 @@ __KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.
#define RX_DMA_COALESCED_PKT_CNT_REG 0x6820
#define TX_SYSCONTROL_REG 0x7000
-#define TX_SYSCONTROL_TPB_DMA_LOOPBACK __BIT(6)
-#define TX_SYSCONTROL_TPO_PKT_LOOPBACK __BIT(7)
+#define TX_SYSCONTROL_TPO_PKT_SYS_LOOPBACK __BIT(7)
+#define TX_SYSCONTROL_TPB_DMA_SYS_LOOPBACK __BIT(6)
+#define TX_SYSCONTROL_TPB_DMA_NET_LOOPBACK __BIT(4)
#define TX_SYSCONTROL_RESET_DIS __BIT(29)
#define TX_TPO2_REG 0x7040
@@ -449,8 +469,10 @@ __KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.
#define TPS_DESC_TCT_CREDIT_MAX __BITS(16,27)
#define TPS_DESC_TCT_WEIGHT __BITS(8,0)
-#define AQ_HW_TXBUF_MAX 160
-#define AQ_HW_RXBUF_MAX 320
+#define AQ1_HW_TXBUF_MAX 160
+#define AQ1_HW_RXBUF_MAX 320
+#define AQ2_HW_TXBUF_MAX 128
+#define AQ2_HW_RXBUF_MAX 192
#define TPO_HWCSUM_REG 0x7800
#define TPO_HWCSUM_IP4CSUM_EN __BIT(1)
@@ -467,7 +489,9 @@ __KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.
#define TPB_TX_BUF_REG 0x7900
#define TPB_TX_BUF_EN __BIT(0)
#define TPB_TX_BUF_SCP_INS_EN __BIT(2)
-#define TPB_TX_BUF_TC_MODE_EN __BIT(8)
+#define TPB_TX_BUF_CLK_GATE_EN __BIT(5)
+#define TPB_TX_BUF_TC_MODE __BIT(8)
+#define TPB_TX_BUF_TC_Q_RAND_MAP_EN __BIT(9) /* AQ2 */
/* TPB_TXB_BUFSIZE_REG[AQ_TRAFFICCLASS_NUM] 0x7910-7990 */
#define TPB_TXB_BUFSIZE_REG(i) (0x7910 + (i) * 0x10)
@@ -508,6 +532,345 @@ __KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.
#define TX_INTR_MODERATION_CTL_MIN __BITS(15,8)
#define TX_INTR_MODERATION_CTL_MAX __BITS(24,16)
+/* AQ2 (ATL2) registers */
+#define AQ2_QUEUE_MODE 0x0c9c
+
+#define AQ2_MIF_HOST_FINISHED_STATUS_WRITE_REG 0x0e00
+#define AQ2_MIF_HOST_FINISHED_STATUS_READ_REG 0x0e04
+#define AQ2_MIF_HOST_FINISHED_STATUS_ACK __BIT(0)
+
+#define AQ2_MCP_HOST_REQ_INT_REG 0x0f00
+#define AQ2_MCP_HOST_REQ_INT_READY __BIT(0)
+#define AQ2_MCP_HOST_REQ_INT_SET_REG 0x0f04
+#define AQ2_MCP_HOST_REQ_INT_CLR_REG 0x0f08
+
+#define AQ2_PHI_EXT_TAG_REG 0x1000
+#define AQ2_PHI_EXT_TAG_ENABLE __BIT(5)
+
+#define AQ2_MIF_BOOT_REG 0x3040
+#define AQ2_MIF_BOOT_HOST_DATA_LOADED __BIT(16)
+#define AQ2_MIF_BOOT_BOOT_STARTED __BIT(24)
+#define AQ2_MIF_BOOT_CRASH_INIT __BIT(27)
+#define AQ2_MIF_BOOT_BOOT_CODE_FAILED __BIT(28)
+#define AQ2_MIF_BOOT_FW_INIT_FAILED __BIT(29)
+#define AQ2_MIF_BOOT_FW_INIT_COMP_SUCCESS __BIT(31)
+
+/* ART(Action Resolver Table) */
+#define AQ2_ART_ACTION_ACT_MASK __BITS(9,8)
+#define AQ2_ART_ACTION_RSS_MASK __BIT(7)
+#define AQ2_ART_ACTION_INDEX_MASK __BITS(6,2)
+#define AQ2_ART_ACTION_ENABLE_MASK __BIT(0)
+#define AQ2_ART_ACTION(act, rss, idx, en) \
+ (__SHIFTIN((act), AQ2_ART_ACTION_ACT_MASK) | \
+ __SHIFTIN((rss), AQ2_ART_ACTION_RSS_MASK) | \
+ __SHIFTIN((idx), AQ2_ART_ACTION_INDEX_MASK) | \
+ __SHIFTIN((en), AQ2_ART_ACTION_ENABLE_MASK))
+#define AQ2_ART_ACTION_DROP AQ2_ART_ACTION(0, 0, 0, 1)
+#define AQ2_ART_ACTION_DISABLE AQ2_ART_ACTION(0, 0, 0, 0)
+#define AQ2_ART_ACTION_ASSIGN_QUEUE(q) AQ2_ART_ACTION(1, 0, (q), 1)
+#define AQ2_ART_ACTION_ASSIGN_TC(tc) AQ2_ART_ACTION(1, 1, (tc), 1)
+
+#define AQ2_RPF_TAG_PCP_MASK __BITS(31,29)
+#define AQ2_RPF_TAG_FLEX_MASK __BITS(28,27)
+#define AQ2_RPF_TAG_UNKNOWN_MASK __BITS(26,24)
+#define AQ2_RPF_TAG_L4_MASK __BITS(23,21)
+#define AQ2_RPF_TAG_L3_V6_MASK __BITS(20,18)
+#define AQ2_RPF_TAG_L3_V4_MASK __BITS(17,15)
+#define AQ2_RPF_TAG_UNTAG_MASK __BIT(14)
+#define AQ2_RPF_TAG_VLAN_MASK __BITS(13,10)
+#define AQ2_RPF_TAG_ET_MASK __BITS(9,7)
+#define AQ2_RPF_TAG_ALLMC_MASK __BIT(6)
+#define AQ2_RPF_TAG_UC_MASK __BITS(5,0)
+
+/* index of aq2_filter_art_set() */
+#define AQ2_RPF_INDEX_L2_PROMISC_OFF 0
+#define AQ2_RPF_INDEX_VLAN_PROMISC_OFF 1
+#define AQ2_RPF_INDEX_L3L4_USER 8
+#define AQ2_RPF_INDEX_ET_PCP_USER 24
+#define AQ2_RPF_INDEX_VLAN_USER 40
+#define AQ2_RPF_INDEX_PCP_TO_TC 56
+
+#define AQ2_RPF_L2BC_TAG_REG 0x50f0
+#define AQ2_RPF_L2BC_TAG_MASK __BITS(5,0)
+
+#define AQ2_RPF_NEW_CTRL_REG 0x5104
+#define AQ2_RPF_NEW_CTRL_ENABLE __BIT(11)
+
+#define AQ2_RPF_L2UC_TAG_REG(i) (0x5110 + (i) * 8)
+#define AQ2_RPF_L2UC_TAG_MASK __BITS(27,22)
+
+#define AQ2_RPF_REDIR2_REG 0x54c8
+#define AQ2_RPF_REDIR2_INDEX __BIT(12)
+#define AQ2_RPF_REDIR2_HASHTYPE __BITS(8,0)
+#define AQ2_RPF_REDIR2_HASHTYPE_NONE 0
+#define AQ2_RPF_REDIR2_HASHTYPE_IP __BIT(0)
+#define AQ2_RPF_REDIR2_HASHTYPE_TCP4 __BIT(1)
+#define AQ2_RPF_REDIR2_HASHTYPE_UDP4 __BIT(2)
+#define AQ2_RPF_REDIR2_HASHTYPE_IP6 __BIT(3)
+#define AQ2_RPF_REDIR2_HASHTYPE_TCP6 __BIT(4)
+#define AQ2_RPF_REDIR2_HASHTYPE_UDP6 __BIT(5)
+#define AQ2_RPF_REDIR2_HASHTYPE_IP6EX __BIT(6)
+#define AQ2_RPF_REDIR2_HASHTYPE_TCP6EX __BIT(7)
+#define AQ2_RPF_REDIR2_HASHTYPE_UDP6EX __BIT(8)
+#define AQ2_RPF_REDIR2_HASHTYPE_ALL __BITS(8,0)
+
+#define AQ2_RX_Q_TC_MAP_REG(i) (0x5900 + (i) * 4)
+
+#define AQ2_RDM_RX_DESC_RD_REQ_LIMIT_REG 0x5a04
+
+#define AQ2_RPF_RSS_REDIR_REG(tc, i) \
+ (0x6200 + (0x100 * ((tc) >> 2)) + (i) * 4)
+#define AQ2_RPF_RSS_REDIR_TC_MASK(tc) \
+ (__BITS(4,0) << (5 * ((tc) & 3)))
+
+#define AQ2_RPF_L3_V6_V4_SELECT_REG 0x6500
+#define AQ2_RPF_L3_V6_V4_SELECT_EN __BIT(23)
+
+#define AQ2_RPF_REC_TAB_ENABLE_REG 0x6ff0
+#define AQ2_RPF_REC_TAB_ENABLE_MASK __BITS(15,0)
+
+#define AQ2_TX_Q_TC_MAP_REG(i) (0x799c + (i) * 4)
+
+#define AQ2_LAUNCHTIME_CTRL_REG 0x7a1c
+#define AQ2_LAUNCHTIME_CTRL_RATIO __BITS(15,8)
+#define AQ2_LAUNCHTIME_CTRL_RATIO_SPEED_QUATER 4
+#define AQ2_LAUNCHTIME_CTRL_RATIO_SPEED_HALF 2
+#define AQ2_LAUNCHTIME_CTRL_RATIO_SPEED_FULL 1
+
+/* AT2_TX_INTR_MODERATION_CTL_REG[AQ_RINGS_NUM] 0x7c28-0x8428 */
+#define AQ2_TX_INTR_MODERATION_CTL_REG(i) (0x7c28 + (i) * 0x40)
+#define AQ2_TX_INTR_MODERATION_CTL_EN __BIT(1)
+#define AQ2_TX_INTR_MODERATION_CTL_MIN __BITS(15,8)
+#define AQ2_TX_INTR_MODERATION_CTL_MAX __BITS(24,16)
+
+/* RW shared buffer */
+#define AQ2_FW_INTERFACE_IN_MTU_REG 0x12000
+#define AQ2_FW_INTERFACE_IN_MAC_ADDRESS_REG 0x12008
+#define AQ2_FW_INTERFACE_IN_LINK_CONTROL_REG 0x12010
+#define AQ2_FW_INTERFACE_IN_LINK_CONTROL_PROMISCUOUS_MODE __BIT(13)
+#define AQ2_FW_INTERFACE_IN_LINK_CONTROL_FRAME_PADDING_REMOVAL_RX __BIT(12)
+#define AQ2_FW_INTERFACE_IN_LINK_CONTROL_CRC_FORWARDING __BIT(11)
+#define AQ2_FW_INTERFACE_IN_LINK_CONTROL_TX_PADDING __BIT(10)
+#define AQ2_FW_INTERFACE_IN_LINK_CONTROL_CONTROL_FRAME __BIT(9)
+#define AQ2_FW_INTERFACE_IN_LINK_CONTROL_DISCARD_ERROR_FRAME __BIT(8)
+#define AQ2_FW_INTERFACE_IN_LINK_CONTROL_DISABLE_LENGTH_CHECK __BIT(7)
+#define AQ2_FW_INTERFACE_IN_LINK_CONTROL_FLOW_CONTROL_MODE __BIT(6)
+#define AQ2_FW_INTERFACE_IN_LINK_CONTROL_DISCARD_SHORT_FRAMES __BIT(5)
+#define AQ2_FW_INTERFACE_IN_LINK_CONTROL_DISABLE_CRC_CORRUPTION __BIT(4)
+#define AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE __BITS(3,0)
+#define AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE_INVALID 0
+#define AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE_ACTIVE 1
+#define AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE_SLEEP_PROXY 2
+#define AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE_LOWPOWER 3
+#define AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE_SHUTDOWN 4
+
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_REG 0x12018
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_DOWNSHIFT_RETRY __BITS(31,28)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_DOWNSHIFT __BIT(27)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_PAUSE_TX __BIT(25)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_PAUSE_RX __BIT(24)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_EEE_10G __BIT(20)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_EEE_5G __BIT(19)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_EEE_2G5 __BIT(18)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_EEE_1G __BIT(17)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_EEE_100M __BIT(16)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_10G __BIT(15)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_N5G __BIT(14)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_5G __BIT(13)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_N2G5 __BIT(12)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_2G5 __BIT(11)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_1G __BIT(10)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_100M __BIT(9)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_10M __BIT(8)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_1G_HD __BIT(7)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_100M_HD __BIT(6)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_10M_HD __BIT(5)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_EXTERNAL_LOOPBACK __BIT(4)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_INTERNAL_LOOPBACK __BIT(3)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_MINIMAL_LINK_SPEED __BIT(2)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_LINK_RENEGOTIATE __BIT(1)
+#define AQ2_FW_INTERFACE_IN_LINK_OPTIONS_LINK_UP __BIT(0)
+
+#define AQ2_FW_INTERFACE_IN_THERMAL_SHUTDOWN_REG 0x12020
+#define AQ2_FW_INTERFACE_IN_THERMAL_SHUTDOWN_WARN_TEMP __BITS(24,31)
+#define AQ2_FW_INTERFACE_IN_THERMAL_SHUTDOWN_COLD_TEMP __BITS(16,23)
+#define AQ2_FW_INTERFACE_IN_THERMAL_SHUTDOWN_SHUTDOWN_TEMP __BITS(15,8)
+#define AQ2_FW_INTERFACE_IN_THERMAL_SHUTDOWN_WARNING_ENABLE __BIT(1)
+#define AQ2_FW_INTERFACE_IN_THERMAL_SHUTDOWN_ENABLE __BIT(0)
+
+#define AQ2_FW_INTERFACE_IN_SLEEP_PROXY 0x12028
+#define AQ2_FW_INTERFACE_IN_PAUSE_QUANTA 0x12984
+
+#define AQ2_FW_INTERFACE_IN_CABLE_DIAG_CONTROL_REG 0x12a44
+#define AQ2_FW_INTERFACE_IN_DATA_BUFFER_STATUS_OFF_REG 0x12a4c
+#define AQ2_FW_INTERFACE_IN_DATA_BUFFER_STATUS_LEN_REG 0x12a50
+#define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_REG 0x12a58
+#define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_MCAST_QUEUE_OR_TC __BIT(23)
+#define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_MCAST_RX_QUEUE_TC_INDEX __BITS(22,18)
+#define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_MCAST_ACCEPT __BIT(16)
+#define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_BCAST_QUEUE_OR_TC __BIT(15)
+#define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_BCAST_RX_QUEUE_TC_INDEX __BITS(14,10)
+#define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_BCAST_ACCEPT __BIT(8)
+#define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_PROMISC_QUEUE_OR_TC __BIT(7)
+#define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_PROMISC_RX_QUEUE_TX_INDEX __BITS(6,2)
+#define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_PROMISC_MCAST __BIT(1)
+#define AQ2_FW_INTERFACE_IN_REQUEST_POLICY_PROMISC_ALL __BIT(0)
+
+/* RO shared buffer */
+#define AQ2_FW_INTERFACE_OUT_TRANSACTION_ID_REG 0x13000
+#define AQ2_FW_INTERFACE_OUT_TRANSACTION_ID_B __BITS(31,16)
+#define AQ2_FW_INTERFACE_OUT_TRANSACTION_ID_A __BITS(15,0)
+#define AQ2_FW_INTERFACE_OUT_VERSION_BUNDLE_REG 0x13004
+#define AQ2_FW_INTERFACE_OUT_VERSION_MAC_REG 0x13008
+#define AQ2_FW_INTERFACE_OUT_VERSION_PHY_REG 0x1300c
+#define AQ2_FW_INTERFACE_OUT_VERSION_BUILD __BITS(31,16)
+#define AQ2_FW_INTERFACE_OUT_VERSION_MINOR __BITS(8,15)
+#define AQ2_FW_INTERFACE_OUT_VERSION_MAJOR __BITS(7,0)
+#define AQ2_FW_INTERFACE_OUT_VERSION_IFACE_REG 0x13010
+#define AQ2_FW_INTERFACE_OUT_VERSION_IFACE_VER __BITS(3,0)
+#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_LINK_STATUS_REG 0x13014
+#define AQ2_FW_INTERFACE_OUT_LINK_STATUS_DUPLEX __BIT(11)
+#define AQ2_FW_INTERFACE_OUT_LINK_STATUS_EEE __BIT(10)
+#define AQ2_FW_INTERFACE_OUT_LINK_STATUS_PAUSE_RX __BIT(9)
+#define AQ2_FW_INTERFACE_OUT_LINK_STATUS_PAUSE_TX __BIT(8)
+#define AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE __BITS(7,4)
+#define AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_10G 6
+#define AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_5G 5
+#define AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_2G5 4
+#define AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_1G 3
+#define AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_100M 2
+#define AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_10M 1
+#define AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_INVALID 0
+#define AQ2_FW_INTERFACE_OUT_LINK_STATUS_STATE __BITS(3,0)
+#define AQ2_FW_INTERFACE_OUT_WOL_STATUS_REG 0x13018
+
+#define AQ2_FW_INTERFACE_OUT_MAC_HEALTH_MONITOR 0x13610
+#define AQ2_FW_INTERFACE_OUT_PHY_HEALTH_MONITOR 0x13620
+typedef struct aq2_health_monitor {
+ uint32_t data1;
+#define HEALTH_MONITOR_DATA1_READY __BIT(0)
+#define HEALTH_MONITOR_DATA1_FAULT __BIT(1)
+#define HEALTH_MONITOR_DATA1_FLASHLESS_FINISHED __BIT(2)
+#define HEALTH_MONITOR_DATA1_HOT_WARNING __BIT(2)
+#define HEALTH_MONITOR_DATA1_TEMPERATURE __BITS(15,8)
+#define HEALTH_MONITOR_DATA1_HEARTBEAT __BITS(31,16)
+ uint32_t data2;
+#define HEALTH_MONITOR_DATA2_FAULTCODE __BITS(15,0)
+} aq2_health_monitor_t;
+
+#define AQ2_FW_INTERFACE_OUT_CABLE_DIAG_STATUS_LANE_REG(i) (0x13630 + (i) * 4)
+#define AQ2_FW_INTERFACE_OUT_CABLE_DIAG_STATUS_IDSTAT_REG 0x13640
+#define AQ2_FW_INTERFACE_OUT_CABLE_DIAG_STATUS_IDSTAT_ID __BITS(7,0)
+#define AQ2_FW_INTERFACE_OUT_CABLE_DIAG_STATUS_IDSTAT_STATUS __BITS(8,11)
+
+#define AQ2_FW_INTERFACE_OUT_DEVICE_LINK_CAPS_REG 0x13648
+#define AQ2_FW_INTERFACE_OUT_SLEEP_PROXY_CAPS_REG 0x13650
+#define AQ2_FW_INTERFACE_OUT_LKP_LINK_CAPS_REG 0x13660
+#define AQ2_FW_INTERFACE_OUT_LKP_LINK_CAPS_PAUSE_TX __BIT(25)
+#define AQ2_FW_INTERFACE_OUT_LKP_LINK_CAPS_PAUSE_RX __BIT(24)
+#define AQ2_FW_INTERFACE_OUT_LKP_LINK_CAPS_EEE_10G __BIT(23)
+#define AQ2_FW_INTERFACE_OUT_LKP_LINK_CAPS_EEE_5G __BIT(21)
+#define AQ2_FW_INTERFACE_OUT_LKP_LINK_CAPS_EEE_2G5 __BIT(19)
+#define AQ2_FW_INTERFACE_OUT_LKP_LINK_CAPS_EEE_1G __BIT(18)
+#define AQ2_FW_INTERFACE_OUT_LKP_LINK_CAPS_EEE_100M __BIT(17)
+#define AQ2_FW_INTERFACE_OUT_LKP_LINK_CAPS_RATE_10G __BIT(15)
+#define AQ2_FW_INTERFACE_OUT_LKP_LINK_CAPS_RATE_N5G __BIT(14)
+#define AQ2_FW_INTERFACE_OUT_LKP_LINK_CAPS_RATE_5G __BIT(13)
+#define AQ2_FW_INTERFACE_OUT_LKP_LINK_CAPS_RATE_N2G5 __BIT(12)
+#define AQ2_FW_INTERFACE_OUT_LKP_LINK_CAPS_RATE_2G5 __BIT(11)
+#define AQ2_FW_INTERFACE_OUT_LKP_LINK_CAPS_RATE_1G __BIT(10)
+#define AQ2_FW_INTERFACE_OUT_LKP_LINK_CAPS_RATE_100M __BIT(9)
+#define AQ2_FW_INTERFACE_OUT_LKP_LINK_CAPS_RATE_10M __BIT(8)
+#define AQ2_FW_INTERFACE_OUT_LKP_LINK_CAPS_RATE_1G_HD __BIT(7)
+#define AQ2_FW_INTERFACE_OUT_LKP_LINK_CAPS_RATE_100M_HD __BIT(6)
+#define AQ2_FW_INTERFACE_OUT_LKP_LINK_CAPS_RATE_10M_HD __BIT(5)
+
+#define AQ2_FW_INTERFACE_OUT_CORE_DUMP_REG 0x13668
+#define AQ2_FW_INTERFACE_OUT_STATS_REG 0x13700
+struct aq2_statistics_a0 {
+ uint32_t link_up;
+ uint32_t link_down;
+ uint64_t tx_unicast_octets;
+ uint64_t tx_multicast_octets;
+ uint64_t tx_broadcast_octets;
+ uint64_t rx_unicast_octets;
+ uint64_t rx_multicast_octets;
+ uint64_t rx_broadcast_octets;
+ uint32_t tx_unicast_frames;
+ uint32_t tx_multicast_frames;
+ uint32_t tx_broadcast_frames;
+ uint32_t tx_errors;
+ uint32_t rx_unicast_frames;
+ uint32_t rx_multicast_frames;
+ uint32_t rx_broadcast_frames;
+ uint32_t rx_dropped_frames;
+ uint32_t rx_errors;
+ uint32_t tx_good_frames;
+ uint32_t rx_good_frames;
+ uint32_t reserved1;
+ uint32_t main_loop_cycles;
+ uint32_t reserved2;
+};
+
+struct aq2_statistics_b0 {
+ uint64_t rx_good_octets;
+ uint64_t rx_pause_frames;
+ uint64_t rx_good_frames;
+ uint64_t rx_errors;
+ uint64_t rx_unicast_frames;
+ uint64_t rx_multicast_frames;
+ uint64_t rx_broadcast_frames;
+ uint64_t tx_good_octets;
+ uint64_t tx_pause_frames;
+ uint64_t tx_good_frames;
+ uint64_t tx_errors;
+ uint64_t tx_unicast_frames;
+ uint64_t tx_multicast_frames;
+ uint64_t tx_broadcast_frames;
+ uint32_t main_loop_cycles;
+} __packed;
+
+typedef struct aq2_statistics {
+ union {
+ struct aq2_statistics_a0 a0;
+ struct aq2_statistics_b0 b0;
+ };
+} aq2_statistics_t;
+
+#define AQ2_FW_INTERFACE_OUT_FILTER_CAPS_REG 0x13774
+typedef struct aq2_filter_caps {
+ uint32_t caps1;
+#define AQ2_FW_INTERFACE_OUT_FILTER_CAPS1_ETHTYPE_FILTER_COUNT __BITS(24,31)
+#define AQ2_FW_INTERFACE_OUT_FILTER_CAPS1_ETHTYPE_FILTER_BASE_INDEX __BITS(16,23)
+#define AQ2_FW_INTERFACE_OUT_FILTER_CAPS1_L2_FILTER_COUNT __BITS(8,15)
+#define AQ2_FW_INTERFACE_OUT_FILTER_CAPS1_FLEXIBLE_FILTER_MASK __BITS(6,7)
+#define AQ2_FW_INTERFACE_OUT_FILTER_CAPS1_L2_FILTER_BASE_INDEX __BITS(0,5)
+ uint32_t caps2;
+#define AQ2_FW_INTERFACE_OUT_FILTER_CAPS2_L3_IP6_FILTER_COUNT __BITS(28,31)
+#define AQ2_FW_INTERFACE_OUT_FILTER_CAPS2_L3_IP6_FILTER_BASE_INDEX __BITS(24,27)
+#define AQ2_FW_INTERFACE_OUT_FILTER_CAPS2_L3_IP4_FILTER_COUNT __BITS(20,23)
+#define AQ2_FW_INTERFACE_OUT_FILTER_CAPS2_L3_IP4_FILTER_BASE_INDEX __BITS(16,19)
+#define AQ2_FW_INTERFACE_OUT_FILTER_CAPS2_VLAN_FILTER_COUNT __BITS(8,15)
+#define AQ2_FW_INTERFACE_OUT_FILTER_CAPS2_VLAN_FILTER_BASE_INDEX __BITS(0,7)
+ uint32_t caps3;
+#define AQ2_FW_INTERFACE_OUT_FILTER_CAPS3_RESOLVER_TABLE_COUNT __BITS(24,31)
+#define AQ2_FW_INTERFACE_OUT_FILTER_CAPS3_RESOLVER_BASE_INDEX __BITS(16,23)
+#define AQ2_FW_INTERFACE_OUT_FILTER_CAPS3_L4_FLEX_FILTER_COUNT __BITS(12,15)
+#define AQ2_FW_INTERFACE_OUT_FILTER_CAPS3_L4_FLEX_FILTER_BASE_INDEX __BITS(8,11)
+#define AQ2_FW_INTERFACE_OUT_FILTER_CAPS3_L4_FILTER_COUNT __BITS(4,7)
+#define AQ2_FW_INTERFACE_OUT_FILTER_CAPS3_L4_FILTER_BASE_INDEX __BITS(0,3)
+} aq2_filter_caps_t;
+
+#define AQ2_FW_INTERFACE_OUT_DEVICE_CAPS_REG 0x13780
+#define AQ2_FW_INTERFACE_OUT_MANAGEMENT_STATUS_REG 0x1378c
+#define AQ2_FW_INTERFACE_OUT_TRACE_REG 0x13800
+
+#define AQ2_RPF_ACT_ART_REQ_TAG_REG(i) (0x14000 + (i) * 0x10)
+#define AQ2_RPF_ACT_ART_REQ_MASK_REG(i) (0x14004 + (i) * 0x10)
+#define AQ2_RPF_ACT_ART_REQ_ACTION_REG(i) (0x14008 + (i) * 0x10)
+
#define FW1X_CTRL_10G __BIT(0)
#define FW1X_CTRL_5G __BIT(1)
#define FW1X_CTRL_5GSR __BIT(2)
@@ -613,6 +976,9 @@ typedef enum aq_fw_bootloader_mode {
#define AQ_READ_REG(sc, reg) \
bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))
+#define AQ_READ_REGS(sc, reg, p, cnt) \
+ bus_space_read_region_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (p), (cnt))
+
#define AQ_READ64_REG(sc, reg) \
((uint64_t)AQ_READ_REG(sc, reg) | \
(((uint64_t)AQ_READ_REG(sc, (reg) + 4)) << 32))
@@ -733,15 +1099,16 @@ typedef struct fw2x_mailbox { /* struct
typedef enum aq_link_speed {
AQ_LINK_NONE = 0,
- AQ_LINK_100M = (1 << 0),
- AQ_LINK_1G = (1 << 1),
- AQ_LINK_2G5 = (1 << 2),
- AQ_LINK_5G = (1 << 3),
- AQ_LINK_10G = (1 << 4)
+ AQ_LINK_10G = __BIT(0),
+ AQ_LINK_5G = __BIT(1),
+ AQ_LINK_2G5 = __BIT(2),
+ AQ_LINK_1G = __BIT(3),
+ AQ_LINK_100M = __BIT(4),
+ AQ_LINK_10M = __BIT(5)
} aq_link_speed_t;
#define AQ_LINK_ALL (AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5 | \
AQ_LINK_5G | AQ_LINK_10G )
-#define AQ_LINK_AUTO AQ_LINK_ALL
+#define AQ_LINK_AUTO __BITS(31, 0)
typedef enum aq_link_fc {
AQ_FC_NONE = 0,
@@ -905,6 +1272,7 @@ struct aq_queue {
struct aq_softc;
struct aq_firmware_ops {
int (*reset)(struct aq_softc *);
+ int (*get_mac_addr)(struct aq_softc *);
int (*set_mode)(struct aq_softc *, aq_hw_fw_mpi_state_t,
aq_link_speed_t, aq_link_fc_t, aq_link_eee_t);
int (*get_mode)(struct aq_softc *, aq_hw_fw_mpi_state_t *,
@@ -941,7 +1309,7 @@ struct aq_firmware_ops {
#define AQ_UNLOCK(sc) mutex_exit(&(sc)->sc_mutex);
#define AQ_LOCKED(sc) KASSERT(mutex_owned(&(sc)->sc_mutex));
-/* lock for FW2X_MPI_{CONTROL,STATE]_REG read-modify-write */
+/* lock for firmware interface */
#define AQ_MPI_LOCK(sc) mutex_enter(&(sc)->sc_mpi_mutex);
#define AQ_MPI_UNLOCK(sc) mutex_exit(&(sc)->sc_mpi_mutex);
#define AQ_MPI_LOCKED(sc) KASSERT(mutex_owned(&(sc)->sc_mpi_mutex));
@@ -977,6 +1345,8 @@ struct aq_softc {
struct aq_queue sc_queue[AQ_RSSQUEUE_MAX];
int sc_nqueues;
+ uint32_t sc_tc_mode; /* traffic class mode (4 or 8) */
+ uint32_t sc_tcs; /* traffic class num */
pci_chipset_tag_t sc_pc;
pcitag_t sc_pcitag;
@@ -987,7 +1357,9 @@ struct aq_softc {
kmutex_t sc_mpi_mutex;
const struct aq_firmware_ops *sc_fw_ops;
- uint64_t sc_fw_caps;
+ uint64_t sc_fw_caps; /* AQ1 */
+ aq2_filter_caps_t sc_filter_caps; /* AQ2 */
+ uint32_t sc_filter_art_base_index; /* AQ2 */
enum aq_media_type sc_media_type;
aq_link_speed_t sc_available_rates;
@@ -1004,11 +1376,18 @@ struct aq_softc {
#define FEATURES_TPO2 0x00000002
#define FEATURES_RPF2 0x00000004
#define FEATURES_MPI_AQ 0x00000008
-#define FEATURES_REV_A0 0x10000000
-#define FEATURES_REV_A (FEATURES_REV_A0)
-#define FEATURES_REV_B0 0x20000000
-#define FEATURES_REV_B1 0x40000000
-#define FEATURES_REV_B (FEATURES_REV_B0|FEATURES_REV_B1)
+#define FEATURES_AQ1_REV_A0 0x01000000
+#define FEATURES_AQ1_REV_A (FEATURES_AQ1_REV_A0)
+#define FEATURES_AQ1_REV_B0 0x02000000
+#define FEATURES_AQ1_REV_B1 0x04000000
+#define FEATURES_AQ1_REV_B (FEATURES_AQ1_REV_B0 | FEATURES_AQ1_REV_B1)
+#define FEATURES_AQ1 (FEATURES_AQ1_REV_A | FEATURES_AQ1_REV_B)
+#define FEATURES_AQ2 0x10000000
+#define FEATURES_AQ2_IFACE_A0 0x20000000
+#define FEATURES_AQ2_IFACE_B0 0x40000000
+#define HWTYPE_AQ1_P(sc) (((sc)->sc_features & FEATURES_AQ1) != 0)
+#define HWTYPE_AQ2_P(sc) (((sc)->sc_features & FEATURES_AQ2) != 0)
+
int sc_max_mtu;
uint32_t sc_mbox_addr;
@@ -1112,14 +1491,14 @@ static int aq_set_linkmode(struct aq_sof
static int aq_get_linkmode(struct aq_softc *, aq_link_speed_t *, aq_link_fc_t *,
aq_link_eee_t *);
-static int aq_fw_reset(struct aq_softc *);
-static int aq_fw_version_init(struct aq_softc *);
+static int aq1_fw_reboot(struct aq_softc *);
+static int aq1_fw_version_init(struct aq_softc *);
static int aq_hw_init(struct aq_softc *);
-static int aq_hw_init_ucp(struct aq_softc *);
+static int aq1_hw_init_ucp(struct aq_softc *);
static int aq_hw_reset(struct aq_softc *);
-static int aq_fw_downld_dwords(struct aq_softc *, uint32_t, uint32_t *,
+static int aq1_fw_downld_dwords(struct aq_softc *, uint32_t, uint32_t *,
uint32_t);
-static int aq_get_mac_addr(struct aq_softc *);
+static int aq1_get_mac_addr(struct aq_softc *);
static int aq_init_rss(struct aq_softc *);
static int aq_set_capability(struct aq_softc *);
@@ -1145,9 +1524,24 @@ static int fw2x_get_temperature(struct a
#endif
static int aq_watchdog_timeout = AQ_WATCHDOG_TIMEOUT;
+static int aq2_fw_reboot(struct aq_softc *);
+static int aq2_fw_reset(struct aq_softc *);
+static int aq2_get_mac_addr(struct aq_softc *);
+static int aq2_fw_set_mode(struct aq_softc *, aq_hw_fw_mpi_state_t,
+ aq_link_speed_t, aq_link_fc_t, aq_link_eee_t);
+static int aq2_fw_get_mode(struct aq_softc *, aq_hw_fw_mpi_state_t *,
+ aq_link_speed_t *, aq_link_fc_t *, aq_link_eee_t *);
+static int aq2_init_filter(struct aq_softc *);
+static int aq2_filter_art_set(struct aq_softc *, uint32_t, uint32_t, uint32_t,
+ uint32_t);
+static int aq2_fw_get_stats(struct aq_softc *, aq_hw_stats_s_t *);
+#if NSYSMON_ENVSYS > 0
+static int aq2_fw_get_temperature(struct aq_softc *, uint32_t *);
+#endif
static const struct aq_firmware_ops aq_fw1x_ops = {
.reset = fw1x_reset,
+ .get_mac_addr = aq1_get_mac_addr,
.set_mode = fw1x_set_mode,
.get_mode = fw1x_get_mode,
.get_stats = fw1x_get_stats,
@@ -1158,6 +1552,7 @@ static const struct aq_firmware_ops aq_f
static const struct aq_firmware_ops aq_fw2x_ops = {
.reset = fw2x_reset,
+ .get_mac_addr = aq1_get_mac_addr,
.set_mode = fw2x_set_mode,
.get_mode = fw2x_get_mode,
.get_stats = fw2x_get_stats,
@@ -1166,6 +1561,17 @@ static const struct aq_firmware_ops aq_f
#endif
};
+static const struct aq_firmware_ops aq2_fw_ops = {
+ .reset = aq2_fw_reset,
+ .get_mac_addr = aq2_get_mac_addr,
+ .set_mode = aq2_fw_set_mode,
+ .get_mode = aq2_fw_get_mode,
+ .get_stats = aq2_fw_get_stats,
+#if NSYSMON_ENVSYS > 0
+ .get_temperature = aq2_fw_get_temperature
+#endif
+};
+
CFATTACH_DECL3_NEW(aq, sizeof(struct aq_softc),
aq_match, aq_attach, aq_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
@@ -1173,72 +1579,107 @@ static const struct aq_product {
pci_vendor_id_t aq_vendor;
pci_product_id_t aq_product;
const char *aq_name;
+ enum aq_hwtype aq_hwtype;
enum aq_media_type aq_media_type;
aq_link_speed_t aq_available_rates;
} aq_products[] = {
{ PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC100,
- "Aquantia AQC100 10 Gigabit Network Adapter",
+ "Aquantia AQC100 10 Gigabit Network Adapter", HWTYPE_AQ1,
AQ_MEDIA_TYPE_FIBRE, AQ_LINK_ALL
},
{ PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC107,
- "Aquantia AQC107 10 Gigabit Network Adapter",
+ "Aquantia AQC107 10 Gigabit Network Adapter", HWTYPE_AQ1,
AQ_MEDIA_TYPE_TP, AQ_LINK_ALL
},
{ PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC108,
- "Aquantia AQC108 5 Gigabit Network Adapter",
+ "Aquantia AQC108 5 Gigabit Network Adapter", HWTYPE_AQ1,
AQ_MEDIA_TYPE_TP, AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5 | AQ_LINK_5G
},
{ PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC109,
- "Aquantia AQC109 2.5 Gigabit Network Adapter",
+ "Aquantia AQC109 2.5 Gigabit Network Adapter", HWTYPE_AQ1,
AQ_MEDIA_TYPE_TP, AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5
},
{ PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC111,
- "Aquantia AQC111 5 Gigabit Network Adapter",
+ "Aquantia AQC111 5 Gigabit Network Adapter", HWTYPE_AQ1,
AQ_MEDIA_TYPE_TP, AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5 | AQ_LINK_5G
},
{ PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC112,
- "Aquantia AQC112 2.5 Gigabit Network Adapter",
+ "Aquantia AQC112 2.5 Gigabit Network Adapter", HWTYPE_AQ1,
AQ_MEDIA_TYPE_TP, AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5
},
{ PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC100S,
- "Aquantia AQC100S 10 Gigabit Network Adapter",
+ "Aquantia AQC100S 10 Gigabit Network Adapter", HWTYPE_AQ1,
AQ_MEDIA_TYPE_FIBRE, AQ_LINK_ALL
},
{ PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC107S,
- "Aquantia AQC107S 10 Gigabit Network Adapter",
+ "Aquantia AQC107S 10 Gigabit Network Adapter", HWTYPE_AQ1,
AQ_MEDIA_TYPE_TP, AQ_LINK_ALL
},
{ PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC108S,
- "Aquantia AQC108S 5 Gigabit Network Adapter",
+ "Aquantia AQC108S 5 Gigabit Network Adapter", HWTYPE_AQ1,
AQ_MEDIA_TYPE_TP, AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5 | AQ_LINK_5G
},
{ PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC109S,
- "Aquantia AQC109S 2.5 Gigabit Network Adapter",
+ "Aquantia AQC109S 2.5 Gigabit Network Adapter", HWTYPE_AQ1,
AQ_MEDIA_TYPE_TP, AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5
},
{ PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC111S,
- "Aquantia AQC111S 5 Gigabit Network Adapter",
+ "Aquantia AQC111S 5 Gigabit Network Adapter", HWTYPE_AQ1,
AQ_MEDIA_TYPE_TP, AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5 | AQ_LINK_5G
},
{ PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC112S,
- "Aquantia AQC112S 2.5 Gigabit Network Adapter",
+ "Aquantia AQC112S 2.5 Gigabit Network Adapter", HWTYPE_AQ1,
AQ_MEDIA_TYPE_TP, AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5
},
{ PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_D100,
- "Aquantia D100 10 Gigabit Network Adapter",
+ "Aquantia D100 10 Gigabit Network Adapter", HWTYPE_AQ1,
AQ_MEDIA_TYPE_FIBRE, AQ_LINK_ALL
},
{ PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_D107,
- "Aquantia D107 10 Gigabit Network Adapter",
+ "Aquantia D107 10 Gigabit Network Adapter", HWTYPE_AQ1,
AQ_MEDIA_TYPE_TP, AQ_LINK_ALL
},
{ PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_D108,
- "Aquantia D108 5 Gigabit Network Adapter",
+ "Aquantia D108 5 Gigabit Network Adapter", HWTYPE_AQ1,
AQ_MEDIA_TYPE_TP, AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5 | AQ_LINK_5G
},
{ PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_D109,
- "Aquantia D109 2.5 Gigabit Network Adapter",
+ "Aquantia D109 2.5 Gigabit Network Adapter", HWTYPE_AQ1,
AQ_MEDIA_TYPE_TP, AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5
+ },
+ { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC113DEV,
+ "Aquantia AQC113DEV 10 Gigabit Network Adapter", HWTYPE_AQ2,
+ AQ_MEDIA_TYPE_TP, AQ_LINK_ALL | AQ_LINK_10M
+ },
+ { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC113,
+ "Aquantia AQC113 10 Gigabit Network Adapter", HWTYPE_AQ2,
+ AQ_MEDIA_TYPE_TP, AQ_LINK_ALL | AQ_LINK_10M
+ },
+ { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC113C,
+ "Aquantia AQC113C 10 Gigabit Network Adapter", HWTYPE_AQ2,
+ AQ_MEDIA_TYPE_TP, AQ_LINK_ALL | AQ_LINK_10M
+ },
+ { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC113CA,
+ "Aquantia AQC113CA 10 Gigabit Network Adapter", HWTYPE_AQ2,
+ AQ_MEDIA_TYPE_TP, AQ_LINK_ALL | AQ_LINK_10M
+ },
+ { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC113CS,
+ "Aquantia AQC113CS 10 Gigabit Network Adapter", HWTYPE_AQ2,
+ AQ_MEDIA_TYPE_TP, AQ_LINK_ALL | AQ_LINK_10M
+ },
+ { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC114CS,
+ "Aquantia AQC114CS 5 Gigabit Network Adapter", HWTYPE_AQ2,
+ AQ_MEDIA_TYPE_TP,
+ AQ_LINK_10M | AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5 | AQ_LINK_5G
+ },
+ { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC115C,
+ "Aquantia AQC115C 2.5 Gigabit Network Adapter", HWTYPE_AQ2,
+ AQ_MEDIA_TYPE_TP,
+ AQ_LINK_10M | AQ_LINK_100M | AQ_LINK_1G | AQ_LINK_2G5
+ },
+ { PCI_VENDOR_AQUANTIA, PCI_PRODUCT_AQUANTIA_AQC116C,
+ "Aquantia AQC116C Gigabit Network Adapter", HWTYPE_AQ2,
+ AQ_MEDIA_TYPE_TP, AQ_LINK_10M | AQ_LINK_100M | AQ_LINK_1G
}
};
@@ -1311,12 +1752,20 @@ aq_attach(device_t parent, device_t self
return;
}
- error = aq_fw_reset(sc);
+ switch (aqp->aq_hwtype) {
+ case HWTYPE_AQ1:
+ error = aq1_fw_reboot(sc);
+ break;
+ case HWTYPE_AQ2:
+ error = aq2_fw_reboot(sc);
+ break;
+ default:
+ error = ENOTSUP;
+ break;
+ }
if (error != 0)
goto attach_failure;
- sc->sc_nqueues = MIN(ncpu, AQ_RSSQUEUE_MAX);
-
/* max queue num is 8, and must be 2^n */
if (ncpu >= 8)
sc->sc_nqueues = 8;
@@ -1327,6 +1776,9 @@ aq_attach(device_t parent, device_t self
else
sc->sc_nqueues = 1;
+ sc->sc_tc_mode = (sc->sc_nqueues <= 4) ? 8 : 4;
+ sc->sc_tcs = 1;
+
int msixcount = pci_msix_count(pa->pa_pc, pa->pa_tag);
#ifndef CONFIG_NO_TXRX_INDEPENDENT
if (msixcount >= (sc->sc_nqueues * 2 + 1)) {
@@ -1356,9 +1808,10 @@ aq_attach(device_t parent, device_t self
sc->sc_msix = false;
}
- /* on FW Ver1 or FIBRE, linkstat interrupt does not occur on boot? */
+ /* on AQ1a0, AQ2, or FIBRE, linkstat interrupt doesn't work? */
if (aqp->aq_media_type == AQ_MEDIA_TYPE_FIBRE ||
- FW_VERSION_MAJOR(sc) == 1)
+ (HWTYPE_AQ1_P(sc) && FW_VERSION_MAJOR(sc) == 1) ||
+ HWTYPE_AQ2_P(sc))
sc->sc_poll_linkstat = true;
#ifdef AQ_FORCE_POLL_LINKSTAT
@@ -1422,20 +1875,14 @@ aq_attach(device_t parent, device_t self
if (error != 0)
goto attach_failure;
- error = aq_fw_version_init(sc);
+ error = aq_hw_reset(sc);
if (error != 0)
goto attach_failure;
- error = aq_hw_init_ucp(sc);
- if (error < 0)
- goto attach_failure;
-
- KASSERT(sc->sc_mbox_addr != 0);
- error = aq_hw_reset(sc);
+ error = sc->sc_fw_ops->get_mac_addr(sc);
if (error != 0)
goto attach_failure;
- aq_get_mac_addr(sc);
aq_init_rss(sc);
error = aq_hw_init(sc); /* initialize and interrupts */
@@ -1517,8 +1964,8 @@ aq_attach(device_t parent, device_t self
#if NSYSMON_ENVSYS > 0
/* temperature monitoring */
if (sc->sc_fw_ops != NULL && sc->sc_fw_ops->get_temperature != NULL &&
- (sc->sc_fw_caps & FW2X_CTRL_TEMPERATURE) != 0) {
-
+ (((sc->sc_fw_caps & FW2X_CTRL_TEMPERATURE) != 0) ||
+ HWTYPE_AQ2_P(sc))) {
sc->sc_sme = sysmon_envsys_create();
sc->sc_sme->sme_name = device_xname(self);
sc->sc_sme->sme_cookie = sc;
@@ -1837,7 +2284,7 @@ aq_setup_legacy(struct aq_softc *sc, str
}
static void
-global_software_reset(struct aq_softc *sc)
+aq1_global_software_reset(struct aq_softc *sc)
{
uint32_t v;
@@ -1853,7 +2300,7 @@ global_software_reset(struct aq_softc *s
}
static int
-mac_soft_reset_rbl(struct aq_softc *sc, aq_fw_bootloader_mode_t *mode)
+aq1_mac_soft_reset_rbl(struct aq_softc *sc, aq_fw_bootloader_mode_t *mode)
{
int timo;
@@ -1866,7 +2313,7 @@ mac_soft_reset_rbl(struct aq_softc *sc,
/* MAC FW will reload PHY FW if 1E.1000.3 was cleaned - #undone */
AQ_WRITE_REG(sc, FW_BOOT_EXIT_CODE_REG, RBL_STATUS_DEAD);
- global_software_reset(sc);
+ aq1_global_software_reset(sc);
AQ_WRITE_REG(sc, AQ_FW_GLB_CTL2_REG, 0x40e0);
@@ -1907,7 +2354,7 @@ mac_soft_reset_rbl(struct aq_softc *sc,
}
static int
-mac_soft_reset_flb(struct aq_softc *sc)
+aq1_mac_soft_reset_flb(struct aq_softc *sc)
{
uint32_t v;
int timo;
@@ -1977,7 +2424,7 @@ mac_soft_reset_flb(struct aq_softc *sc)
AQ_WRITE_REG(sc, AQ_FW_GLB_CPU_SEM_REG(0), 1);
/* PHY Kickstart: #undone */
- global_software_reset(sc);
+ aq1_global_software_reset(sc);
for (timo = 0; timo < 1000; timo++) {
if (AQ_READ_REG(sc, AQ_FW_VERSION_REG) != 0)
@@ -1994,18 +2441,18 @@ mac_soft_reset_flb(struct aq_softc *sc)
}
static int
-mac_soft_reset(struct aq_softc *sc, aq_fw_bootloader_mode_t *mode)
+aq1_mac_soft_reset(struct aq_softc *sc, aq_fw_bootloader_mode_t *mode)
{
if (sc->sc_rbl_enabled)
- return mac_soft_reset_rbl(sc, mode);
+ return aq1_mac_soft_reset_rbl(sc, mode);
if (mode != NULL)
*mode = FW_BOOT_MODE_FLB;
- return mac_soft_reset_flb(sc);
+ return aq1_mac_soft_reset_flb(sc);
}
static int
-aq_fw_read_version(struct aq_softc *sc)
+aq1_fw_read_version(struct aq_softc *sc)
{
int i, error = EBUSY;
#define MAC_FW_START_TIMEOUT_MS 10000
@@ -2021,7 +2468,7 @@ aq_fw_read_version(struct aq_softc *sc)
}
static int
-aq_fw_reset(struct aq_softc *sc)
+aq1_fw_reboot(struct aq_softc *sc)
{
uint32_t ver, v, bootExitCode;
int i, error;
@@ -2048,17 +2495,17 @@ aq_fw_reset(struct aq_softc *sc)
* 2) Driver may skip reset sequence and save time.
*/
if (sc->sc_fast_start_enabled && (ver != 0)) {
- error = aq_fw_read_version(sc);
+ error = aq1_fw_read_version(sc);
/* Skip reset as it just completed */
if (error == 0)
return 0;
}
aq_fw_bootloader_mode_t mode = FW_BOOT_MODE_UNKNOWN;
- error = mac_soft_reset(sc, &mode);
+ error = aq1_mac_soft_reset(sc, &mode);
if (error != 0) {
aprint_error_dev(sc->sc_dev, "MAC reset failed: %d\n", error);
- return error;
+ return ENXIO;
}
switch (mode) {
@@ -2066,27 +2513,37 @@ aq_fw_reset(struct aq_softc *sc)
aprint_debug_dev(sc->sc_dev,
"FLB> F/W successfully loaded from flash.\n");
sc->sc_flash_present = true;
- return aq_fw_read_version(sc);
+ break;
case FW_BOOT_MODE_RBL_FLASH:
aprint_debug_dev(sc->sc_dev,
"RBL> F/W loaded from flash. Host Bootload disabled.\n");
sc->sc_flash_present = true;
- return aq_fw_read_version(sc);
+ break;
case FW_BOOT_MODE_UNKNOWN:
aprint_error_dev(sc->sc_dev,
"F/W bootload error: unknown bootloader type\n");
return ENOTSUP;
case FW_BOOT_MODE_RBL_HOST_BOOTLOAD:
aprint_debug_dev(sc->sc_dev, "RBL> Host Bootload mode\n");
- break;
+ aprint_error_dev(sc->sc_dev,
+ "RBL> F/W Host Bootload not implemented\n");
+ return ENOTSUP;
}
- /*
- * XXX: TODO: add support Host Boot
- */
- aprint_error_dev(sc->sc_dev,
- "RBL> F/W Host Bootload not implemented\n");
- return ENOTSUP;
+ error = aq1_fw_read_version(sc);
+ if (error != 0)
+ return error;
+
+ error = aq1_fw_version_init(sc);
+ if (error != 0)
+ return error;
+
+ error = aq1_hw_init_ucp(sc);
+ if (error < 0)
+ return error;
+
+ KASSERT(sc->sc_mbox_addr != 0);
+ return 0;
}
static int
@@ -2114,7 +2571,7 @@ aq_hw_reset(struct aq_softc *sc)
}
static int
-aq_hw_init_ucp(struct aq_softc *sc)
+aq1_hw_init_ucp(struct aq_softc *sc)
{
int timo;
@@ -2152,7 +2609,7 @@ aq_hw_init_ucp(struct aq_softc *sc)
}
static int
-aq_fw_version_init(struct aq_softc *sc)
+aq1_fw_version_init(struct aq_softc *sc)
{
int error = 0;
char fw_vers[sizeof("F/W version xxxxx.xxxxx.xxxxx")];
@@ -2177,25 +2634,25 @@ aq_fw_version_init(struct aq_softc *sc)
case 0x01:
aprint_normal_dev(sc->sc_dev, "Atlantic revision A0, %s\n",
fw_vers);
- sc->sc_features |= FEATURES_REV_A0 |
+ sc->sc_features |= FEATURES_AQ1_REV_A0 |
FEATURES_MPI_AQ | FEATURES_MIPS;
- sc->sc_max_mtu = AQ_JUMBO_MTU_REV_A;
+ sc->sc_max_mtu = AQ1_JUMBO_MTU_REV_A;
break;
case 0x02:
aprint_normal_dev(sc->sc_dev, "Atlantic revision B0, %s\n",
fw_vers);
- sc->sc_features |= FEATURES_REV_B0 |
+ sc->sc_features |= FEATURES_AQ1_REV_B0 |
FEATURES_MPI_AQ | FEATURES_MIPS |
FEATURES_TPO2 | FEATURES_RPF2;
- sc->sc_max_mtu = AQ_JUMBO_MTU_REV_B;
+ sc->sc_max_mtu = AQ1_JUMBO_MTU_REV_B;
break;
case 0x0A:
aprint_normal_dev(sc->sc_dev, "Atlantic revision B1, %s\n",
fw_vers);
- sc->sc_features |= FEATURES_REV_B1 |
+ sc->sc_features |= FEATURES_AQ1_REV_B1 |
FEATURES_MPI_AQ | FEATURES_MIPS |
FEATURES_TPO2 | FEATURES_RPF2;
- sc->sc_max_mtu = AQ_JUMBO_MTU_REV_B;
+ sc->sc_max_mtu = AQ1_JUMBO_MTU_REV_B;
break;
default:
aprint_error_dev(sc->sc_dev,
@@ -2223,7 +2680,7 @@ fw1x_reset(struct aq_softc *sc)
* Read the beginning of Statistics structure to capture
* the Transaction ID.
*/
- aq_fw_downld_dwords(sc, sc->sc_mbox_addr,
+ aq1_fw_downld_dwords(sc, sc->sc_mbox_addr,
(uint32_t *)&mbox, sizeof(mbox) / sizeof(uint32_t));
/* Successfully read the stats. */
@@ -2315,7 +2772,7 @@ fw1x_get_stats(struct aq_softc *sc, aq_h
{
int error;
- error = aq_fw_downld_dwords(sc,
+ error = aq1_fw_downld_dwords(sc,
sc->sc_mbox_addr + offsetof(fw1x_mailbox_t, msm), (uint32_t *)stats,
sizeof(aq_hw_stats_s_t) / sizeof(uint32_t));
if (error < 0) {
@@ -2335,7 +2792,7 @@ fw2x_reset(struct aq_softc *sc)
fw2x_capabilities_t caps = { 0 };
int error;
- error = aq_fw_downld_dwords(sc,
+ error = aq1_fw_downld_dwords(sc,
sc->sc_mbox_addr + offsetof(fw2x_mailbox_t, caps),
(uint32_t *)&caps, sizeof caps / sizeof(uint32_t));
if (error != 0) {
@@ -2503,7 +2960,7 @@ fw2x_get_stats(struct aq_softc *sc, aq_h
}
CTASSERT(sizeof(fw2x_msm_statistics_t) <= sizeof(struct aq_hw_stats_s));
- error = aq_fw_downld_dwords(sc,
+ error = aq1_fw_downld_dwords(sc,
sc->sc_mbox_addr + offsetof(fw2x_mailbox_t, msm), (uint32_t *)stats,
sizeof(fw2x_msm_statistics_t) / sizeof(uint32_t));
if (error != 0) {
@@ -2533,7 +2990,7 @@ fw2x_get_temperature(struct aq_softc *sc
if (error != 0)
goto failure;
- error = aq_fw_downld_dwords(sc,
+ error = aq1_fw_downld_dwords(sc,
sc->sc_mbox_addr + offsetof(fw2x_mailbox_t, phy_info2),
&value, sizeof(value) / sizeof(uint32_t));
if (error != 0)
@@ -2554,16 +3011,16 @@ fw2x_get_temperature(struct aq_softc *sc
#endif
static int
-aq_fw_downld_dwords(struct aq_softc *sc, uint32_t addr, uint32_t *p,
+aq1_fw_downld_dwords(struct aq_softc *sc, uint32_t addr, uint32_t *p,
uint32_t cnt)
{
uint32_t v;
int error = 0;
- WAIT_FOR(AQ_READ_REG(sc, AQ_FW_SEM_RAM_REG) == 1, 1, 10000, &error);
+ WAIT_FOR(AQ_READ_REG(sc, AQ1_FW_SEM_RAM_REG) == 1, 1, 10000, &error);
if (error != 0) {
- AQ_WRITE_REG(sc, AQ_FW_SEM_RAM_REG, 1);
- v = AQ_READ_REG(sc, AQ_FW_SEM_RAM_REG);
+ AQ_WRITE_REG(sc, AQ1_FW_SEM_RAM_REG, 1);
+ v = AQ_READ_REG(sc, AQ1_FW_SEM_RAM_REG);
if (v == 0) {
device_printf(sc->sc_dev,
"%s:%d: timeout\n", __func__, __LINE__);
@@ -2578,7 +3035,7 @@ aq_fw_downld_dwords(struct aq_softc *sc,
/* execute mailbox interface */
AQ_WRITE_REG_BIT(sc, AQ_FW_MBOX_CMD_REG,
AQ_FW_MBOX_CMD_EXECUTE, 1);
- if (sc->sc_features & FEATURES_REV_B1) {
+ if (sc->sc_features & FEATURES_AQ1_REV_B1) {
WAIT_FOR(AQ_READ_REG(sc, AQ_FW_MBOX_ADDR_REG) != addr,
1, 1000, &error);
} else {
@@ -2589,7 +3046,7 @@ aq_fw_downld_dwords(struct aq_softc *sc,
*p++ = AQ_READ_REG(sc, AQ_FW_MBOX_VAL_REG);
addr += sizeof(uint32_t);
}
- AQ_WRITE_REG(sc, AQ_FW_SEM_RAM_REG, 1);
+ AQ_WRITE_REG(sc, AQ1_FW_SEM_RAM_REG, 1);
if (error != 0)
device_printf(sc->sc_dev,
@@ -2600,7 +3057,7 @@ aq_fw_downld_dwords(struct aq_softc *sc,
/* read my mac address */
static int
-aq_get_mac_addr(struct aq_softc *sc)
+aq1_get_mac_addr(struct aq_softc *sc)
{
uint32_t mac_addr[2];
uint32_t efuse_shadow_addr;
@@ -2618,7 +3075,7 @@ aq_get_mac_addr(struct aq_softc *sc)
}
memset(mac_addr, 0, sizeof(mac_addr));
- err = aq_fw_downld_dwords(sc, efuse_shadow_addr + (40 * 4),
+ err = aq1_fw_downld_dwords(sc, efuse_shadow_addr + (40 * 4),
mac_addr, __arraycount(mac_addr));
if (err < 0)
return err;
@@ -2645,7 +3102,7 @@ aq_set_mac_addr(struct aq_softc *sc, int
{
uint32_t h, l;
- if (index >= AQ_HW_MAC_NUM)
+ if (index >= AQ_HW_MAC_NUM(sc))
return EINVAL;
if (enaddr == NULL) {
@@ -2655,16 +3112,21 @@ aq_set_mac_addr(struct aq_softc *sc, int
return 0;
}
- h = (enaddr[0] << 8) | (enaddr[1]);
+ h = (enaddr[0] << 8) | (enaddr[1]);
l = ((uint32_t)enaddr[2] << 24) | (enaddr[3] << 16) |
- (enaddr[4] << 8) | (enaddr[5]);
+ (enaddr[4] << 8) | (enaddr[5]);
/* disable, set, and enable */
AQ_WRITE_REG_BIT(sc, RPF_L2UC_MSW_REG(index), RPF_L2UC_MSW_EN, 0);
AQ_WRITE_REG(sc, RPF_L2UC_LSW_REG(index), l);
AQ_WRITE_REG_BIT(sc, RPF_L2UC_MSW_REG(index),
RPF_L2UC_MSW_MACADDR_HI, h);
- AQ_WRITE_REG_BIT(sc, RPF_L2UC_MSW_REG(index), RPF_L2UC_MSW_ACTION, 1);
+ AQ_WRITE_REG_BIT(sc, RPF_L2UC_MSW_REG(index),
+ RPF_L2UC_MSW_ACTION, RPF_ACTION_HOST);
+ if (HWTYPE_AQ2_P(sc)) {
+ AQ_WRITE_REG_BIT(sc, RPF_L2UC_MSW_REG(index),
+ RPF_L2UC_MSW_TAG, __SHIFTIN(1, AQ2_RPF_TAG_UC_MASK));
+ }
AQ_WRITE_REG_BIT(sc, RPF_L2UC_MSW_REG(index), RPF_L2UC_MSW_EN, 1);
return 0;
@@ -2745,6 +3207,15 @@ aq_set_filter(struct aq_softc *sc)
struct ether_multistep step;
int idx, error = 0;
+ if (HWTYPE_AQ2_P(sc)) {
+ uint32_t action = (ifp->if_flags & IFF_PROMISC) ?
+ AQ2_ART_ACTION_DISABLE : AQ2_ART_ACTION_DROP;
+ aq2_filter_art_set(sc, AQ2_RPF_INDEX_L2_PROMISC_OFF, 0,
+ AQ2_RPF_TAG_UC_MASK | AQ2_RPF_TAG_ALLMC_MASK, action);
+ aq2_filter_art_set(sc, AQ2_RPF_INDEX_VLAN_PROMISC_OFF, 0,
+ AQ2_RPF_TAG_VLAN_MASK | AQ2_RPF_TAG_UNTAG_MASK, action);
+ }
+
if (ifp->if_flags & IFF_PROMISC) {
AQ_WRITE_REG_BIT(sc, RPF_L2BC_REG, RPF_L2BC_PROMISC,
(ifp->if_flags & IFF_PROMISC) ? 1 : 0);
@@ -2753,7 +3224,7 @@ aq_set_filter(struct aq_softc *sc)
}
/* clear all table */
- for (idx = 0; idx < AQ_HW_MAC_NUM; idx++) {
+ for (idx = 0; idx < AQ_HW_MAC_NUM(sc); idx++) {
if (idx == AQ_HW_MAC_OWN) /* already used for own */
continue;
aq_set_mac_addr(sc, idx, NULL);
@@ -2772,7 +3243,7 @@ aq_set_filter(struct aq_softc *sc)
if (idx == AQ_HW_MAC_OWN)
idx++;
- if ((idx >= AQ_HW_MAC_NUM) ||
+ if ((idx >= AQ_HW_MAC_NUM(sc)) ||
memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
/*
* too many filters.
@@ -2800,6 +3271,475 @@ aq_set_filter(struct aq_softc *sc)
}
static int
+aq2_filter_art_set(struct aq_softc *sc, uint32_t idx,
+ uint32_t tag, uint32_t mask, uint32_t action)
+{
+ int error;
+
+ AQ_MPI_LOCK(sc);
+
+ WAIT_FOR(AQ_READ_REG(sc, AQ2_ART_SEM_REG) == 1, 10, 10000, &error);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "%s: timeout\n", __func__);
+ goto done;
+ }
+
+ idx += sc->sc_filter_art_base_index;
+ AQ_WRITE_REG(sc, AQ2_RPF_ACT_ART_REQ_TAG_REG(idx), tag);
+ AQ_WRITE_REG(sc, AQ2_RPF_ACT_ART_REQ_MASK_REG(idx), mask);
+ AQ_WRITE_REG(sc, AQ2_RPF_ACT_ART_REQ_ACTION_REG(idx), action);
+
+ AQ_WRITE_REG(sc, AQ2_ART_SEM_REG, 1);
+
+ done:
+ AQ_MPI_UNLOCK(sc);
+ return 0;
+}
+
+static int
+aq2_init_filter(struct aq_softc *sc)
+{
+ AQ_WRITE_REG_BIT(sc, AQ2_RPF_REC_TAB_ENABLE_REG,
+ AQ2_RPF_REC_TAB_ENABLE_MASK, 0xffff);
+ AQ_WRITE_REG_BIT(sc, RPF_L2UC_MSW_REG(0),
+ RPF_L2UC_MSW_TAG, __SHIFTIN(1, AQ2_RPF_TAG_UC_MASK));
+ AQ_WRITE_REG_BIT(sc, AQ2_RPF_L2BC_TAG_REG,
+ AQ2_RPF_L2BC_TAG_MASK, __SHIFTIN(1, AQ2_RPF_TAG_UC_MASK));
+
+ aq2_filter_art_set(sc, AQ2_RPF_INDEX_L2_PROMISC_OFF,
+ 0, AQ2_RPF_TAG_UC_MASK | AQ2_RPF_TAG_ALLMC_MASK,
+ AQ2_ART_ACTION_DROP);
+ aq2_filter_art_set(sc, AQ2_RPF_INDEX_VLAN_PROMISC_OFF,
+ 0, AQ2_RPF_TAG_VLAN_MASK | AQ2_RPF_TAG_UNTAG_MASK,
+ AQ2_ART_ACTION_DROP);
+
+ for (int i = 0; i < 8; i++) {
+ aq2_filter_art_set(sc, AQ2_RPF_INDEX_PCP_TO_TC + i,
+ __SHIFTIN(i, AQ2_RPF_TAG_PCP_MASK), AQ2_RPF_TAG_PCP_MASK,
+ AQ2_ART_ACTION_ASSIGN_TC(i % sc->sc_nqueues));
+ }
+
+ return 0;
+}
+
+static int
+aq2_interface_buffer_read(struct aq_softc *sc, uint32_t reg0, uint32_t *data0,
+ uint32_t size0)
+{
+ uint32_t tid0, tid1, reg, *data, size;
+ int timo;
+
+ for (timo = 10000; timo > 0; timo--) {
+ tid0 = AQ_READ_REG(sc, AQ2_FW_INTERFACE_OUT_TRANSACTION_ID_REG);
+ if (__SHIFTOUT(tid0, AQ2_FW_INTERFACE_OUT_TRANSACTION_ID_A) !=
+ __SHIFTOUT(tid0, AQ2_FW_INTERFACE_OUT_TRANSACTION_ID_B)) {
+ delay(10);
+ continue;
+ }
+
+ for (reg = reg0, data = data0, size = size0;
+ size >= 4; reg += 4, data++, size -= 4) {
+ *data = AQ_READ_REG(sc, reg);
+ }
+
+ tid1 = AQ_READ_REG(sc, AQ2_FW_INTERFACE_OUT_TRANSACTION_ID_REG);
+ if (tid0 == tid1)
+ break;
+ }
+ if (timo == 0) {
+ device_printf(sc->sc_dev, "%s: timeout\n", __func__);
+ return ETIMEDOUT;
+ }
+ return 0;
+}
+
+static int
+aq2_fw_reboot(struct aq_softc *sc)
+{
+ uint32_t v;
+ int timo;
+ char buf[32];
+
+ /* It seems that there is still only one type of firmware ABI in aq2 */
+ sc->sc_fw_ops = &aq2_fw_ops;
+ sc->sc_features |= FEATURES_AQ2;
+ sc->sc_max_mtu = AQ2_JUMBO_MTU;
+
+ AQ_WRITE_REG(sc, AQ2_MCP_HOST_REQ_INT_CLR_REG, 1);
+ AQ_WRITE_REG(sc, AQ2_MIF_BOOT_REG, 1); /* reboot request */
+ for (timo = 200000; timo > 0; timo--) {
+ v = AQ_READ_REG(sc, AQ2_MIF_BOOT_REG);
+ if ((v & AQ2_MIF_BOOT_BOOT_STARTED) && v != 0xffffffff)
+ break;
+ delay(10);
+ }
+ if (timo <= 0) {
+ aprint_error_dev(sc->sc_dev, "FW reboot timeout\n");
+ return ETIMEDOUT;
+ }
+
+ for (timo = 2000000; timo > 0; timo--) {
+ v = AQ_READ_REG(sc, AQ2_MIF_BOOT_REG);
+ if ((v & AQ2_MIF_BOOT_FW_INIT_FAILED) ||
+ (v & AQ2_MIF_BOOT_FW_INIT_COMP_SUCCESS))
+ break;
+ v = AQ_READ_REG(sc, AQ2_MCP_HOST_REQ_INT_REG);
+ if (v & AQ2_MCP_HOST_REQ_INT_READY)
+ break;
+ delay(10);
+ }
+ if (timo <= 0) {
+ aprint_error_dev(sc->sc_dev, "FW restart timeout\n");
+ return ETIMEDOUT;
+ }
+
+ v = AQ_READ_REG(sc, AQ2_MIF_BOOT_REG);
+ if (v & AQ2_MIF_BOOT_FW_INIT_FAILED) {
+ aprint_error_dev(sc->sc_dev, "FW restart failed\n");
+ return ETIMEDOUT;
+ }
+
+ v = AQ_READ_REG(sc, AQ2_MCP_HOST_REQ_INT_REG);
+ if (v & AQ2_MCP_HOST_REQ_INT_READY) {
+ aprint_error_dev(sc->sc_dev, "firmware required\n");
+ return ENXIO;
+ }
+
+ /*
+ * Get aq2 firmware version.
+ * Note that the bit layout and its meaning are different from aq1.
+ */
+ aq2_interface_buffer_read(sc, AQ2_FW_INTERFACE_OUT_VERSION_BUNDLE_REG,
+ (uint32_t *)&v, sizeof(v));
+ sc->sc_fw_version =
+ __SHIFTOUT(v, AQ2_FW_INTERFACE_OUT_VERSION_MAJOR) << 24 |
+ __SHIFTOUT(v, AQ2_FW_INTERFACE_OUT_VERSION_MINOR) << 16 |
+ __SHIFTOUT(v, AQ2_FW_INTERFACE_OUT_VERSION_BUILD);
+
+ aq2_interface_buffer_read(sc, AQ2_FW_INTERFACE_OUT_VERSION_IFACE_REG,
+ (uint32_t *)&v, sizeof(v));
+ switch (__SHIFTOUT(v, AQ2_FW_INTERFACE_OUT_VERSION_IFACE_VER)) {
+ case AQ2_FW_INTERFACE_OUT_VERSION_IFACE_VER_A0:
+ sc->sc_features |= FEATURES_AQ2_IFACE_A0;
+ strncpy(buf, "A0", sizeof(buf));
+ break;
+ case AQ2_FW_INTERFACE_OUT_VERSION_IFACE_VER_B0:
+ sc->sc_features |= FEATURES_AQ2_IFACE_B0;
+ strncpy(buf, "B0", sizeof(buf));
+ break;
+ default:
+ snprintf(buf, sizeof(buf), "(unknown 0x%08x)", v);
+ break;
+ }
+ aprint_normal_dev(sc->sc_dev,
+ "Atlantic2 %s, F/W version %d.%d.%d\n", buf,
+ FW_VERSION_MAJOR(sc), FW_VERSION_MINOR(sc), FW_VERSION_BUILD(sc));
+
+ aq2_interface_buffer_read(sc, AQ2_FW_INTERFACE_OUT_FILTER_CAPS_REG,
+ (uint32_t *)&sc->sc_filter_caps, sizeof(sc->sc_filter_caps));
+ sc->sc_filter_art_base_index = __SHIFTOUT(sc->sc_filter_caps.caps3,
+ AQ2_FW_INTERFACE_OUT_FILTER_CAPS3_RESOLVER_BASE_INDEX) * 8;
+
+ /* debug info */
+ v = AQ_READ_REG(sc, AQ_HW_REVISION_REG);
+ aprint_debug_dev(sc->sc_dev, "HW Rev: 0x%08x\n", v);
+
+ aq2_interface_buffer_read(sc, AQ2_FW_INTERFACE_OUT_VERSION_MAC_REG,
+ (uint32_t *)&v, sizeof(v));
+ aprint_debug_dev(sc->sc_dev, "MAC Version %d.%d.%d\n",
+ (int)__SHIFTOUT(v, AQ2_FW_INTERFACE_OUT_VERSION_MAJOR),
+ (int)__SHIFTOUT(v, AQ2_FW_INTERFACE_OUT_VERSION_MINOR),
+ (int)__SHIFTOUT(v, AQ2_FW_INTERFACE_OUT_VERSION_BUILD));
+
+ aq2_interface_buffer_read(sc, AQ2_FW_INTERFACE_OUT_VERSION_PHY_REG,
+ (uint32_t *)&v, sizeof(v));
+ aprint_debug_dev(sc->sc_dev, "PHY Version %d.%d.%d\n",
+ (int)__SHIFTOUT(v, AQ2_FW_INTERFACE_OUT_VERSION_MAJOR),
+ (int)__SHIFTOUT(v, AQ2_FW_INTERFACE_OUT_VERSION_MINOR),
+ (int)__SHIFTOUT(v, AQ2_FW_INTERFACE_OUT_VERSION_BUILD));
+
+ v = AQ_READ_REG(sc, AQ2_HW_FPGA_VERSION_REG);
+ aprint_debug_dev(sc->sc_dev, "AQ2 FPGA Version: %d.%d.%d.%d\n",
+ (int)__SHIFTOUT(v, __BITS(31, 24)),
+ (int)__SHIFTOUT(v, __BITS(23, 16)),
+ (int)__SHIFTOUT(v, __BITS(15, 8)),
+ (int)__SHIFTOUT(v, __BITS(7, 0)));
+
+ aprint_debug_dev(sc->sc_dev, "FILTER CAPS: 0x%08x,0x%08x,0x%08x\n",
+ sc->sc_filter_caps.caps1, sc->sc_filter_caps.caps2,
+ sc->sc_filter_caps.caps3);
+
+ return 0;
+}
+
+static int
+aq2_fw_wait_shared_ack(struct aq_softc *sc)
+{
+ int error;
+
+ AQ_WRITE_REG(sc, AQ2_MIF_HOST_FINISHED_STATUS_WRITE_REG,
+ AQ2_MIF_HOST_FINISHED_STATUS_ACK);
+ WAIT_FOR((AQ_READ_REG(sc, AQ2_MIF_HOST_FINISHED_STATUS_READ_REG) &
+ AQ2_MIF_HOST_FINISHED_STATUS_ACK) == 0, 100, 100000, &error);
+
+ return error;
+}
+
+static int
+aq2_fw_reset(struct aq_softc *sc)
+{
+ AQ_WRITE_REG_BIT(sc, AQ2_FW_INTERFACE_IN_LINK_CONTROL_REG,
+ AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE,
+ AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE_ACTIVE);
+
+ AQ_WRITE_REG(sc, AQ2_FW_INTERFACE_IN_MTU_REG,
+ AQ2_JUMBO_MTU + sizeof(struct ether_header));
+
+ uint32_t v = AQ_READ_REG(sc, AQ2_FW_INTERFACE_IN_REQUEST_POLICY_REG);
+ v |= AQ2_FW_INTERFACE_IN_REQUEST_POLICY_MCAST_QUEUE_OR_TC;
+ v &= ~AQ2_FW_INTERFACE_IN_REQUEST_POLICY_MCAST_RX_QUEUE_TC_INDEX;
+ v |= AQ2_FW_INTERFACE_IN_REQUEST_POLICY_MCAST_ACCEPT;
+ v |= AQ2_FW_INTERFACE_IN_REQUEST_POLICY_BCAST_QUEUE_OR_TC;
+ v &= AQ2_FW_INTERFACE_IN_REQUEST_POLICY_BCAST_RX_QUEUE_TC_INDEX;
+ v |= AQ2_FW_INTERFACE_IN_REQUEST_POLICY_BCAST_ACCEPT;
+ v |= AQ2_FW_INTERFACE_IN_REQUEST_POLICY_PROMISC_QUEUE_OR_TC;
+ v &= ~AQ2_FW_INTERFACE_IN_REQUEST_POLICY_PROMISC_RX_QUEUE_TX_INDEX;
+ AQ_WRITE_REG(sc, AQ2_FW_INTERFACE_IN_REQUEST_POLICY_REG, v);
+
+ return aq2_fw_wait_shared_ack(sc);
+}
+
+static int
+aq2_fw_set_mode(struct aq_softc *sc, aq_hw_fw_mpi_state_t mode,
+ aq_link_speed_t speed, aq_link_fc_t fc, aq_link_eee_t eee)
+{
+ uint32_t v;
+ int error;
+
+ AQ_MPI_LOCK(sc);
+
+ v = AQ_READ_REG(sc, AQ2_FW_INTERFACE_IN_LINK_OPTIONS_REG);
+ v &= ~(
+ AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_10G |
+ AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_N5G |
+ AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_5G |
+ AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_N2G5 |
+ AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_2G5 |
+ AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_1G |
+ AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_100M |
+ AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_10M |
+ AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_1G_HD |
+ AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_100M_HD |
+ AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_10M_HD);
+
+ v &= ~AQ2_FW_INTERFACE_IN_LINK_OPTIONS_LINK_UP;
+
+ if (speed & AQ_LINK_10G)
+ v |= AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_10G;
+ if (speed & AQ_LINK_5G)
+ v |= AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_N5G |
+ AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_5G;
+ if (speed & AQ_LINK_2G5)
+ v |= AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_N2G5 |
+ AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_2G5;
+ if (speed & AQ_LINK_1G)
+ v |= AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_1G |
+ AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_1G_HD;
+ if (speed & AQ_LINK_100M)
+ v |= AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_100M |
+ AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_100M_HD;
+ if (speed & AQ_LINK_10M) {
+ v |= AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_10M |
+ AQ2_FW_INTERFACE_IN_LINK_OPTIONS_RATE_10M_HD;
+ }
+
+ /* flow control */
+ v &= ~(AQ2_FW_INTERFACE_IN_LINK_OPTIONS_PAUSE_TX |
+ AQ2_FW_INTERFACE_IN_LINK_OPTIONS_PAUSE_RX);
+ if (fc & AQ_FC_TX)
+ v |= AQ2_FW_INTERFACE_IN_LINK_OPTIONS_PAUSE_TX;
+ if (fc & AQ_FC_RX)
+ v |= AQ2_FW_INTERFACE_IN_LINK_OPTIONS_PAUSE_RX;
+
+ if (speed == AQ_LINK_NONE) {
+ AQ_WRITE_REG_BIT(sc, AQ2_FW_INTERFACE_IN_LINK_CONTROL_REG,
+ AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE,
+ AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE_SHUTDOWN);
+ } else {
+ AQ_WRITE_REG_BIT(sc, AQ2_FW_INTERFACE_IN_LINK_CONTROL_REG,
+ AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE,
+ AQ2_FW_INTERFACE_IN_LINK_CONTROL_MODE_ACTIVE);
+ v |= AQ2_FW_INTERFACE_IN_LINK_OPTIONS_LINK_UP;
+ }
+
+ AQ_WRITE_REG(sc, AQ2_FW_INTERFACE_IN_LINK_OPTIONS_REG, v);
+ error = aq2_fw_wait_shared_ack(sc);
+
+ AQ_MPI_UNLOCK(sc);
+ return error;
+}
+
+static int
+aq2_fw_get_mode(struct aq_softc *sc, aq_hw_fw_mpi_state_t *modep,
+ aq_link_speed_t *speedp, aq_link_fc_t *fcp, aq_link_eee_t *eeep)
+{
+ aq_link_speed_t speed;
+ uint32_t v;
+
+ v = AQ_READ_REG(sc, AQ2_FW_INTERFACE_OUT_LINK_STATUS_REG);
+ switch (__SHIFTOUT(v, AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE)) {
+ case AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_10G:
+ speed = AQ_LINK_10G;
+ break;
+ case AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_5G:
+ speed = AQ_LINK_5G;
+ break;
+ case AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_2G5:
+ speed = AQ_LINK_2G5;
+ break;
+ case AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_1G:
+ speed = AQ_LINK_1G;
+ break;
+ case AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_100M:
+ speed = AQ_LINK_100M;
+ break;
+ case AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_10M:
+ speed = AQ_LINK_10M;
+ break;
+ case AQ2_FW_INTERFACE_OUT_LINK_STATUS_RATE_INVALID:
+ default:
+ speed = AQ_LINK_NONE;
+ break;
+ }
+ if (speedp != NULL)
+ *speedp = speed;
+
+ aq_link_fc_t fc = 0;
+ if (v & AQ2_FW_INTERFACE_OUT_LINK_STATUS_PAUSE_TX)
+ fc |= AQ_FC_TX;
+ if (v & AQ2_FW_INTERFACE_OUT_LINK_STATUS_PAUSE_RX)
+ fc |= AQ_FC_RX;
+ if (fcp != NULL)
+ *fcp = fc;
+
+ aq_link_eee_t eee;
+ eee = (v & AQ2_FW_INTERFACE_OUT_LINK_STATUS_EEE) ?
+ AQ_EEE_ENABLE : AQ_EEE_DISABLE;
+ if (eeep != NULL)
+ *eeep = eee;
+
+ return -1;
+}
+
+static int
+aq2_fw_get_stats(struct aq_softc *sc, aq_hw_stats_s_t *stats)
+{
+ aq2_statistics_t aq2stat;
+ int error;
+
+ AQ_MPI_LOCK(sc);
+ error = aq2_interface_buffer_read(sc, AQ2_FW_INTERFACE_OUT_STATS_REG,
+ (uint32_t *)&aq2stat, sizeof(aq2stat));
+ AQ_MPI_UNLOCK(sc);
+ if (error != 0)
+ return error;
+
+ if (sc->sc_features & FEATURES_AQ2_IFACE_A0) {
+ /* RX */
+ stats->uprc = aq2stat.a0.rx_unicast_frames;
+ stats->mprc = aq2stat.a0.rx_multicast_frames;
+ stats->bprc = aq2stat.a0.rx_broadcast_frames;
+ stats->erpr = aq2stat.a0.rx_errors;
+ stats->ubrc = aq2stat.a0.rx_unicast_octets;
+ stats->bbrc = aq2stat.a0.rx_broadcast_octets;
+ stats->mbrc = aq2stat.a0.rx_multicast_octets;
+ stats->prc = aq2stat.a0.rx_good_frames;
+ /* TX */
+ stats->uptc = aq2stat.a0.tx_unicast_frames;
+ stats->bptc = aq2stat.a0.tx_broadcast_frames;
+ stats->mptc = aq2stat.a0.tx_multicast_frames;
+ stats->erpt = aq2stat.a0.tx_errors;
+ stats->ubtc = aq2stat.a0.tx_unicast_octets;
+ stats->bbtc = aq2stat.a0.tx_broadcast_octets;
+ stats->mbtc = aq2stat.a0.tx_multicast_octets;
+ stats->ptc = aq2stat.a0.tx_good_frames;
+ } else if (sc->sc_features & FEATURES_AQ2_IFACE_B0) {
+ /* RX */
+ stats->uprc = aq2stat.b0.rx_unicast_frames;
+ stats->mprc = aq2stat.b0.rx_multicast_frames;
+ stats->bprc = aq2stat.b0.rx_broadcast_frames;
+ stats->erpr = aq2stat.b0.rx_errors;
+ stats->ubrc = 0;
+ stats->bbrc = 0;
+ stats->mbrc = 0;
+ stats->prc = aq2stat.b0.rx_good_frames;
+ /* TX */
+ stats->uptc = aq2stat.b0.tx_unicast_frames;
+ stats->bptc = aq2stat.b0.tx_multicast_frames;
+ stats->mptc = aq2stat.b0.tx_broadcast_frames;
+ stats->erpt = aq2stat.b0.tx_errors;
+ stats->ubtc = 0;
+ stats->bbtc = 0;
+ stats->mbtc = 0;
+ stats->ptc = aq2stat.b0.tx_good_frames;
+ } else {
+ return ENOTSUP;
+ }
+ stats->dpc = AQ_READ64_REG(sc, RX_DMA_DROP_PKT_CNT_REG);
+ stats->cprc = AQ_READ64_REG(sc, RX_DMA_COALESCED_PKT_CNT_REG);
+
+ return error;
+}
+
+#if NSYSMON_ENVSYS > 0
+static int
+aq2_fw_get_temperature(struct aq_softc *sc, uint32_t *temp)
+{
+ aq2_health_monitor_t health;
+ uint32_t data;
+
+ AQ_MPI_LOCK(sc);
+
+ aq2_interface_buffer_read(sc, AQ2_FW_INTERFACE_OUT_PHY_HEALTH_MONITOR,
+ (uint32_t *)&health, sizeof(health));
+
+ AQ_MPI_UNLOCK(sc);
+
+ data = __SHIFTOUT(health.data1, HEALTH_MONITOR_DATA1_TEMPERATURE);
+ if (data == 0)
+ return EIO;
+
+ *temp = data * 1000000 + 273150000;
+ return 0;
+}
+#endif
+
+static int
+aq2_get_mac_addr(struct aq_softc *sc)
+{
+ uint32_t mac_addr[2];
+
+ memset(mac_addr, 0, sizeof(mac_addr));
+ AQ_READ_REGS(sc, AQ2_FW_INTERFACE_IN_MAC_ADDRESS_REG,
+ mac_addr, __arraycount(mac_addr));
+
+ if (mac_addr[0] == 0 && mac_addr[1] == 0) {
+ aprint_error_dev(sc->sc_dev, "mac address not found\n");
+ return ENXIO;
+ }
+
+ HTOLE32(mac_addr[0]);
+ HTOLE32(mac_addr[1]);
+
+ memcpy(sc->sc_enaddr.ether_addr_octet,
+ (uint8_t *)mac_addr, ETHER_ADDR_LEN);
+ aprint_normal_dev(sc->sc_dev, "Etheraddr: %s\n",
+ ether_sprintf(sc->sc_enaddr.ether_addr_octet));
+
+ return 0;
+}
+
+static int
aq_ifmedia_change(struct ifnet * const ifp)
{
struct aq_softc * const sc = ifp->if_softc;
@@ -2818,6 +3758,9 @@ aq_ifmedia_change(struct ifnet * const i
case IFM_NONE:
rate = AQ_LINK_NONE;
break;
+ case IFM_10_T:
+ rate = AQ_LINK_10M;
+ break;
case IFM_100_TX:
rate = AQ_LINK_100M;
break;
@@ -2862,9 +3805,12 @@ aq_ifmedia_status(struct ifnet * const i
if (sc->sc_link_fc & AQ_FC_TX)
ifmr->ifm_active |= IFM_ETH_TXPAUSE;
+ /* XXX: need to detect fulldup or halfdup */
switch (sc->sc_link_rate) {
+ case AQ_LINK_10M:
+ ifmr->ifm_active |= IFM_10_T | IFM_FDX;
+ break;
case AQ_LINK_100M:
- /* XXX: need to detect fulldup or halfdup */
ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
break;
case AQ_LINK_1G:
@@ -2897,6 +3843,11 @@ aq_initmedia(struct aq_softc *sc)
ifmedia_add(&(sc)->sc_media, IFM_ETHER | media, 0, NULL);
IFMEDIA_ETHER_ADD(sc, IFM_NONE);
+
+ if (sc->sc_available_rates & AQ_LINK_10M) {
+ IFMEDIA_ETHER_ADD(sc, IFM_10_T);
+ IFMEDIA_ETHER_ADD(sc, IFM_10_T | IFM_FDX);
+ }
if (sc->sc_available_rates & AQ_LINK_100M) {
IFMEDIA_ETHER_ADD(sc, IFM_100_TX);
IFMEDIA_ETHER_ADD(sc, IFM_100_TX | IFM_FLOW);
@@ -2953,7 +3904,8 @@ static void
aq_hw_init_tx_path(struct aq_softc *sc)
{
/* Tx TC/RSS number config */
- AQ_WRITE_REG_BIT(sc, TPB_TX_BUF_REG, TPB_TX_BUF_TC_MODE_EN, 1);
+ AQ_WRITE_REG_BIT(sc, TPB_TX_BUF_REG, TPB_TX_BUF_TC_MODE,
+ (sc->sc_tc_mode == 4) ? 1 : 0);
AQ_WRITE_REG_BIT(sc, THM_LSO_TCP_FLAG1_REG,
THM_LSO_TCP_FLAG1_FIRST, 0x0ff6);
@@ -2969,6 +3921,10 @@ aq_hw_init_tx_path(struct aq_softc *sc)
AQ_WRITE_REG_BIT(sc, TDM_DCA_REG, TDM_DCA_MODE, 0);
AQ_WRITE_REG_BIT(sc, TPB_TX_BUF_REG, TPB_TX_BUF_SCP_INS_EN, 1);
+
+ if ((sc->sc_features & FEATURES_AQ1_REV_B) || HWTYPE_AQ2_P(sc)) {
+ AQ_WRITE_REG_BIT(sc, TPB_TX_BUF_REG, TPB_TX_BUF_CLK_GATE_EN, 0);
+ }
}
static void
@@ -2976,22 +3932,19 @@ aq_hw_init_rx_path(struct aq_softc *sc)
{
int i;
- /* clear setting */
- AQ_WRITE_REG_BIT(sc, RPB_RPF_RX_REG, RPB_RPF_RX_TC_MODE, 0);
+ /* Rx TC/RSS number config */
+ AQ_WRITE_REG_BIT(sc, RPB_RPF_RX_REG, RPB_RPF_RX_TC_MODE,
+ (sc->sc_tc_mode == 4) ? 1 : 0);
+
+ /* Rx flow control */
AQ_WRITE_REG_BIT(sc, RPB_RPF_RX_REG, RPB_RPF_RX_FC_MODE, 0);
- AQ_WRITE_REG(sc, RX_FLR_RSS_CONTROL1_REG, 0);
- for (i = 0; i < 32; i++) {
- AQ_WRITE_REG_BIT(sc, RPF_ETHERTYPE_FILTER_REG(i),
- RPF_ETHERTYPE_FILTER_EN, 0);
+
+ if (HWTYPE_AQ2_P(sc)) {
+ AQ_WRITE_REG_BIT(sc, AQ2_RPF_REDIR2_REG,
+ AQ2_RPF_REDIR2_HASHTYPE, AQ2_RPF_REDIR2_HASHTYPE_ALL);
}
if (sc->sc_rss_enable) {
- /* Rx TC/RSS number config */
- AQ_WRITE_REG_BIT(sc, RPB_RPF_RX_REG, RPB_RPF_RX_TC_MODE, 1);
-
- /* Rx flow control */
- AQ_WRITE_REG_BIT(sc, RPB_RPF_RX_REG, RPB_RPF_RX_FC_MODE, 1);
-
/* RSS Ring selection */
switch (sc->sc_nqueues) {
case 2:
@@ -3007,10 +3960,21 @@ aq_hw_init_rx_path(struct aq_softc *sc)
RX_FLR_RSS_CONTROL1_EN | 0x33333333);
break;
}
+ } else {
+ /* disable RSS */
+ AQ_WRITE_REG(sc, RX_FLR_RSS_CONTROL1_REG, 0);
+ }
+
+ if (HWTYPE_AQ1_P(sc)) {
+ /* multicast filter */
+ for (i = 0; i < 32; i++) {
+ AQ_WRITE_REG_BIT(sc, RPF_ETHERTYPE_FILTER_REG(i),
+ RPF_ETHERTYPE_FILTER_EN, 0);
+ }
}
/* L2 and Multicast filters */
- for (i = 0; i < AQ_HW_MAC_NUM; i++) {
+ for (i = 0; i < AQ_HW_MAC_NUM(sc); i++) {
AQ_WRITE_REG_BIT(sc, RPF_L2UC_MSW_REG(i), RPF_L2UC_MSW_EN, 0);
AQ_WRITE_REG_BIT(sc, RPF_L2UC_MSW_REG(i), RPF_L2UC_MSW_ACTION,
RPF_ACTION_HOST);
@@ -3025,27 +3989,36 @@ aq_hw_init_rx_path(struct aq_softc *sc)
ETHERTYPE_VLAN);
AQ_WRITE_REG_BIT(sc, RPF_VLAN_MODE_REG, RPF_VLAN_MODE_PROMISC, 0);
- if (sc->sc_features & FEATURES_REV_B) {
+ if ((sc->sc_features & FEATURES_AQ1_REV_B) || HWTYPE_AQ2_P(sc)) {
AQ_WRITE_REG_BIT(sc, RPF_VLAN_MODE_REG,
RPF_VLAN_MODE_ACCEPT_UNTAGGED, 1);
AQ_WRITE_REG_BIT(sc, RPF_VLAN_MODE_REG,
RPF_VLAN_MODE_UNTAGGED_ACTION, RPF_ACTION_HOST);
}
- /* misc */
- if (sc->sc_features & FEATURES_RPF2)
- AQ_WRITE_REG(sc, RX_TCP_RSS_HASH_REG, RX_TCP_RSS_HASH_RPF2);
- else
- AQ_WRITE_REG(sc, RX_TCP_RSS_HASH_REG, 0);
+ if (HWTYPE_AQ2_P(sc)) {
+ aq2_init_filter(sc);
+ }
- /*
- * XXX: RX_TCP_RSS_HASH_REG:
- * linux set 0x000f0000
- * freebsd set 0x000f001e
- */
- /* RSS hash type set for IP/TCP */
- AQ_WRITE_REG_BIT(sc, RX_TCP_RSS_HASH_REG,
- RX_TCP_RSS_HASH_TYPE, 0x001e);
+ AQ_WRITE_REG_BIT(sc, RX_DMA_INT_DESC_WRWB_EN_REG,
+ RX_DMA_INT_DESC_WRWB_EN, 1);
+
+ if (HWTYPE_AQ1_P(sc)) {
+ if (sc->sc_features & FEATURES_RPF2) {
+ AQ_WRITE_REG(sc, RX_TCP_RSS_HASH_REG,
+ RX_TCP_RSS_HASH_RPF2);
+ } else {
+ AQ_WRITE_REG(sc, RX_TCP_RSS_HASH_REG, 0);
+ }
+ /*
+ * XXX: RX_TCP_RSS_HASH_REG:
+ * linux set 0x000f0000
+ * freebsd set 0x000f001e
+ */
+ /* RSS hash type set for IP/TCP */
+ AQ_WRITE_REG_BIT(sc, RX_TCP_RSS_HASH_REG,
+ RX_TCP_RSS_HASH_TYPE, 0x001e);
+ }
AQ_WRITE_REG_BIT(sc, RPF_L2BC_REG, RPF_L2BC_EN, 1);
AQ_WRITE_REG_BIT(sc, RPF_L2BC_REG, RPF_L2BC_ACTION, RPF_ACTION_HOST);
@@ -3058,6 +4031,7 @@ aq_hw_init_rx_path(struct aq_softc *sc)
static void
aq_hw_interrupt_moderation_set(struct aq_softc *sc)
{
+ uint32_t v;
int i;
if (sc->sc_intr_moderation_enable) {
@@ -3065,6 +4039,7 @@ aq_hw_interrupt_moderation_set(struct aq
unsigned int tx_max, rx_max; /* 0-511? */
switch (sc->sc_link_rate) {
+ case AQ_LINK_10M:
case AQ_LINK_100M:
tx_min = 0x4f;
tx_max = 0xff;
@@ -3107,12 +4082,24 @@ aq_hw_interrupt_moderation_set(struct aq
AQ_WRITE_REG_BIT(sc, RX_DMA_INT_DESC_WRWB_EN_REG,
RX_DMA_INT_DESC_MODERATE_EN, 1);
- for (i = 0; i < AQ_RINGS_NUM; i++) {
- AQ_WRITE_REG(sc, TX_INTR_MODERATION_CTL_REG(i),
- __SHIFTIN(tx_min, TX_INTR_MODERATION_CTL_MIN) |
+ if (HWTYPE_AQ2_P(sc)) {
+ v = __SHIFTIN(tx_min, AQ2_TX_INTR_MODERATION_CTL_MIN) |
+ __SHIFTIN(tx_max, AQ2_TX_INTR_MODERATION_CTL_MAX) |
+ AQ2_TX_INTR_MODERATION_CTL_EN;
+ for (i = 0; i < AQ_RINGS_NUM; i++) {
+ AQ_WRITE_REG(sc,
+ AQ2_TX_INTR_MODERATION_CTL_REG(i), v);
+ }
+ } else {
+ v = __SHIFTIN(tx_min, TX_INTR_MODERATION_CTL_MIN) |
__SHIFTIN(tx_max, TX_INTR_MODERATION_CTL_MAX) |
- TX_INTR_MODERATION_CTL_EN);
+ TX_INTR_MODERATION_CTL_EN;
+ for (i = 0; i < AQ_RINGS_NUM; i++) {
+ AQ_WRITE_REG(sc,
+ TX_INTR_MODERATION_CTL_REG(i), v);
+ }
}
+
for (i = 0; i < AQ_RINGS_NUM; i++) {
AQ_WRITE_REG(sc, RX_INTR_MODERATION_CTL_REG(i),
__SHIFTIN(rx_min, RX_INTR_MODERATION_CTL_MIN) |
@@ -3130,9 +4117,18 @@ aq_hw_interrupt_moderation_set(struct aq
AQ_WRITE_REG_BIT(sc, RX_DMA_INT_DESC_WRWB_EN_REG,
RX_DMA_INT_DESC_MODERATE_EN, 0);
- for (i = 0; i < AQ_RINGS_NUM; i++) {
- AQ_WRITE_REG(sc, TX_INTR_MODERATION_CTL_REG(i), 0);
+ if (HWTYPE_AQ2_P(sc)) {
+ for (i = 0; i < AQ_RINGS_NUM; i++) {
+ AQ_WRITE_REG(sc,
+ AQ2_TX_INTR_MODERATION_CTL_REG(i), 0);
+ }
+ } else {
+ for (i = 0; i < AQ_RINGS_NUM; i++) {
+ AQ_WRITE_REG(sc,
+ TX_INTR_MODERATION_CTL_REG(i), 0);
+ }
}
+
for (i = 0; i < AQ_RINGS_NUM; i++) {
AQ_WRITE_REG(sc, RX_INTR_MODERATION_CTL_REG(i), 0);
}
@@ -3142,8 +4138,7 @@ aq_hw_interrupt_moderation_set(struct aq
static void
aq_hw_qos_set(struct aq_softc *sc)
{
- uint32_t tc = 0;
- uint32_t buff_size;
+ uint32_t tc, tx_bufsize, rx_bufsize;
/* TPS Descriptor rate init */
AQ_WRITE_REG_BIT(sc, TPS_DESC_RATE_REG, TPS_DESC_RATE_TA_RST, 0);
@@ -3156,45 +4151,89 @@ aq_hw_qos_set(struct aq_softc *sc)
AQ_WRITE_REG_BIT(sc, TPS_DESC_TC_ARB_MODE_REG, TPS_DESC_TC_ARB_MODE, 0);
AQ_WRITE_REG_BIT(sc, TPS_DATA_TC_ARB_MODE_REG, TPS_DATA_TC_ARB_MODE, 0);
- AQ_WRITE_REG_BIT(sc, TPS_DATA_TCT_REG(tc),
- TPS_DATA_TCT_CREDIT_MAX, 0xfff);
- AQ_WRITE_REG_BIT(sc, TPS_DATA_TCT_REG(tc),
- TPS_DATA_TCT_WEIGHT, 0x64);
- AQ_WRITE_REG_BIT(sc, TPS_DESC_TCT_REG(tc),
- TPS_DESC_TCT_CREDIT_MAX, 0x50);
- AQ_WRITE_REG_BIT(sc, TPS_DESC_TCT_REG(tc),
- TPS_DESC_TCT_WEIGHT, 0x1e);
-
- /* Tx buf size */
- tc = 0;
- buff_size = AQ_HW_TXBUF_MAX;
- AQ_WRITE_REG_BIT(sc, TPB_TXB_BUFSIZE_REG(tc), TPB_TXB_BUFSIZE,
- buff_size);
- AQ_WRITE_REG_BIT(sc, TPB_TXB_THRESH_REG(tc), TPB_TXB_THRESH_HI,
- (buff_size * (1024 / 32) * 66) / 100);
- AQ_WRITE_REG_BIT(sc, TPB_TXB_THRESH_REG(tc), TPB_TXB_THRESH_LO,
- (buff_size * (1024 / 32) * 50) / 100);
-
- /* QoS Rx buf size per TC */
- tc = 0;
- buff_size = AQ_HW_RXBUF_MAX;
- AQ_WRITE_REG_BIT(sc, RPB_RXB_BUFSIZE_REG(tc), RPB_RXB_BUFSIZE,
- buff_size);
- AQ_WRITE_REG_BIT(sc, RPB_RXB_XOFF_REG(tc), RPB_RXB_XOFF_EN, 0);
- AQ_WRITE_REG_BIT(sc, RPB_RXB_XOFF_REG(tc), RPB_RXB_XOFF_THRESH_HI,
- (buff_size * (1024 / 32) * 66) / 100);
- AQ_WRITE_REG_BIT(sc, RPB_RXB_XOFF_REG(tc), RPB_RXB_XOFF_THRESH_LO,
- (buff_size * (1024 / 32) * 50) / 100);
+ if (HWTYPE_AQ1_P(sc)) {
+ tx_bufsize = AQ1_HW_TXBUF_MAX / sc->sc_tcs;
+ rx_bufsize = AQ1_HW_RXBUF_MAX / sc->sc_tcs;
+ } else {
+ tx_bufsize = AQ2_HW_TXBUF_MAX / sc->sc_tcs;
+ rx_bufsize = AQ2_HW_RXBUF_MAX / sc->sc_tcs;
+ }
+
+ for (tc = 0; tc < sc->sc_tcs; tc++) {
+ AQ_WRITE_REG_BIT(sc, TPS_DATA_TCT_REG(tc),
+ TPS_DATA_TCT_CREDIT_MAX, 0xfff);
+ AQ_WRITE_REG_BIT(sc, TPS_DATA_TCT_REG(tc),
+ TPS_DATA_TCT_WEIGHT, 0x64);
+ AQ_WRITE_REG_BIT(sc, TPS_DESC_TCT_REG(tc),
+ TPS_DESC_TCT_CREDIT_MAX, 0x50);
+ AQ_WRITE_REG_BIT(sc, TPS_DESC_TCT_REG(tc),
+ TPS_DESC_TCT_WEIGHT, 0x1e);
+
+ /* Tx buf size */
+ AQ_WRITE_REG_BIT(sc, TPB_TXB_BUFSIZE_REG(tc), TPB_TXB_BUFSIZE,
+ tx_bufsize);
+ AQ_WRITE_REG_BIT(sc, TPB_TXB_THRESH_REG(tc), TPB_TXB_THRESH_HI,
+ (tx_bufsize * (1024 / 32) * 66) / 100);
+ AQ_WRITE_REG_BIT(sc, TPB_TXB_THRESH_REG(tc), TPB_TXB_THRESH_LO,
+ (tx_bufsize * (1024 / 32) * 50) / 100);
+
+ /* QoS Rx buf size per TC */
+ AQ_WRITE_REG_BIT(sc, RPB_RXB_XOFF_REG(tc), RPB_RXB_XOFF_EN, 0);
+ AQ_WRITE_REG_BIT(sc, RPB_RXB_BUFSIZE_REG(tc), RPB_RXB_BUFSIZE,
+ rx_bufsize);
+ AQ_WRITE_REG_BIT(sc, RPB_RXB_XOFF_REG(tc),
+ RPB_RXB_XOFF_THRESH_HI,
+ (rx_bufsize * (1024 / 32) * 66) / 100);
+ AQ_WRITE_REG_BIT(sc, RPB_RXB_XOFF_REG(tc),
+ RPB_RXB_XOFF_THRESH_LO,
+ (rx_bufsize * (1024 / 32) * 50) / 100);
+ }
/* QoS 802.1p priority -> TC mapping */
- int i_priority;
- for (i_priority = 0; i_priority < 8; i_priority++) {
+ for (int pri = 0; pri < 8; pri++) {
AQ_WRITE_REG_BIT(sc, RPF_RPB_RX_TC_UPT_REG,
- RPF_RPB_RX_TC_UPT_MASK(i_priority), 0);
+ RPF_RPB_RX_TC_UPT_MASK(pri), sc->sc_tcs * pri / 8);
+ }
+
+ /* ring to TC mapping */
+ if (HWTYPE_AQ2_P(sc)) {
+ AQ_WRITE_REG_BIT(sc, TPB_TX_BUF_REG,
+ TPB_TX_BUF_TC_Q_RAND_MAP_EN, 1);
+ switch (sc->sc_tc_mode) {
+ case 4:
+ AQ_WRITE_REG(sc, AQ2_TX_Q_TC_MAP_REG(0), 0x00000000);
+ AQ_WRITE_REG(sc, AQ2_TX_Q_TC_MAP_REG(1), 0x00000000);
+ AQ_WRITE_REG(sc, AQ2_TX_Q_TC_MAP_REG(2), 0x01010101);
+ AQ_WRITE_REG(sc, AQ2_TX_Q_TC_MAP_REG(3), 0x01010101);
+ AQ_WRITE_REG(sc, AQ2_TX_Q_TC_MAP_REG(4), 0x02020202);
+ AQ_WRITE_REG(sc, AQ2_TX_Q_TC_MAP_REG(5), 0x02020202);
+ AQ_WRITE_REG(sc, AQ2_TX_Q_TC_MAP_REG(6), 0x03030303);
+ AQ_WRITE_REG(sc, AQ2_TX_Q_TC_MAP_REG(7), 0x03030303);
+
+ AQ_WRITE_REG(sc, AQ2_RX_Q_TC_MAP_REG(0), 0x00000000);
+ AQ_WRITE_REG(sc, AQ2_RX_Q_TC_MAP_REG(1), 0x11111111);
+ AQ_WRITE_REG(sc, AQ2_RX_Q_TC_MAP_REG(2), 0x22222222);
+ AQ_WRITE_REG(sc, AQ2_RX_Q_TC_MAP_REG(3), 0x33333333);
+ break;
+ case 8:
+ AQ_WRITE_REG(sc, AQ2_TX_Q_TC_MAP_REG(0), 0x00000000);
+ AQ_WRITE_REG(sc, AQ2_TX_Q_TC_MAP_REG(1), 0x01010101);
+ AQ_WRITE_REG(sc, AQ2_TX_Q_TC_MAP_REG(2), 0x02020202);
+ AQ_WRITE_REG(sc, AQ2_TX_Q_TC_MAP_REG(3), 0x03030303);
+ AQ_WRITE_REG(sc, AQ2_TX_Q_TC_MAP_REG(4), 0x04040404);
+ AQ_WRITE_REG(sc, AQ2_TX_Q_TC_MAP_REG(5), 0x05050505);
+ AQ_WRITE_REG(sc, AQ2_TX_Q_TC_MAP_REG(6), 0x06060606);
+ AQ_WRITE_REG(sc, AQ2_TX_Q_TC_MAP_REG(7), 0x07070707);
+
+ AQ_WRITE_REG(sc, AQ2_RX_Q_TC_MAP_REG(0), 0x11110000);
+ AQ_WRITE_REG(sc, AQ2_RX_Q_TC_MAP_REG(1), 0x33332222);
+ AQ_WRITE_REG(sc, AQ2_RX_Q_TC_MAP_REG(2), 0x55554444);
+ AQ_WRITE_REG(sc, AQ2_RX_Q_TC_MAP_REG(3), 0x77776666);
+ break;
+ }
}
}
-/* called once from aq_attach */
static int
aq_init_rss(struct aq_softc *sc)
{
@@ -3204,6 +4243,21 @@ aq_init_rss(struct aq_softc *sc)
unsigned int i;
int error;
+ if (HWTYPE_AQ2_P(sc)) {
+ uint32_t q_per_tc = (sc->sc_tc_mode == 8) ? 4 : 8;
+ uint32_t tc;
+
+ AQ_WRITE_REG_BIT(sc, AQ2_RPF_REDIR2_REG,
+ AQ2_RPF_REDIR2_INDEX, (sc->sc_tc_mode == 8) ? 1 : 0);
+ for (i = 0; i < AQ_RSS_INDIRECTION_TABLE_MAX; i++) {
+ for (tc = 0; tc < sc->sc_tc_mode; tc++) {
+ uint32_t q = tc * q_per_tc + (i % sc->sc_nqueues);
+ AQ_WRITE_REG_BIT(sc, AQ2_RPF_RSS_REDIR_REG(tc, i),
+ AQ2_RPF_RSS_REDIR_TC_MASK(tc), q);
+ }
+ }
+ }
+
/* initialize rss key */
rss_getkey((uint8_t *)rss_key);
@@ -3283,7 +4337,7 @@ aq_init_rss(struct aq_softc *sc)
}
static void
-aq_hw_l3_filter_set(struct aq_softc *sc)
+aq1_hw_l3_filter_set(struct aq_softc *sc)
{
int i;
@@ -3305,8 +4359,15 @@ aq_set_vlan_filters(struct aq_softc *sc)
ETHER_LOCK(ec);
/* disable all vlan filters */
- for (i = 0; i < RPF_VLAN_MAX_FILTERS; i++)
+ for (i = 0; i < RPF_VLAN_MAX_FILTERS; i++) {
AQ_WRITE_REG(sc, RPF_VLAN_FILTER_REG(i), 0);
+ if (HWTYPE_AQ2_P(sc)) {
+ aq2_filter_art_set(sc, AQ2_RPF_INDEX_VLAN_USER + i,
+ 0, 0, AQ2_ART_ACTION_DISABLE);
+ AQ_WRITE_REG_BIT(sc, RPF_VLAN_FILTER_REG(i),
+ RPF_VLAN_FILTER_TAG, 1);
+ }
+ }
/* count VID */
i = 0;
@@ -3339,6 +4400,22 @@ aq_set_vlan_filters(struct aq_softc *sc)
RPF_VLAN_FILTER_ACTION, RPF_ACTION_HOST);
AQ_WRITE_REG_BIT(sc, RPF_VLAN_FILTER_REG(i),
RPF_VLAN_FILTER_ID, vlanidp->vid);
+
+ if (HWTYPE_AQ2_P(sc)) {
+ /*
+ * If you want to fix the ring (CPU) for each VLAN ID,
+ * Use AQ2_ART_ACTION_ASSIGN_QUEUE(i % sc->sc_nqueues)
+ * instead of AQ2_ART_ACTION_ASSIGN_TC().
+ */
+ uint32_t action =
+ AQ2_ART_ACTION_ASSIGN_TC(i % sc->sc_nqueues);
+
+ AQ_WRITE_REG_BIT(sc, RPF_VLAN_FILTER_REG(i),
+ RPF_VLAN_FILTER_TAG, i + 2);
+ aq2_filter_art_set(sc, AQ2_RPF_INDEX_VLAN_USER + i,
+ __SHIFTIN(i + 2, AQ2_RPF_TAG_VLAN_MASK),
+ AQ2_RPF_TAG_VLAN_MASK, action);
+ }
i++;
}
@@ -3351,16 +4428,32 @@ aq_hw_init(struct aq_softc *sc)
{
uint32_t v;
- /* Force limit MRRS on RDM/TDM to 2K */
- v = AQ_READ_REG(sc, AQ_PCI_REG_CONTROL_6_REG);
- AQ_WRITE_REG(sc, AQ_PCI_REG_CONTROL_6_REG, (v & ~0x0707) | 0x0404);
+ if (HWTYPE_AQ1_P(sc)) {
+ /* Force limit MRRS on RDM/TDM to 2K */
+ v = AQ_READ_REG(sc, AQ_PCI_REG_CONTROL_6_REG);
+ AQ_WRITE_REG(sc, AQ_PCI_REG_CONTROL_6_REG,
+ (v & ~0x0707) | 0x0404);
- /*
- * TX DMA total request limit. B0 hardware is not capable to
- * handle more than (8K-MRRS) incoming DMA data.
- * Value 24 in 256byte units
- */
- AQ_WRITE_REG(sc, AQ_HW_TX_DMA_TOTAL_REQ_LIMIT_REG, 24);
+ /*
+ * TX DMA total request limit. B0 hardware is not capable to
+ * handle more than (8K-MRRS) incoming DMA data.
+ * Value 24 in 256byte units
+ */
+ AQ_WRITE_REG(sc, AQ_HW_TX_DMA_TOTAL_REQ_LIMIT_REG, 24);
+ }
+
+ if (HWTYPE_AQ2_P(sc)) {
+ uint32_t fpgaver, speed;
+ fpgaver = AQ_READ_REG(sc, AQ2_HW_FPGA_VERSION_REG);
+ if (fpgaver < 0x01000000)
+ speed = AQ2_LAUNCHTIME_CTRL_RATIO_SPEED_FULL;
+ else if (fpgaver >= 0x01008502)
+ speed = AQ2_LAUNCHTIME_CTRL_RATIO_SPEED_HALF;
+ else
+ speed = AQ2_LAUNCHTIME_CTRL_RATIO_SPEED_QUATER;
+ AQ_WRITE_REG_BIT(sc, AQ2_LAUNCHTIME_CTRL_REG,
+ AQ2_LAUNCHTIME_CTRL_RATIO, speed);
+ }
aq_hw_init_tx_path(sc);
aq_hw_init_rx_path(sc);
@@ -3372,6 +4465,11 @@ aq_hw_init(struct aq_softc *sc)
aq_hw_qos_set(sc);
+ if (HWTYPE_AQ2_P(sc)) {
+ AQ_WRITE_REG_BIT(sc, AQ2_RPF_NEW_CTRL_REG,
+ AQ2_RPF_NEW_CTRL_ENABLE, 1);
+ }
+
/* Enable interrupt */
int irqmode;
if (sc->sc_msix)
@@ -3387,7 +4485,7 @@ aq_hw_init(struct aq_softc *sc)
AQ_WRITE_REG(sc, AQ_INTR_AUTOMASK_REG, 0xffffffff);
AQ_WRITE_REG(sc, AQ_GEN_INTR_MAP_REG(0),
- ((AQ_B0_ERR_INT << 24) | (1U << 31)) |
+ ((AQ_B0_ERR_INT << 24) | (1 << 31)) |
((AQ_B0_ERR_INT << 16) | (1 << 23))
);
@@ -3421,6 +4519,9 @@ aq_update_link_status(struct aq_softc *s
if (changed) {
switch (rate) {
+ case AQ_LINK_10M:
+ speed = 10;
+ break;
case AQ_LINK_100M:
speed = 100;
break;
@@ -3442,7 +4543,7 @@ aq_update_link_status(struct aq_softc *s
break;
}
- if (sc->sc_link_rate == AQ_LINK_NONE) {
+ if (sc->sc_link_rate == AQ_LINK_NONE && rate != AQ_LINK_NONE) {
/* link DOWN -> UP */
device_printf(sc->sc_dev, "link is UP: speed=%u\n",
speed);
@@ -3475,10 +4576,11 @@ aq_update_statistics(struct aq_softc *sc
int prev = sc->sc_statistics_idx;
int cur = prev ^ 1;
- sc->sc_fw_ops->get_stats(sc, &sc->sc_statistics[cur]);
+ if (sc->sc_fw_ops->get_stats(sc, &sc->sc_statistics[cur]) != 0)
+ return;
/*
- * aq's internal statistics counter is 32bit.
+ * some aq's internal statistics counters are 32bit.
* cauculate delta, and add to evcount
*/
#define ADD_DELTA(cur, prev, name) \
@@ -4604,7 +5706,7 @@ aq_rx_intr(void *arg)
static int
aq_vlan_cb(struct ethercom *ec, uint16_t vid, bool set)
{
- struct ifnet *ifp = &ec->ec_if;
+ struct ifnet * const ifp = &ec->ec_if;
struct aq_softc * const sc = ifp->if_softc;
aq_set_vlan_filters(sc);
@@ -4695,7 +5797,8 @@ aq_init_locked(struct ifnet *ifp)
}
}
aq_init_rss(sc);
- aq_hw_l3_filter_set(sc);
+ if (HWTYPE_AQ1_P(sc))
+ aq1_hw_l3_filter_set(sc);
/* ring reset? */
aq_unset_stopping_flags(sc);