Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F162708167
D58142.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
D58142.diff
View Options
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
@@ -125,6 +125,15 @@
#define AQ2_RPF_REDIR2_INDEX (1 << 12)
#define AQ2_RPF_REDIR2_HASHTYPE 0x000001FF
#define AQ2_RPF_REDIR2_HASHTYPE_NONE 0
+#define AQ2_RPF_REDIR2_HASHTYPE_IP (1 << 0)
+#define AQ2_RPF_REDIR2_HASHTYPE_TCP4 (1 << 1)
+#define AQ2_RPF_REDIR2_HASHTYPE_UDP4 (1 << 2)
+#define AQ2_RPF_REDIR2_HASHTYPE_IP6 (1 << 3)
+#define AQ2_RPF_REDIR2_HASHTYPE_TCP6 (1 << 4)
+#define AQ2_RPF_REDIR2_HASHTYPE_UDP6 (1 << 5)
+#define AQ2_RPF_REDIR2_HASHTYPE_IP6EX (1 << 6)
+#define AQ2_RPF_REDIR2_HASHTYPE_TCP6EX (1 << 7)
+#define AQ2_RPF_REDIR2_HASHTYPE_UDP6EX (1 << 8)
#define AQ2_RPF_REDIR2_HASHTYPE_ALL 0x000001FF
#define AQ2_RX_Q_TC_MAP_REG(i) (0x5900 + (i) * 4)
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
@@ -383,7 +383,7 @@
int aq_hw_ver_match(const struct aq_hw_fw_version* ver_expected,
const struct aq_hw_fw_version* ver_actual);
-void aq_hw_set_promisc(struct aq_hw *hw, bool l2_promisc, bool vlan_promisc,
+int aq_hw_set_promisc(struct aq_hw *hw, bool l2_promisc, bool vlan_promisc,
bool mc_promisc);
int aq_hw_set_power(struct aq_hw *hw, unsigned int power_state);
diff --git a/sys/dev/aq/aq_hw.c b/sys/dev/aq/aq_hw.c
--- a/sys/dev/aq/aq_hw.c
+++ b/sys/dev/aq/aq_hw.c
@@ -37,6 +37,7 @@
#include <sys/endian.h>
#include <sys/socket.h>
#include <machine/cpu.h>
+#include <net/rss_config.h>
#include "aq_hw.h"
#include "aq2_hw.h"
@@ -405,9 +406,11 @@
uint32_t buff_size = 0U;
uint32_t n_tcs;
unsigned int i_priority = 0U;
+ unsigned int i;
int err = 0;
AQ_DBG_ENTER();
+
/* TPS Descriptor rate init */
tps_tx_pkt_shed_desc_rate_curr_time_res_set(hw, 0x0U);
tps_tx_pkt_shed_desc_rate_lim_set(hw, 0xA);
@@ -421,11 +424,22 @@
/* One TC per active 8-ring group; share the buffer across them. */
n_tcs = aq_hw_active_tcs(hw);
- buff_size = AQ_HW_TXBUF_MAX / n_tcs;
+ buff_size = (IS_CHIP_FEATURE(hw, ATLANTIC2) ?
+ AQ2_HW_TXBUF_MAX : AQ_HW_TXBUF_MAX) / n_tcs;
for (tc = 0; tc < n_tcs; tc++) {
- tps_tx_pkt_shed_tc_data_max_credit_set(hw, 0xFFF, tc);
- tps_tx_pkt_shed_tc_data_weight_set(hw, 0x64, tc);
+ if (IS_CHIP_FEATURE(hw, ATLANTIC2)) {
+ /* Atlantic 2's data-TC credit/weight fields are wider. */
+ AQ_WRITE_REG_BIT(hw, TPS_DATA_TCT_REG(tc),
+ TPS2_DATA_TCT_CREDIT_MAX,
+ TPS2_DATA_TCT_CREDIT_MAX_SHIFT, 0xfff0);
+ AQ_WRITE_REG_BIT(hw, TPS_DATA_TCT_REG(tc),
+ TPS2_DATA_TCT_WEIGHT,
+ TPS2_DATA_TCT_WEIGHT_SHIFT, 0x640);
+ } else {
+ tps_tx_pkt_shed_tc_data_max_credit_set(hw, 0xFFF, tc);
+ tps_tx_pkt_shed_tc_data_weight_set(hw, 0x64, tc);
+ }
tps_tx_pkt_shed_desc_tc_max_credit_set(hw, 0x50, tc);
tps_tx_pkt_shed_desc_tc_weight_set(hw, 0x1E, tc);
@@ -438,7 +452,8 @@
/* QoS Rx buf size per TC */
tc = 0;
- buff_size = AQ_HW_RXBUF_MAX;
+ buff_size = IS_CHIP_FEATURE(hw, ATLANTIC2) ?
+ AQ2_HW_RXBUF_MAX : AQ_HW_RXBUF_MAX;
rpb_rx_pkt_buff_size_per_tc_set(hw, buff_size, tc);
rpb_rx_buff_hi_threshold_per_tc_set(hw,
@@ -450,6 +465,20 @@
for (i_priority = 8U; i_priority--;)
rpf_rpb_user_priority_tc_map_set(hw, i_priority, 0U);
+ /* Atlantic 2 ring -> TC map (TC = ring / HW_ATL_B0_RINGS_PER_TC). */
+ if (IS_CHIP_FEATURE(hw, ATLANTIC2)) {
+ AQ_WRITE_REG_BIT(hw, TPB_TX_BUF_REG,
+ TPB_TX_BUF_TC_Q_RAND_MAP_EN,
+ TPB_TX_BUF_TC_Q_RAND_MAP_EN_SHIFT, 1);
+ /* TX packs a byte per ring (4/reg); RX a nibble (8/reg). */
+ for (i = 0; i < HW_ATL_B0_RINGS_MAX / 4; i++)
+ AQ_WRITE_REG(hw, AQ2_TX_Q_TC_MAP_REG(i),
+ (i / 2) * 0x01010101U);
+ for (i = 0; i < HW_ATL_B0_RINGS_MAX / 8; i++)
+ AQ_WRITE_REG(hw, AQ2_RX_Q_TC_MAP_REG(i),
+ i * 0x11111111U);
+ }
+
err = aq_hw_err_from_flags(hw);
AQ_DBG_EXIT(err);
return (err);
@@ -541,7 +570,8 @@
tdm_tx_desc_wr_wb_irq_en_set(hw, 1U);
/* misc */
- AQ_WRITE_REG(hw, 0x00007040U, 0x00010000U);//IS_CHIP_FEATURE(TPO2) ? 0x00010000U : 0x00000000U);
+ AQ_WRITE_REG(hw, 0x00007040U,
+ IS_CHIP_FEATURE(hw, TPO2) ? 0x00010000U : 0x00000000U);
tdm_tx_dca_en_set(hw, 0U);
tdm_tx_dca_mode_set(hw, 0U);
@@ -552,17 +582,68 @@
return (err);
}
+/* Atlantic 2: install one action-resolver-table row under the ART semaphore. */
+static int
+aq2_art_filter_set(struct aq_hw *hw, uint32_t idx, uint32_t tag,
+ uint32_t mask, uint32_t action)
+{
+ if (AQ_HW_WAIT_FOR(reg_glb_cpu_sem_get(hw, AQ2_ART_SEM_INDEX) == 1U,
+ 10U, 1000U) != 0) {
+ device_printf(hw->dev, "ART semaphore timeout, idx %u\n", idx);
+ return (EBUSY);
+ }
+
+ idx += hw->art_filter_base_index;
+ AQ_WRITE_REG(hw, AQ2_RPF_ACT_ART_REQ_TAG_REG(idx), tag);
+ AQ_WRITE_REG(hw, AQ2_RPF_ACT_ART_REQ_MASK_REG(idx), mask);
+ AQ_WRITE_REG(hw, AQ2_RPF_ACT_ART_REQ_ACTION_REG(idx), action);
+
+ reg_glb_cpu_sem_set(hw, 1U, AQ2_ART_SEM_INDEX);
+ return (0);
+}
+
static int
aq_hw_init_rx_path(struct aq_hw *hw)
{
unsigned int control_reg_val = 0U;
int i;
- int err;
+ int err = 0;
AQ_DBG_ENTER();
/* Rx TC/RSS number config */
rpb_rpf_rx_traf_class_mode_set(hw, 1U);
+ /*
+ * Atlantic 2: program the RSS hash types the kernel honors. UDP is
+ * excluded by default (see aq_rss_hashconfig()); clearing its per-cast
+ * bits keeps fragmented UDP on a single queue without the A1 L3L4
+ * flow-filter workaround.
+ */
+ if (IS_CHIP_FEATURE(hw, ATLANTIC2)) {
+ static const struct {
+ u_int kern;
+ uint32_t hw;
+ } ht_map[] = {
+ { RSS_HASHTYPE_RSS_IPV4, AQ2_RPF_REDIR2_HASHTYPE_IP },
+ { RSS_HASHTYPE_RSS_TCP_IPV4, AQ2_RPF_REDIR2_HASHTYPE_TCP4 },
+ { RSS_HASHTYPE_RSS_UDP_IPV4, AQ2_RPF_REDIR2_HASHTYPE_UDP4 },
+ { RSS_HASHTYPE_RSS_IPV6, AQ2_RPF_REDIR2_HASHTYPE_IP6 },
+ { RSS_HASHTYPE_RSS_TCP_IPV6, AQ2_RPF_REDIR2_HASHTYPE_TCP6 },
+ { RSS_HASHTYPE_RSS_UDP_IPV6, AQ2_RPF_REDIR2_HASHTYPE_UDP6 },
+ { RSS_HASHTYPE_RSS_IPV6_EX, AQ2_RPF_REDIR2_HASHTYPE_IP6EX },
+ { RSS_HASHTYPE_RSS_TCP_IPV6_EX, AQ2_RPF_REDIR2_HASHTYPE_TCP6EX },
+ { RSS_HASHTYPE_RSS_UDP_IPV6_EX, AQ2_RPF_REDIR2_HASHTYPE_UDP6EX },
+ };
+ u_int hc = aq_rss_hashconfig();
+ uint32_t ht = 0;
+
+ for (i = 0; i < (int)nitems(ht_map); i++)
+ if (hc & ht_map[i].kern)
+ ht |= ht_map[i].hw;
+ AQ_WRITE_REG_BIT(hw, AQ2_RPF_REDIR2_REG,
+ AQ2_RPF_REDIR2_HASHTYPE, 0, ht);
+ }
+
/* Rx flow control */
rpb_rx_flow_ctl_mode_set(hw, 1U);
@@ -589,13 +670,38 @@
/* Rx Interrupts */
rdm_rx_desc_wr_wb_irq_en_set(hw, 1U);
- /* misc */
- control_reg_val = 0x000F0000U; //RPF2
+ if (IS_CHIP_FEATURE(hw, ATLANTIC2)) {
+ /* Enable the resolver table and tag L2 unicast/broadcast. */
+ AQ_WRITE_REG_BIT(hw, AQ2_RPF_REC_TAB_ENABLE_REG,
+ AQ2_RPF_REC_TAB_ENABLE_MASK, 0, AQ2_RPF_REC_TAB_ENABLE_MASK);
+ AQ_WRITE_REG_BIT(hw, RPF_L2UC_MSW_REG(0),
+ RPF_L2UC_MSW_TAG, RPF_L2UC_MSW_TAG_SHIFT, 1);
+ AQ_WRITE_REG_BIT(hw, AQ2_RPF_L2BC_TAG_REG,
+ AQ2_RPF_L2BC_TAG_MASK, 0, 1);
+
+ /* Drop rows (promisc lifts them); all PCP -> TC 0. */
+ err = aq2_art_filter_set(hw, AQ2_RPF_INDEX_L2_PROMISC_OFF, 0,
+ AQ2_RPF_TAG_UC_MASK | AQ2_RPF_TAG_ALLMC_MASK,
+ AQ2_ART_ACTION_DROP);
+ if (err == 0)
+ err = aq2_art_filter_set(hw,
+ AQ2_RPF_INDEX_VLAN_PROMISC_OFF, 0,
+ AQ2_RPF_TAG_VLAN_MASK | AQ2_RPF_TAG_UNTAG_MASK,
+ AQ2_ART_ACTION_DROP);
+ for (i = 0; err == 0 && i < 8; i++)
+ err = aq2_art_filter_set(hw, AQ2_RPF_INDEX_PCP_TO_TC + i,
+ ((uint32_t)i << AQ2_RPF_TAG_PCP_SHIFT),
+ AQ2_RPF_TAG_PCP_MASK,
+ AQ2_ART_ACTION_ASSIGN_TC(0));
+ } else {
+ /* misc */
+ control_reg_val = 0x000F0000U; //RPF2
- /* RSS hash type set for IP/TCP */
- control_reg_val |= 0x1EU;
+ /* RSS hash type set for IP/TCP */
+ control_reg_val |= 0x1EU;
- AQ_WRITE_REG(hw, 0x00005040U, control_reg_val);
+ AQ_WRITE_REG(hw, 0x00005040U, control_reg_val);
+ }
rpfl2broadcast_en_set(hw, 1U);
rpfl2broadcast_flr_act_set(hw, 1U);
@@ -604,7 +710,8 @@
rdm_rx_dca_en_set(hw, 0U);
rdm_rx_dca_mode_set(hw, 0U);
- err = aq_hw_err_from_flags(hw);
+ if (err == 0)
+ err = aq_hw_err_from_flags(hw);
AQ_DBG_EXIT(err);
return (err);
}
@@ -628,6 +735,10 @@
rpfl2_uc_flr_en_set(hw, 0U, index);
rpfl2unicast_dest_addresslsw_set(hw, l, index);
rpfl2unicast_dest_addressmsw_set(hw, h, index);
+ /* Atlantic 2: classify this address into the resolver table. */
+ if (IS_CHIP_FEATURE(hw, ATLANTIC2))
+ AQ_WRITE_REG_BIT(hw, RPF_L2UC_MSW_REG(index),
+ RPF_L2UC_MSW_TAG, RPF_L2UC_MSW_TAG_SHIFT, 1);
rpfl2_uc_flr_en_set(hw, 1U, index);
err = aq_hw_err_from_flags(hw);
@@ -686,6 +797,11 @@
aq_hw_qos_set(hw);
+ /* Atlantic 2: turn on the new RPF / action-resolver engine. */
+ if (IS_CHIP_FEATURE(hw, ATLANTIC2))
+ AQ_WRITE_REG_BIT(hw, AQ2_RPF_NEW_CTRL_REG,
+ AQ2_RPF_NEW_CTRL_ENABLE, 11, 1);
+
err = aq_hw_err_from_flags(hw);
if (err != 0)
goto err_exit;
@@ -784,8 +900,13 @@
rdm_rdm_intr_moder_en_set(hw, active);
for (int i = HW_ATL_B0_RINGS_MAX; i--;) {
- reg_tx_intr_moder_ctrl_set(hw, itr_tx, i);
- reg_rx_intr_moder_ctrl_set(hw, itr_rx, i);
+ /* A2 Tx moderation register moved; same layout. Rx is shared. */
+ if (IS_CHIP_FEATURE(hw, ATLANTIC2))
+ AQ_WRITE_REG(hw, AQ2_TX_INTR_MODERATION_CTL_REG(i),
+ itr_tx);
+ else
+ reg_tx_intr_moder_ctrl_set(hw, itr_tx, i);
+ reg_rx_intr_moder_ctrl_set(hw, itr_rx, i);
}
err = aq_hw_err_from_flags(hw);
@@ -816,6 +937,12 @@
aq_vlans[i].vlan_id,
i);
hw_atl_rpf_vlan_flr_act_set(hw, 1U, i);
+ /* A2: tag the filter so the VLAN drop row passes it. */
+ if (IS_CHIP_FEATURE(hw, ATLANTIC2))
+ AQ_WRITE_REG_BIT(hw,
+ AQ2_RPF_VLAN_FLR_TAG_REG(i),
+ AQ2_RPF_VLAN_FLR_TAG,
+ AQ2_RPF_VLAN_FLR_TAG_SHIFT, 1U);
hw_atl_rpf_vlan_flr_en_set(hw, 1U, i);
if (aq_vlans[i].queue != 0xFF) {
hw_atl_rpf_vlan_rxq_flr_set(hw,
@@ -832,26 +959,45 @@
int
hw_atl_b0_hw_vlan_promisc_set(struct aq_hw *hw, bool promisc)
{
+ int err;
+
+ /* A2: fallible ART write first; a timeout leaves the legacy bit as-is. */
+ if (IS_CHIP_FEATURE(hw, ATLANTIC2)) {
+ err = aq2_art_filter_set(hw, AQ2_RPF_INDEX_VLAN_PROMISC_OFF,
+ 0, AQ2_RPF_TAG_VLAN_MASK | AQ2_RPF_TAG_UNTAG_MASK,
+ promisc ? AQ2_ART_ACTION_DISABLE : AQ2_ART_ACTION_DROP);
+ if (err != 0)
+ return (err);
+ }
hw_atl_rpf_vlan_prom_mode_en_set(hw, promisc);
return aq_hw_err_from_flags(hw);
}
-void
+int
aq_hw_set_promisc(struct aq_hw *hw, bool l2_promisc, bool vlan_promisc,
bool mc_promisc)
{
+ int err = 0;
+
AQ_DBG_ENTERA("promisc %d, vlan_promisc %d, allmulti %d", l2_promisc,
vlan_promisc, mc_promisc);
rpfl2promiscuous_mode_en_set(hw, l2_promisc);
- hw_atl_b0_hw_vlan_promisc_set(hw, l2_promisc | vlan_promisc);
+ err = hw_atl_b0_hw_vlan_promisc_set(hw, l2_promisc | vlan_promisc);
+
+ /* A2: promisc toggles the unicast drop row. */
+ if (err == 0 && IS_CHIP_FEATURE(hw, ATLANTIC2))
+ err = aq2_art_filter_set(hw, AQ2_RPF_INDEX_L2_PROMISC_OFF, 0,
+ AQ2_RPF_TAG_UC_MASK | AQ2_RPF_TAG_ALLMC_MASK,
+ l2_promisc ? AQ2_ART_ACTION_DISABLE : AQ2_ART_ACTION_DROP);
rpfl2_accept_all_mc_packets_set(hw, mc_promisc);
rpfl2multicast_flr_en_set(hw, mc_promisc, 0);
- AQ_DBG_EXIT(0);
+ AQ_DBG_EXIT(err);
+ return (err);
}
int
@@ -919,6 +1065,26 @@
memset(bitary, 0, sizeof(bitary));
+ /* A2 per-TC redirection table; flat RX rings, same queue per TC. */
+ if (IS_CHIP_FEATURE(hw, ATLANTIC2)) {
+ uint32_t n_tcs = aq_hw_active_tcs(hw);
+ int tc, slot, q;
+ uint32_t word;
+
+ AQ_WRITE_REG_BIT(hw, AQ2_RPF_REDIR2_REG, AQ2_RPF_REDIR2_INDEX,
+ 12, 0);
+ for (slot = 0; slot < AQ2_RPF_RSS_REDIR_MAX; slot++) {
+ q = rss_table[slot] &
+ (HW_ATL_RSS_INDIRECTION_QUEUES_MAX - 1U);
+ word = 0U;
+ for (tc = 0; (uint32_t)tc < n_tcs; tc++)
+ word |= (uint32_t)q << (5 * tc);
+ AQ_WRITE_REG(hw, AQ2_RPF_RSS_REDIR_REG(0, slot), word);
+ }
+ /* A2 uses this table only; skip the legacy indirection writes. */
+ return (aq_hw_err_from_flags(hw));
+ }
+
for (i = HW_ATL_RSS_INDIRECTION_TABLE_MAX; i--;) {
uint32_t bit_pos = i * HW_ATL_RSS_INDIRECTION_ENTRY_BITS;
uint32_t word = bit_pos / 16U;
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
@@ -773,9 +773,11 @@
aq_if_enable_intr(ctx);
aq_hw_rss_hash_set(&softc->hw, softc->rss_key);
aq_hw_rss_set(&softc->hw, softc->rss_table);
- aq_hw_udp_rss_enable(hw, (aq_rss_hashconfig() &
- (RSS_HASHTYPE_RSS_UDP_IPV4 | RSS_HASHTYPE_RSS_UDP_IPV6 |
- RSS_HASHTYPE_RSS_UDP_IPV6_EX)) != 0);
+ /* A2 selects UDP hashing per-protocol in REDIR2; A1 uses the filter. */
+ if (!IS_CHIP_FEATURE(hw, ATLANTIC2))
+ aq_hw_udp_rss_enable(hw, (aq_rss_hashconfig() &
+ (RSS_HASHTYPE_RSS_UDP_IPV4 | RSS_HASHTYPE_RSS_UDP_IPV6 |
+ RSS_HASHTYPE_RSS_UDP_IPV6_EX)) != 0);
aq_hw_set_link_speed(hw, hw->link_rate);
/* iflib does not replay filter state after init; aq_hw_init() clears it. */
@@ -875,9 +877,12 @@
if_foreach_llmaddr(ifp, &aq_mc_filter_apply, softc);
}
- aq_hw_set_promisc(hw, !!(if_getflags(ifp) & IFF_PROMISC),
+ if (aq_hw_set_promisc(hw, !!(if_getflags(ifp) & IFF_PROMISC),
aq_is_vlan_promisc_required(softc),
- !!(if_getflags(ifp) & IFF_ALLMULTI) || aq_is_mc_promisc_required(softc));
+ !!(if_getflags(ifp) & IFF_ALLMULTI) ||
+ aq_is_mc_promisc_required(softc)) != 0)
+ device_printf(softc->dev,
+ "multicast filter update failed\n");
AQ_DBG_EXIT(0);
}
@@ -943,17 +948,18 @@
aq_if_promisc_set(if_ctx_t ctx, int flags)
{
struct aq_dev *softc;
+ int err;
AQ_DBG_ENTER();
softc = iflib_get_softc(ctx);
- aq_hw_set_promisc(&softc->hw, !!(flags & IFF_PROMISC),
+ err = aq_hw_set_promisc(&softc->hw, !!(flags & IFF_PROMISC),
aq_is_vlan_promisc_required(softc),
!!(flags & IFF_ALLMULTI) || aq_is_mc_promisc_required(softc));
- AQ_DBG_EXIT(0);
- return (0);
+ AQ_DBG_EXIT(err);
+ return (err);
}
static void
@@ -1127,9 +1133,10 @@
}
hw_atl_b0_hw_vlan_set(hw, aq_vlans);
- hw_atl_b0_hw_vlan_promisc_set(hw,
+ if (hw_atl_b0_hw_vlan_promisc_set(hw,
aq_is_vlan_promisc_required(softc) ||
- (if_getflags(iflib_get_ifp(softc->ctx)) & IFF_PROMISC) != 0);
+ (if_getflags(iflib_get_ifp(softc->ctx)) & IFF_PROMISC) != 0) != 0)
+ device_printf(softc->dev, "VLAN filter update failed\n");
}
/* VLAN support */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jul 17, 12:40 AM (5 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35152655
Default Alt Text
D58142.diff (14 KB)
Attached To
Mode
D58142: aq(4): program the Atlantic 2 multiqueue datapath
Attached
Detach File
Event Timeline
Log In to Comment