mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
Merge branch 'net-atlantic-add-ptp-support-for-aqc113-antigua'
Sukhdeep Singh says:
====================
net: atlantic: add PTP support for AQC113 (Antigua)
This series adds IEEE 1588 PTP support for the AQC113 (Antigua) network
controller. AQC113 is the successor to the existing AQC107 (Atlantic)
chip already supported by the atlantic driver.
AQC113 uses a substantially different hardware architecture for PTP
compared to AQC107:
- Dual on-chip TSG clocks with direct register access instead of
PHY-based timestamping via firmware
- TX timestamps via descriptor writeback instead of firmware mailbox
- Hardware L3/L4 RX filters for PTP multicast steering with both
IPv4 and IPv6 support
- Reference-counted shared filter slots managed through an Action
Resolver Table (ART), allowing multiple rules to share L3/L4
hardware filters when their match criteria are identical
The series is structured in four parts:
Patches 1-3 prepare the existing L3/L4 filter path:
Patch 1 corrects flow_type masking and IPv6 address handling in
aq_set_data_fl3l4(). Patch 2 moves the active_ipv4/ipv6 bitmap
updates to after the hardware write succeeds. Patch 3 decouples
the function from driver-internal structures so it can be called
directly by the AQC113 PTP filter setup code.
Patches 4-5 add the AQC113 hardware infrastructure:
Patch 4 adds the low-level register definitions and accessor
functions. Patch 5 adds filter data structures and firmware
capability query.
Patches 6-7 implement the AQC113 L2/L3/L4 RX filter management:
Patch 6 fixes the AQC113 HW init path: ART section selection,
L2 filter slot assignment, and MAC address programming. Patch 7
implements the complete L3/L4 RX filter ops including reference-
counted ART sharing and IPv4/IPv6 steering.
Patches 8-12 add the AQC113 PTP feature:
Patch 8 reserves the dedicated PTP traffic class buffer and
configures the TX path. Patch 9 extends the hw_ops interface
with PTP-specific function pointers and updates AQC107 to the
new signatures. Patches 10-12 implement the full PTP subsystem:
Patch 10 adds the hw_atl2 register-level PTP clock ops, Patch 11
adds TX timestamp polling and PTP TX traffic classification, and
Patch 12 integrates PTP into aq_ptp and the driver core.
The existing AQC107 PTP implementation is not functionally changed
by this series; AQC113-specific code paths are gated on chip
detection throughout.
Tested on AQC113 at 1G, 2.5G, 5G, and 10G link speeds using
ptp4l/phc2sys with hardware timestamping in both L2 and L4
(IPv4/IPv6) modes.
====================
Link: https://patch.msgid.link/20260610115448.272-1-sukhdeeps@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
a61bb36996
|
|
@ -181,6 +181,20 @@ aq_check_approve_fvlan(struct aq_nic_s *aq_nic,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool aq_is_ipv6_flow_type(const struct ethtool_rx_flow_spec *fsp)
|
||||
{
|
||||
switch (fsp->flow_type & ~FLOW_EXT) {
|
||||
case TCP_V6_FLOW:
|
||||
case UDP_V6_FLOW:
|
||||
case SCTP_V6_FLOW:
|
||||
case IPV6_FLOW:
|
||||
case IPV6_USER_FLOW:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int __must_check
|
||||
aq_check_filter(struct aq_nic_s *aq_nic,
|
||||
struct ethtool_rx_flow_spec *fsp)
|
||||
|
|
@ -466,31 +480,23 @@ static int aq_add_del_fvlan(struct aq_nic_s *aq_nic,
|
|||
return aq_filters_vlans_update(aq_nic);
|
||||
}
|
||||
|
||||
static int aq_set_data_fl3l4(struct aq_nic_s *aq_nic,
|
||||
struct aq_rx_filter *aq_rx_fltr,
|
||||
struct aq_rx_filter_l3l4 *data, bool add)
|
||||
int aq_set_data_fl3l4(const struct ethtool_rx_flow_spec *fsp,
|
||||
struct aq_rx_filter_l3l4 *data,
|
||||
int location, bool add)
|
||||
{
|
||||
struct aq_hw_rx_fltrs_s *rx_fltrs = aq_get_hw_rx_fltrs(aq_nic);
|
||||
const struct ethtool_rx_flow_spec *fsp = &aq_rx_fltr->aq_fsp;
|
||||
u32 flow = fsp->flow_type & ~FLOW_EXT;
|
||||
|
||||
memset(data, 0, sizeof(*data));
|
||||
|
||||
data->is_ipv6 = rx_fltrs->fl3l4.is_ipv6;
|
||||
data->location = HW_ATL_GET_REG_LOCATION_FL3L4(fsp->location);
|
||||
|
||||
if (!add) {
|
||||
if (!data->is_ipv6)
|
||||
rx_fltrs->fl3l4.active_ipv4 &= ~BIT(data->location);
|
||||
else
|
||||
rx_fltrs->fl3l4.active_ipv6 &=
|
||||
~BIT((data->location) / 4);
|
||||
data->is_ipv6 = aq_is_ipv6_flow_type(fsp);
|
||||
data->location = location;
|
||||
|
||||
if (!add)
|
||||
return 0;
|
||||
}
|
||||
|
||||
data->cmd |= HW_ATL_RX_ENABLE_FLTR_L3L4;
|
||||
|
||||
switch (fsp->flow_type) {
|
||||
switch (flow) {
|
||||
case TCP_V4_FLOW:
|
||||
case TCP_V6_FLOW:
|
||||
data->cmd |= HW_ATL_RX_ENABLE_CMP_PROT_L4;
|
||||
|
|
@ -514,11 +520,9 @@ static int aq_set_data_fl3l4(struct aq_nic_s *aq_nic,
|
|||
ntohl(fsp->h_u.tcp_ip4_spec.ip4src);
|
||||
data->ip_dst[0] =
|
||||
ntohl(fsp->h_u.tcp_ip4_spec.ip4dst);
|
||||
rx_fltrs->fl3l4.active_ipv4 |= BIT(data->location);
|
||||
} else {
|
||||
int i;
|
||||
|
||||
rx_fltrs->fl3l4.active_ipv6 |= BIT((data->location) / 4);
|
||||
for (i = 0; i < HW_ATL_RX_CNT_REG_ADDR_IPV6; ++i) {
|
||||
data->ip_dst[i] =
|
||||
ntohl(fsp->h_u.tcp_ip6_spec.ip6dst[i]);
|
||||
|
|
@ -527,23 +531,23 @@ static int aq_set_data_fl3l4(struct aq_nic_s *aq_nic,
|
|||
}
|
||||
data->cmd |= HW_ATL_RX_ENABLE_L3_IPV6;
|
||||
}
|
||||
if (fsp->flow_type != IP_USER_FLOW &&
|
||||
fsp->flow_type != IPV6_USER_FLOW) {
|
||||
if (!data->is_ipv6) {
|
||||
data->p_dst =
|
||||
ntohs(fsp->h_u.tcp_ip4_spec.pdst);
|
||||
data->p_src =
|
||||
ntohs(fsp->h_u.tcp_ip4_spec.psrc);
|
||||
} else {
|
||||
data->p_dst =
|
||||
ntohs(fsp->h_u.tcp_ip6_spec.pdst);
|
||||
data->p_src =
|
||||
ntohs(fsp->h_u.tcp_ip6_spec.psrc);
|
||||
}
|
||||
if (flow == TCP_V4_FLOW || flow == UDP_V4_FLOW ||
|
||||
flow == SCTP_V4_FLOW) {
|
||||
data->p_dst = ntohs(fsp->h_u.tcp_ip4_spec.pdst);
|
||||
data->p_src = ntohs(fsp->h_u.tcp_ip4_spec.psrc);
|
||||
}
|
||||
if (data->ip_src[0] && !data->is_ipv6)
|
||||
if (flow == TCP_V6_FLOW || flow == UDP_V6_FLOW ||
|
||||
flow == SCTP_V6_FLOW) {
|
||||
data->p_dst = ntohs(fsp->h_u.tcp_ip6_spec.pdst);
|
||||
data->p_src = ntohs(fsp->h_u.tcp_ip6_spec.psrc);
|
||||
}
|
||||
if (data->ip_src[0] ||
|
||||
(data->is_ipv6 && (data->ip_src[1] || data->ip_src[2] ||
|
||||
data->ip_src[3])))
|
||||
data->cmd |= HW_ATL_RX_ENABLE_CMP_SRC_ADDR_L3;
|
||||
if (data->ip_dst[0] && !data->is_ipv6)
|
||||
if (data->ip_dst[0] ||
|
||||
(data->is_ipv6 && (data->ip_dst[1] || data->ip_dst[2] ||
|
||||
data->ip_dst[3])))
|
||||
data->cmd |= HW_ATL_RX_ENABLE_CMP_DEST_ADDR_L3;
|
||||
if (data->p_dst)
|
||||
data->cmd |= HW_ATL_RX_ENABLE_CMP_DEST_PORT_L4;
|
||||
|
|
@ -573,16 +577,38 @@ static int aq_set_fl3l4(struct aq_hw_s *aq_hw,
|
|||
static int aq_add_del_fl3l4(struct aq_nic_s *aq_nic,
|
||||
struct aq_rx_filter *aq_rx_fltr, bool add)
|
||||
{
|
||||
struct aq_hw_rx_fltrs_s *rx_fltrs = aq_get_hw_rx_fltrs(aq_nic);
|
||||
const struct aq_hw_ops *aq_hw_ops = aq_nic->aq_hw_ops;
|
||||
struct aq_hw_s *aq_hw = aq_nic->aq_hw;
|
||||
struct aq_rx_filter_l3l4 data;
|
||||
int location;
|
||||
int err;
|
||||
|
||||
if (unlikely(aq_rx_fltr->aq_fsp.location < AQ_RX_FIRST_LOC_FL3L4 ||
|
||||
aq_rx_fltr->aq_fsp.location > AQ_RX_LAST_LOC_FL3L4 ||
|
||||
aq_set_data_fl3l4(aq_nic, aq_rx_fltr, &data, add)))
|
||||
aq_rx_fltr->aq_fsp.location > AQ_RX_LAST_LOC_FL3L4))
|
||||
return -EINVAL;
|
||||
|
||||
return aq_set_fl3l4(aq_hw, aq_hw_ops, &data);
|
||||
location = HW_ATL_GET_REG_LOCATION_FL3L4(aq_rx_fltr->aq_fsp.location);
|
||||
|
||||
aq_set_data_fl3l4(&aq_rx_fltr->aq_fsp, &data, location, add);
|
||||
|
||||
err = aq_set_fl3l4(aq_hw, aq_hw_ops, &data);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (add) {
|
||||
if (!data.is_ipv6)
|
||||
rx_fltrs->fl3l4.active_ipv4 |= BIT(data.location);
|
||||
else
|
||||
rx_fltrs->fl3l4.active_ipv6 |= BIT(data.location / 4);
|
||||
} else {
|
||||
if (!data.is_ipv6)
|
||||
rx_fltrs->fl3l4.active_ipv4 &= ~BIT(data.location);
|
||||
else
|
||||
rx_fltrs->fl3l4.active_ipv6 &= ~BIT(data.location / 4);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aq_add_del_rule(struct aq_nic_s *aq_nic,
|
||||
|
|
|
|||
|
|
@ -32,5 +32,8 @@ int aq_clear_rxnfc_all_rules(struct aq_nic_s *aq_nic);
|
|||
int aq_reapply_rxnfc_all_rules(struct aq_nic_s *aq_nic);
|
||||
int aq_filters_vlans_update(struct aq_nic_s *aq_nic);
|
||||
int aq_filters_vlan_offload_off(struct aq_nic_s *aq_nic);
|
||||
int aq_set_data_fl3l4(const struct ethtool_rx_flow_spec *fsp,
|
||||
struct aq_rx_filter_l3l4 *data,
|
||||
int location, bool add);
|
||||
|
||||
#endif /* AQ_FILTERS_H */
|
||||
|
|
|
|||
|
|
@ -15,10 +15,14 @@
|
|||
#include "aq_common.h"
|
||||
#include "aq_rss.h"
|
||||
#include "hw_atl/hw_atl_utils.h"
|
||||
#include "hw_atl2/hw_atl2.h"
|
||||
|
||||
#define AQ_HW_MAC_COUNTER_HZ 312500000ll
|
||||
#define AQ_HW_PHY_COUNTER_HZ 160000000ll
|
||||
|
||||
#define AQ_HW_TXD_CTL_TS_EN 0x40000000U
|
||||
#define AQ_HW_TXD_CTL_TS_TSG0 0x80000000U
|
||||
|
||||
enum aq_tc_mode {
|
||||
AQ_TC_MODE_INVALID = -1,
|
||||
AQ_TC_MODE_8TCS,
|
||||
|
|
@ -38,6 +42,8 @@ enum aq_tc_mode {
|
|||
|
||||
#define AQ_FRAC_PER_NS 0x100000000LL
|
||||
|
||||
#define AQ2_HW_PTP_COUNTER_HZ 156250000ll
|
||||
|
||||
/* Used for rate to Mbps conversion */
|
||||
#define AQ_MBPS_DIVISOR 125000 /* 1000000 / 8 */
|
||||
|
||||
|
|
@ -109,6 +115,7 @@ struct aq_stats_s {
|
|||
#define AQ_HW_IRQ_MSIX 3U
|
||||
|
||||
#define AQ_HW_SERVICE_IRQS 1U
|
||||
#define AQ_HW_PTP_IRQS 1U
|
||||
|
||||
#define AQ_HW_POWER_STATE_D0 0U
|
||||
#define AQ_HW_POWER_STATE_D3 3U
|
||||
|
|
@ -157,6 +164,15 @@ enum aq_priv_flags {
|
|||
AQ_HW_LOOPBACK_PHYEXT_SYS,
|
||||
};
|
||||
|
||||
enum {
|
||||
AQ_HW_PTP_DISABLE = 0,
|
||||
AQ_HW_PTP_L2_ENABLE = BIT(1),
|
||||
AQ_HW_PTP_L4_ENABLE = BIT(2),
|
||||
};
|
||||
|
||||
#define ATL_TSG_CLOCK_SEL_0 0
|
||||
#define ATL_TSG_CLOCK_SEL_1 1
|
||||
|
||||
#define AQ_HW_LOOPBACK_MASK (BIT(AQ_HW_LOOPBACK_DMA_SYS) |\
|
||||
BIT(AQ_HW_LOOPBACK_PKT_SYS) |\
|
||||
BIT(AQ_HW_LOOPBACK_DMA_NET) |\
|
||||
|
|
@ -198,6 +214,7 @@ struct aq_hw_s {
|
|||
u32 rpc_tid;
|
||||
struct hw_atl_utils_fw_rpc rpc;
|
||||
s64 ptp_clk_offset;
|
||||
s8 clk_select;
|
||||
u16 phy_id;
|
||||
void *priv;
|
||||
};
|
||||
|
|
@ -323,11 +340,15 @@ struct aq_hw_ops {
|
|||
|
||||
int (*hw_ts_to_sys_clock)(struct aq_hw_s *self, u64 ts, u64 *time);
|
||||
|
||||
int (*hw_gpio_pulse)(struct aq_hw_s *self, u32 index, u64 start,
|
||||
u32 period);
|
||||
int (*hw_gpio_pulse)(struct aq_hw_s *self, u32 index,
|
||||
u32 clk_sel, u64 start,
|
||||
u32 period, u32 hightime);
|
||||
|
||||
int (*hw_extts_gpio_enable)(struct aq_hw_s *self, u32 index,
|
||||
u32 enable);
|
||||
u32 channel, int enable);
|
||||
|
||||
void (*enable_ptp)(struct aq_hw_s *self, unsigned int param,
|
||||
int enable);
|
||||
|
||||
int (*hw_get_sync_ts)(struct aq_hw_s *self, u64 *ts);
|
||||
|
||||
|
|
@ -337,6 +358,14 @@ struct aq_hw_ops {
|
|||
int (*extract_hwts)(struct aq_hw_s *self, u8 *p, unsigned int len,
|
||||
u64 *timestamp);
|
||||
|
||||
u64 (*hw_ring_tx_ptp_get_ts)(struct aq_ring_s *ring);
|
||||
|
||||
int (*hw_tx_ptp_ring_init)(struct aq_hw_s *self,
|
||||
struct aq_ring_s *aq_ring);
|
||||
int (*hw_rx_ptp_ring_init)(struct aq_hw_s *self,
|
||||
struct aq_ring_s *aq_ring);
|
||||
u32 (*hw_get_clk_sel)(struct aq_hw_s *self);
|
||||
|
||||
int (*hw_set_fc)(struct aq_hw_s *self, u32 fc, u32 tc);
|
||||
|
||||
int (*hw_set_loopback)(struct aq_hw_s *self, u32 mode, bool enable);
|
||||
|
|
|
|||
|
|
@ -19,8 +19,10 @@
|
|||
#include <linux/netdevice.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/udp.h>
|
||||
#include <net/pkt_cls.h>
|
||||
#include <linux/ptp_classify.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <linux/filter.h>
|
||||
|
||||
|
|
@ -68,14 +70,6 @@ int aq_ndev_open(struct net_device *ndev)
|
|||
if (err < 0)
|
||||
goto err_exit;
|
||||
|
||||
err = aq_reapply_rxnfc_all_rules(aq_nic);
|
||||
if (err < 0)
|
||||
goto err_exit;
|
||||
|
||||
err = aq_filters_vlans_update(aq_nic);
|
||||
if (err < 0)
|
||||
goto err_exit;
|
||||
|
||||
err = aq_nic_start(aq_nic);
|
||||
if (err < 0) {
|
||||
aq_nic_stop(aq_nic);
|
||||
|
|
@ -113,12 +107,20 @@ static netdev_tx_t aq_ndev_start_xmit(struct sk_buff *skb, struct net_device *nd
|
|||
* and hardware PTP design of the chip. Otherwise ptp stream
|
||||
* will fail to sync
|
||||
*/
|
||||
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) ||
|
||||
unlikely((ip_hdr(skb)->version == 4) &&
|
||||
(ip_hdr(skb)->protocol == IPPROTO_UDP) &&
|
||||
((udp_hdr(skb)->dest == htons(319)) ||
|
||||
(udp_hdr(skb)->dest == htons(320)))) ||
|
||||
unlikely(eth_hdr(skb)->h_proto == htons(ETH_P_1588)))
|
||||
if (unlikely(skb->protocol == htons(ETH_P_IP) &&
|
||||
ip_hdr(skb)->protocol == IPPROTO_UDP &&
|
||||
(udp_hdr(skb)->dest == htons(PTP_EV_PORT) ||
|
||||
udp_hdr(skb)->dest == htons(PTP_GEN_PORT))))
|
||||
return aq_ptp_xmit(aq_nic, skb);
|
||||
|
||||
/* PTP over IPv6 does not use extension headers */
|
||||
if (unlikely(skb->protocol == htons(ETH_P_IPV6) &&
|
||||
ipv6_hdr(skb)->nexthdr == IPPROTO_UDP &&
|
||||
(udp_hdr(skb)->dest == htons(PTP_EV_PORT) ||
|
||||
udp_hdr(skb)->dest == htons(PTP_GEN_PORT))))
|
||||
return aq_ptp_xmit(aq_nic, skb);
|
||||
|
||||
if (unlikely(eth_hdr(skb)->h_proto == htons(ETH_P_1588)))
|
||||
return aq_ptp_xmit(aq_nic, skb);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -72,8 +72,15 @@ static void aq_nic_cfg_update_num_vecs(struct aq_nic_s *self)
|
|||
|
||||
cfg->vecs = min(cfg->aq_hw_caps->vecs, AQ_CFG_VECS_DEF);
|
||||
cfg->vecs = min(cfg->vecs, num_online_cpus());
|
||||
if (self->irqvecs > AQ_HW_SERVICE_IRQS)
|
||||
cfg->vecs = min(cfg->vecs, self->irqvecs - AQ_HW_SERVICE_IRQS);
|
||||
if (self->irqvecs > AQ_HW_SERVICE_IRQS + AQ_HW_PTP_IRQS)
|
||||
cfg->vecs = min(cfg->vecs,
|
||||
self->irqvecs - AQ_HW_SERVICE_IRQS - AQ_HW_PTP_IRQS);
|
||||
else if (self->irqvecs > AQ_HW_PTP_IRQS)
|
||||
cfg->vecs = min(cfg->vecs,
|
||||
self->irqvecs - AQ_HW_PTP_IRQS);
|
||||
else
|
||||
cfg->vecs = 1U;
|
||||
|
||||
/* cfg->vecs should be power of 2 for RSS */
|
||||
cfg->vecs = rounddown_pow_of_two(cfg->vecs);
|
||||
|
||||
|
|
@ -138,7 +145,8 @@ void aq_nic_cfg_start(struct aq_nic_s *self)
|
|||
* link status IRQ. If no - we'll know link state from
|
||||
* slower service task.
|
||||
*/
|
||||
if (AQ_HW_SERVICE_IRQS > 0 && cfg->vecs + 1 <= self->irqvecs)
|
||||
if (AQ_HW_SERVICE_IRQS > 0 &&
|
||||
self->irqvecs > AQ_HW_PTP_IRQS + AQ_HW_SERVICE_IRQS)
|
||||
cfg->link_irq_vec = cfg->vecs;
|
||||
else
|
||||
cfg->link_irq_vec = 0;
|
||||
|
|
@ -172,7 +180,14 @@ static int aq_nic_update_link_status(struct aq_nic_s *self)
|
|||
aq_nic_update_interrupt_moderation_settings(self);
|
||||
|
||||
if (self->aq_ptp) {
|
||||
aq_ptp_clock_init(self);
|
||||
/* AQC113 TSG requires >= 100 Mbps full-duplex: below 100 Mbps
|
||||
* timestamp resolution is insufficient for IEEE 1588, and
|
||||
* half-duplex collision domains make TX/RX correlation unreliable.
|
||||
*/
|
||||
bool ptp_link_good = (self->aq_hw->aq_link_status.mbps >= 100 &&
|
||||
self->aq_hw->aq_link_status.full_duplex);
|
||||
|
||||
aq_ptp_clock_init(self, ptp_link_good ? AQ_PTP_LINK_UP : AQ_PTP_NO_LINK);
|
||||
aq_ptp_tm_offset_set(self,
|
||||
self->aq_hw->aq_link_status.mbps);
|
||||
aq_ptp_link_change(self);
|
||||
|
|
@ -279,6 +294,7 @@ static int aq_nic_hw_prepare(struct aq_nic_s *self)
|
|||
int err = 0;
|
||||
|
||||
err = self->aq_hw_ops->hw_soft_reset(self->aq_hw);
|
||||
|
||||
if (err)
|
||||
goto exit;
|
||||
|
||||
|
|
@ -450,7 +466,14 @@ int aq_nic_init(struct aq_nic_s *self)
|
|||
}
|
||||
|
||||
if (aq_nic_get_cfg(self)->is_ptp) {
|
||||
err = aq_ptp_init(self, self->irqvecs - 1);
|
||||
u32 ptp_isr_vec;
|
||||
|
||||
if (self->irqvecs > AQ_HW_PTP_IRQS)
|
||||
ptp_isr_vec = self->irqvecs - AQ_HW_PTP_IRQS;
|
||||
else
|
||||
ptp_isr_vec = 0;
|
||||
|
||||
err = aq_ptp_init(self, ptp_isr_vec);
|
||||
if (err < 0)
|
||||
goto err_exit;
|
||||
|
||||
|
|
@ -496,6 +519,14 @@ int aq_nic_start(struct aq_nic_s *self)
|
|||
goto err_exit;
|
||||
}
|
||||
|
||||
err = aq_reapply_rxnfc_all_rules(self);
|
||||
if (err < 0)
|
||||
goto err_exit;
|
||||
|
||||
err = aq_filters_vlans_update(self);
|
||||
if (err < 0)
|
||||
goto err_exit;
|
||||
|
||||
err = aq_ptp_ring_start(self);
|
||||
if (err < 0)
|
||||
goto err_exit;
|
||||
|
|
@ -683,6 +714,7 @@ unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb,
|
|||
unsigned int ret = 0U;
|
||||
unsigned int dx;
|
||||
u8 l4proto = 0;
|
||||
s32 clk_sel;
|
||||
|
||||
if (ipver == 4)
|
||||
l4proto = ip_hdr(skb)->protocol;
|
||||
|
|
@ -795,6 +827,17 @@ unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb,
|
|||
dx_buff->is_eop = 1U;
|
||||
dx_buff->skb = skb;
|
||||
dx_buff->xdpf = NULL;
|
||||
if (skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS &&
|
||||
self->aq_hw_ops->enable_ptp &&
|
||||
self->aq_hw_ops->hw_get_clk_sel &&
|
||||
aq_ptp_ring(self, ring)) {
|
||||
clk_sel = (s32)self->aq_hw_ops->hw_get_clk_sel(self->aq_hw);
|
||||
if (clk_sel < 0)
|
||||
goto exit;
|
||||
dx_buff->request_ts = 1U;
|
||||
dx_buff->clk_sel = (u32)clk_sel;
|
||||
ring->ptp_ts_deadline = jiffies + HZ;
|
||||
}
|
||||
goto exit;
|
||||
|
||||
mapping_error:
|
||||
|
|
|
|||
|
|
@ -250,6 +250,7 @@ static int aq_pci_probe(struct pci_dev *pdev,
|
|||
goto err_ioremap;
|
||||
}
|
||||
self->aq_hw->aq_nic_cfg = aq_nic_get_cfg(self);
|
||||
self->aq_hw->clk_select = -1;
|
||||
if (self->aq_hw->aq_nic_cfg->aq_hw_caps->priv_data_len) {
|
||||
int len = self->aq_hw->aq_nic_cfg->aq_hw_caps->priv_data_len;
|
||||
|
||||
|
|
@ -293,8 +294,8 @@ static int aq_pci_probe(struct pci_dev *pdev,
|
|||
numvecs = min((u8)AQ_CFG_VECS_DEF,
|
||||
aq_nic_get_cfg(self)->aq_hw_caps->msix_irqs);
|
||||
numvecs = min(numvecs, num_online_cpus());
|
||||
/* Request IRQ vector for PTP */
|
||||
numvecs += 1;
|
||||
/* Request IRQ lines for PTP */
|
||||
numvecs += AQ_HW_PTP_IRQS;
|
||||
|
||||
numvecs += AQ_HW_SERVICE_IRQS;
|
||||
/*enable interrupts */
|
||||
|
|
|
|||
|
|
@ -26,6 +26,18 @@
|
|||
|
||||
#define POLL_SYNC_TIMER_MS 15
|
||||
|
||||
#define PTP_UDP_FILTERS_CNT 4
|
||||
|
||||
#define PTP_IPV4_MC_ADDR1 0xE0000181
|
||||
#define PTP_IPV4_MC_ADDR2 0xE000006B
|
||||
|
||||
#define PTP_IPV6_MC_ADDR10 0xFF0E
|
||||
#define PTP_IPV6_MC_ADDR14 0x0181
|
||||
#define PTP_IPV6_MC_ADDR20 0xFF02
|
||||
#define PTP_IPV6_MC_ADDR24 0x006B
|
||||
|
||||
#define PTP_GPIO_HIGHTIME 100000
|
||||
|
||||
enum ptp_speed_offsets {
|
||||
ptp_offset_idx_10 = 0,
|
||||
ptp_offset_idx_100,
|
||||
|
|
@ -49,11 +61,18 @@ struct ptp_tx_timeout {
|
|||
unsigned long tx_start;
|
||||
};
|
||||
|
||||
struct ptp_tm_offset {
|
||||
unsigned int mbps;
|
||||
int egress;
|
||||
int ingress;
|
||||
};
|
||||
|
||||
struct aq_ptp_s {
|
||||
struct aq_nic_s *aq_nic;
|
||||
struct kernel_hwtstamp_config hwtstamp_config;
|
||||
spinlock_t ptp_lock;
|
||||
spinlock_t ptp_ring_lock;
|
||||
struct mutex ptp_filter_lock; /* serializes aq_ptp_dpath_enable() */
|
||||
struct ptp_clock *ptp_clock;
|
||||
struct ptp_clock_info ptp_info;
|
||||
|
||||
|
|
@ -64,7 +83,7 @@ struct aq_ptp_s {
|
|||
|
||||
struct ptp_tx_timeout ptp_tx_timeout;
|
||||
|
||||
unsigned int idx_vector;
|
||||
unsigned int idx_ptp_vector;
|
||||
struct napi_struct napi;
|
||||
|
||||
struct aq_ring_s ptp_tx;
|
||||
|
|
@ -73,7 +92,7 @@ struct aq_ptp_s {
|
|||
|
||||
struct ptp_skb_ring skb_ring;
|
||||
|
||||
struct aq_rx_filter_l3l4 udp_filter;
|
||||
struct aq_rx_filter_l3l4 udp_filter[PTP_UDP_FILTERS_CNT];
|
||||
struct aq_rx_filter_l2 eth_type_filter;
|
||||
|
||||
struct delayed_work poll_sync;
|
||||
|
|
@ -81,18 +100,15 @@ struct aq_ptp_s {
|
|||
|
||||
bool extts_pin_enabled;
|
||||
u64 last_sync1588_ts;
|
||||
/* TSG clock selection: 0 - PTP, 1 - PTM */
|
||||
u32 ptp_clock_sel;
|
||||
|
||||
bool a1_ptp;
|
||||
};
|
||||
bool a2_ptp;
|
||||
|
||||
struct ptp_tm_offset {
|
||||
unsigned int mbps;
|
||||
int egress;
|
||||
int ingress;
|
||||
struct ptp_tm_offset ptp_offset[6];
|
||||
};
|
||||
|
||||
static struct ptp_tm_offset ptp_offset[6];
|
||||
|
||||
void aq_ptp_tm_offset_set(struct aq_nic_s *aq_nic, unsigned int mbps)
|
||||
{
|
||||
struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
|
||||
|
|
@ -104,10 +120,10 @@ void aq_ptp_tm_offset_set(struct aq_nic_s *aq_nic, unsigned int mbps)
|
|||
egress = 0;
|
||||
ingress = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ptp_offset); i++) {
|
||||
if (mbps == ptp_offset[i].mbps) {
|
||||
egress = ptp_offset[i].egress;
|
||||
ingress = ptp_offset[i].ingress;
|
||||
for (i = 0; i < ARRAY_SIZE(aq_ptp->ptp_offset); i++) {
|
||||
if (mbps == aq_ptp->ptp_offset[i].mbps) {
|
||||
egress = aq_ptp->ptp_offset[i].egress;
|
||||
ingress = aq_ptp->ptp_offset[i].ingress;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -268,6 +284,18 @@ static void aq_ptp_tx_timeout_check(struct aq_ptp_s *aq_ptp)
|
|||
}
|
||||
}
|
||||
|
||||
void aq_ptp_tx_skb_drop_head(struct aq_nic_s *aq_nic)
|
||||
{
|
||||
struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (!aq_ptp)
|
||||
return;
|
||||
skb = aq_ptp_skb_get(&aq_ptp->skb_ring);
|
||||
if (skb)
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
/* aq_ptp_adjfine
|
||||
* @ptp: the ptp clock structure
|
||||
* @ppb: parts per billion adjustment from base
|
||||
|
|
@ -366,6 +394,8 @@ static void aq_ptp_convert_to_hwtstamp(struct aq_ptp_s *aq_ptp,
|
|||
static int aq_ptp_hw_pin_conf(struct aq_nic_s *aq_nic, u32 pin_index, u64 start,
|
||||
u64 period)
|
||||
{
|
||||
struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
|
||||
|
||||
if (period)
|
||||
netdev_dbg(aq_nic->ndev,
|
||||
"Enable GPIO %d pulsing, start time %llu, period %u\n",
|
||||
|
|
@ -380,7 +410,8 @@ static int aq_ptp_hw_pin_conf(struct aq_nic_s *aq_nic, u32 pin_index, u64 start,
|
|||
*/
|
||||
mutex_lock(&aq_nic->fwreq_mutex);
|
||||
aq_nic->aq_hw_ops->hw_gpio_pulse(aq_nic->aq_hw, pin_index,
|
||||
start, (u32)period);
|
||||
aq_ptp->ptp_clock_sel, start,
|
||||
(u32)period, PTP_GPIO_HIGHTIME);
|
||||
mutex_unlock(&aq_nic->fwreq_mutex);
|
||||
|
||||
return 0;
|
||||
|
|
@ -454,6 +485,7 @@ static void aq_ptp_extts_pin_ctrl(struct aq_ptp_s *aq_ptp)
|
|||
|
||||
if (aq_nic->aq_hw_ops->hw_extts_gpio_enable)
|
||||
aq_nic->aq_hw_ops->hw_extts_gpio_enable(aq_nic->aq_hw, 0,
|
||||
aq_ptp->ptp_clock_sel,
|
||||
enable);
|
||||
}
|
||||
|
||||
|
|
@ -543,14 +575,191 @@ void aq_ptp_tx_hwtstamp(struct aq_nic_s *aq_nic, u64 timestamp)
|
|||
return;
|
||||
}
|
||||
|
||||
timestamp += atomic_read(&aq_ptp->offset_egress);
|
||||
aq_ptp_convert_to_hwtstamp(aq_ptp, &hwtstamp, timestamp);
|
||||
skb_tstamp_tx(skb, &hwtstamp);
|
||||
if ((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
|
||||
timestamp += atomic_read(&aq_ptp->offset_egress);
|
||||
aq_ptp_convert_to_hwtstamp(aq_ptp, &hwtstamp, timestamp);
|
||||
skb_tstamp_tx(skb, &hwtstamp);
|
||||
}
|
||||
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
aq_ptp_tx_timeout_update(aq_ptp);
|
||||
}
|
||||
|
||||
static void aq_ptp_fill_udpv4_mc(struct ethtool_rx_flow_spec *fsp,
|
||||
u16 rx_queue, __be32 mc_addr)
|
||||
{
|
||||
memset(fsp, 0, sizeof(*fsp));
|
||||
fsp->ring_cookie = rx_queue;
|
||||
fsp->flow_type = UDP_V4_FLOW;
|
||||
fsp->h_u.udp_ip4_spec.pdst = cpu_to_be16(PTP_EV_PORT);
|
||||
fsp->m_u.udp_ip4_spec.pdst = cpu_to_be16(0xffff);
|
||||
fsp->h_u.udp_ip4_spec.ip4dst = mc_addr;
|
||||
fsp->m_u.udp_ip4_spec.ip4dst = cpu_to_be32(0xffffffff);
|
||||
}
|
||||
|
||||
static void aq_ptp_fill_udpv6_mc(struct ethtool_rx_flow_spec *fsp,
|
||||
u16 rx_queue,
|
||||
__be32 ip6dst_hi, __be32 ip6dst_hi_mask,
|
||||
__be32 ip6dst_lo, __be32 ip6dst_lo_mask)
|
||||
{
|
||||
memset(fsp, 0, sizeof(*fsp));
|
||||
fsp->ring_cookie = rx_queue;
|
||||
fsp->flow_type = UDP_V6_FLOW;
|
||||
fsp->h_u.udp_ip6_spec.pdst = cpu_to_be16(PTP_EV_PORT);
|
||||
fsp->m_u.udp_ip6_spec.pdst = cpu_to_be16(0xffff);
|
||||
fsp->h_u.udp_ip6_spec.ip6dst[0] = ip6dst_hi;
|
||||
fsp->m_u.udp_ip6_spec.ip6dst[0] = ip6dst_hi_mask;
|
||||
fsp->h_u.udp_ip6_spec.ip6dst[3] = ip6dst_lo;
|
||||
fsp->m_u.udp_ip6_spec.ip6dst[3] = ip6dst_lo_mask;
|
||||
}
|
||||
|
||||
static void aq_ptp_add_a2_filter(struct aq_ptp_s *aq_ptp,
|
||||
struct ethtool_rx_flow_spec *fsp,
|
||||
int *flt_idx)
|
||||
{
|
||||
struct aq_nic_s *aq_nic = aq_ptp->aq_nic;
|
||||
|
||||
aq_set_data_fl3l4(fsp,
|
||||
&aq_ptp->udp_filter[*flt_idx],
|
||||
aq_ptp->udp_filter[*flt_idx].location,
|
||||
true);
|
||||
|
||||
netdev_dbg(aq_nic->ndev,
|
||||
"PTP MC filter prepared. Loc: %x\n",
|
||||
aq_ptp->udp_filter[*flt_idx].location);
|
||||
(*flt_idx)++;
|
||||
}
|
||||
|
||||
static int aq_ptp_dpath_enable(struct aq_ptp_s *aq_ptp,
|
||||
int enable_flags, u16 rx_queue)
|
||||
{
|
||||
struct aq_nic_s *aq_nic = aq_ptp->aq_nic;
|
||||
struct ethtool_rxnfc cmd = { 0 };
|
||||
const struct aq_hw_ops *hw_ops = aq_nic->aq_hw_ops;
|
||||
struct ethtool_rx_flow_spec *fsp =
|
||||
(struct ethtool_rx_flow_spec *)&cmd.fs;
|
||||
int err = 0, i = 0;
|
||||
int flt_idx = 0;
|
||||
|
||||
netdev_dbg(aq_nic->ndev,
|
||||
"%sable ptp filters: %x.\n",
|
||||
enable_flags ? "En" : "Dis", enable_flags);
|
||||
|
||||
if (enable_flags) {
|
||||
/* Clear all existing L4 filters before applying new config */
|
||||
for (i = 0; i < PTP_UDP_FILTERS_CNT; i++) {
|
||||
aq_ptp->udp_filter[i].cmd &=
|
||||
~HW_ATL_RX_ENABLE_FLTR_L3L4;
|
||||
if (hw_ops->hw_filter_l3l4_set) {
|
||||
err = hw_ops->hw_filter_l3l4_set(aq_nic->aq_hw,
|
||||
&aq_ptp->udp_filter[i]);
|
||||
if (err)
|
||||
netdev_dbg(aq_nic->ndev,
|
||||
"Set UDP filter failed\n");
|
||||
}
|
||||
}
|
||||
if (enable_flags & (AQ_HW_PTP_L4_ENABLE)) {
|
||||
if (aq_ptp->a1_ptp) {
|
||||
fsp->ring_cookie = rx_queue;
|
||||
fsp->flow_type = UDP_V4_FLOW;
|
||||
fsp->h_u.udp_ip4_spec.pdst =
|
||||
cpu_to_be16(PTP_EV_PORT);
|
||||
fsp->m_u.udp_ip4_spec.pdst =
|
||||
cpu_to_be16(0xffff);
|
||||
err = aq_set_data_fl3l4(fsp,
|
||||
&aq_ptp->udp_filter[flt_idx],
|
||||
aq_ptp->udp_filter[flt_idx].location,
|
||||
true);
|
||||
if (!err) {
|
||||
netdev_dbg(aq_nic->ndev,
|
||||
"Set UDPv4, location: %x\n",
|
||||
aq_ptp->udp_filter[flt_idx]
|
||||
.location);
|
||||
flt_idx++;
|
||||
}
|
||||
} else {
|
||||
aq_ptp_fill_udpv4_mc(fsp, rx_queue,
|
||||
cpu_to_be32(PTP_IPV4_MC_ADDR1));
|
||||
aq_ptp_add_a2_filter(aq_ptp, fsp,
|
||||
&flt_idx);
|
||||
|
||||
aq_ptp_fill_udpv6_mc(fsp, rx_queue,
|
||||
cpu_to_be32(PTP_IPV6_MC_ADDR20 << 16),
|
||||
cpu_to_be32(0xffff0000),
|
||||
cpu_to_be32(PTP_IPV6_MC_ADDR24),
|
||||
cpu_to_be32(0x0000ffff));
|
||||
aq_ptp_add_a2_filter(aq_ptp, fsp,
|
||||
&flt_idx);
|
||||
|
||||
aq_ptp_fill_udpv6_mc(fsp, rx_queue,
|
||||
cpu_to_be32(PTP_IPV6_MC_ADDR10 << 16),
|
||||
cpu_to_be32(0xffff0000),
|
||||
cpu_to_be32(PTP_IPV6_MC_ADDR14),
|
||||
cpu_to_be32(0x0000ffff));
|
||||
aq_ptp_add_a2_filter(aq_ptp, fsp,
|
||||
&flt_idx);
|
||||
|
||||
aq_ptp_fill_udpv4_mc(fsp, rx_queue,
|
||||
cpu_to_be32(PTP_IPV4_MC_ADDR2));
|
||||
aq_ptp_add_a2_filter(aq_ptp, fsp,
|
||||
&flt_idx);
|
||||
}
|
||||
}
|
||||
|
||||
if (enable_flags & AQ_HW_PTP_L2_ENABLE) {
|
||||
aq_ptp->eth_type_filter.ethertype = ETH_P_1588;
|
||||
aq_ptp->eth_type_filter.queue = rx_queue;
|
||||
}
|
||||
|
||||
if (hw_ops->hw_filter_l3l4_set) {
|
||||
for (i = 0; i < flt_idx; i++) {
|
||||
err = hw_ops->hw_filter_l3l4_set(aq_nic->aq_hw,
|
||||
&aq_ptp->udp_filter[i]);
|
||||
|
||||
if (!err) {
|
||||
netdev_dbg(aq_nic->ndev,
|
||||
"Set UDP filter complete. Location: %x\n",
|
||||
aq_ptp->udp_filter[i].location);
|
||||
} else {
|
||||
netdev_dbg(aq_nic->ndev, "Set UDP filter failed\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!err && (enable_flags & AQ_HW_PTP_L2_ENABLE) &&
|
||||
hw_ops->hw_filter_l2_set) {
|
||||
err = hw_ops->hw_filter_l2_set(aq_nic->aq_hw,
|
||||
&aq_ptp->eth_type_filter);
|
||||
|
||||
if (!err)
|
||||
netdev_dbg(aq_nic->ndev,
|
||||
"Set L2 filter complete. Location: %d\n",
|
||||
aq_ptp->eth_type_filter.location);
|
||||
}
|
||||
} else {
|
||||
/* PTP disabled, clear all UDP/L2 filters */
|
||||
for (i = 0; i < PTP_UDP_FILTERS_CNT; i++) {
|
||||
aq_ptp->udp_filter[i].cmd &=
|
||||
~HW_ATL_RX_ENABLE_FLTR_L3L4;
|
||||
if (hw_ops->hw_filter_l3l4_set) {
|
||||
err = hw_ops->hw_filter_l3l4_set(aq_nic->aq_hw,
|
||||
&aq_ptp->udp_filter[i]);
|
||||
if (err)
|
||||
netdev_dbg(aq_nic->ndev,
|
||||
"Set UDP filter failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (!err && hw_ops->hw_filter_l2_clear)
|
||||
err = hw_ops->hw_filter_l2_clear(aq_nic->aq_hw,
|
||||
&aq_ptp->eth_type_filter);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* aq_ptp_rx_hwtstamp - utility function which checks for RX time stamp
|
||||
* @adapter: pointer to adapter struct
|
||||
* @shhwtstamps: particular skb_shared_hwtstamps to save timestamp
|
||||
|
|
@ -572,59 +781,61 @@ void aq_ptp_hwtstamp_config_get(struct aq_ptp_s *aq_ptp,
|
|||
*config = aq_ptp->hwtstamp_config;
|
||||
}
|
||||
|
||||
static void aq_ptp_prepare_filters(struct aq_ptp_s *aq_ptp)
|
||||
static unsigned int aq_ptp_parse_rx_filters(enum hwtstamp_rx_filters rx_filter)
|
||||
{
|
||||
aq_ptp->udp_filter.cmd = HW_ATL_RX_ENABLE_FLTR_L3L4 |
|
||||
HW_ATL_RX_ENABLE_CMP_PROT_L4 |
|
||||
HW_ATL_RX_UDP |
|
||||
HW_ATL_RX_ENABLE_CMP_DEST_PORT_L4 |
|
||||
HW_ATL_RX_HOST << HW_ATL_RX_ACTION_FL3F4_SHIFT |
|
||||
HW_ATL_RX_ENABLE_QUEUE_L3L4 |
|
||||
aq_ptp->ptp_rx.idx << HW_ATL_RX_QUEUE_FL3L4_SHIFT;
|
||||
aq_ptp->udp_filter.p_dst = PTP_EV_PORT;
|
||||
unsigned int ptp_en_flags = AQ_HW_PTP_DISABLE;
|
||||
|
||||
aq_ptp->eth_type_filter.ethertype = ETH_P_1588;
|
||||
aq_ptp->eth_type_filter.queue = aq_ptp->ptp_rx.idx;
|
||||
switch (rx_filter) {
|
||||
case HWTSTAMP_FILTER_NONE:
|
||||
break;
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
|
||||
ptp_en_flags = AQ_HW_PTP_L2_ENABLE;
|
||||
break;
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
|
||||
ptp_en_flags = AQ_HW_PTP_L4_ENABLE;
|
||||
break;
|
||||
case HWTSTAMP_FILTER_PTP_V2_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
|
||||
case HWTSTAMP_FILTER_ALL:
|
||||
default:
|
||||
ptp_en_flags = AQ_HW_PTP_L4_ENABLE | AQ_HW_PTP_L2_ENABLE;
|
||||
break;
|
||||
}
|
||||
return ptp_en_flags;
|
||||
}
|
||||
|
||||
int aq_ptp_hwtstamp_config_set(struct aq_ptp_s *aq_ptp,
|
||||
struct kernel_hwtstamp_config *config)
|
||||
{
|
||||
unsigned int ptp_en_flags = aq_ptp_parse_rx_filters(config->rx_filter);
|
||||
struct aq_nic_s *aq_nic = aq_ptp->aq_nic;
|
||||
const struct aq_hw_ops *hw_ops;
|
||||
int err = 0;
|
||||
|
||||
hw_ops = aq_nic->aq_hw_ops;
|
||||
if (config->tx_type == HWTSTAMP_TX_ON ||
|
||||
config->rx_filter == HWTSTAMP_FILTER_PTP_V2_EVENT) {
|
||||
aq_ptp_prepare_filters(aq_ptp);
|
||||
if (hw_ops->hw_filter_l3l4_set) {
|
||||
err = hw_ops->hw_filter_l3l4_set(aq_nic->aq_hw,
|
||||
&aq_ptp->udp_filter);
|
||||
}
|
||||
if (!err && hw_ops->hw_filter_l2_set) {
|
||||
err = hw_ops->hw_filter_l2_set(aq_nic->aq_hw,
|
||||
&aq_ptp->eth_type_filter);
|
||||
}
|
||||
aq_utils_obj_set(&aq_nic->flags, AQ_NIC_PTP_DPATH_UP);
|
||||
} else {
|
||||
aq_ptp->udp_filter.cmd &= ~HW_ATL_RX_ENABLE_FLTR_L3L4;
|
||||
if (hw_ops->hw_filter_l3l4_set) {
|
||||
err = hw_ops->hw_filter_l3l4_set(aq_nic->aq_hw,
|
||||
&aq_ptp->udp_filter);
|
||||
}
|
||||
if (!err && hw_ops->hw_filter_l2_clear) {
|
||||
err = hw_ops->hw_filter_l2_clear(aq_nic->aq_hw,
|
||||
&aq_ptp->eth_type_filter);
|
||||
}
|
||||
aq_utils_obj_clear(&aq_nic->flags, AQ_NIC_PTP_DPATH_UP);
|
||||
mutex_lock(&aq_ptp->ptp_filter_lock);
|
||||
if (aq_ptp->hwtstamp_config.rx_filter != config->rx_filter) {
|
||||
err = aq_ptp_dpath_enable(aq_ptp,
|
||||
ptp_en_flags,
|
||||
aq_ptp->ptp_rx.idx);
|
||||
}
|
||||
mutex_unlock(&aq_ptp->ptp_filter_lock);
|
||||
|
||||
if (err)
|
||||
return -EREMOTEIO;
|
||||
|
||||
aq_ptp->hwtstamp_config = *config;
|
||||
if (ptp_en_flags != AQ_HW_PTP_DISABLE)
|
||||
aq_utils_obj_set(&aq_nic->flags, AQ_NIC_PTP_DPATH_UP);
|
||||
else
|
||||
aq_utils_obj_clear(&aq_nic->flags, AQ_NIC_PTP_DPATH_UP);
|
||||
|
||||
aq_ptp->hwtstamp_config = *config;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -673,21 +884,23 @@ static int aq_ptp_poll(struct napi_struct *napi, int budget)
|
|||
was_cleaned = true;
|
||||
}
|
||||
|
||||
/* Processing HW_TIMESTAMP RX traffic */
|
||||
err = aq_nic->aq_hw_ops->hw_ring_hwts_rx_receive(aq_nic->aq_hw,
|
||||
&aq_ptp->hwts_rx);
|
||||
if (err < 0)
|
||||
goto err_exit;
|
||||
|
||||
if (aq_ptp->hwts_rx.sw_head != aq_ptp->hwts_rx.hw_head) {
|
||||
aq_ring_hwts_rx_clean(&aq_ptp->hwts_rx, aq_nic);
|
||||
|
||||
err = aq_nic->aq_hw_ops->hw_ring_hwts_rx_fill(aq_nic->aq_hw,
|
||||
&aq_ptp->hwts_rx);
|
||||
if (aq_ptp->a1_ptp) {
|
||||
/* Processing HW_TIMESTAMP RX traffic */
|
||||
err = aq_nic->aq_hw_ops->hw_ring_hwts_rx_receive(aq_nic->aq_hw,
|
||||
&aq_ptp->hwts_rx);
|
||||
if (err < 0)
|
||||
goto err_exit;
|
||||
|
||||
was_cleaned = true;
|
||||
if (aq_ptp->hwts_rx.sw_head != aq_ptp->hwts_rx.hw_head) {
|
||||
aq_ring_hwts_rx_clean(&aq_ptp->hwts_rx, aq_nic);
|
||||
|
||||
err = aq_nic->aq_hw_ops->hw_ring_hwts_rx_fill(aq_nic->aq_hw,
|
||||
&aq_ptp->hwts_rx);
|
||||
if (err < 0)
|
||||
goto err_exit;
|
||||
|
||||
was_cleaned = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Processing PTP RX traffic */
|
||||
|
|
@ -818,7 +1031,7 @@ int aq_ptp_irq_alloc(struct aq_nic_s *aq_nic)
|
|||
return 0;
|
||||
|
||||
if (pdev->msix_enabled || pdev->msi_enabled) {
|
||||
err = request_irq(pci_irq_vector(pdev, aq_ptp->idx_vector),
|
||||
err = request_irq(pci_irq_vector(pdev, aq_ptp->idx_ptp_vector),
|
||||
aq_ptp_isr, 0, aq_nic->ndev->name, aq_ptp);
|
||||
} else {
|
||||
err = -EINVAL;
|
||||
|
|
@ -837,7 +1050,7 @@ void aq_ptp_irq_free(struct aq_nic_s *aq_nic)
|
|||
if (!aq_ptp)
|
||||
return;
|
||||
|
||||
free_irq(pci_irq_vector(pdev, aq_ptp->idx_vector), aq_ptp);
|
||||
free_irq(pci_irq_vector(pdev, aq_ptp->idx_ptp_vector), aq_ptp);
|
||||
}
|
||||
|
||||
int aq_ptp_ring_init(struct aq_nic_s *aq_nic)
|
||||
|
|
@ -875,6 +1088,9 @@ int aq_ptp_ring_init(struct aq_nic_s *aq_nic)
|
|||
if (err < 0)
|
||||
goto err_rx_free;
|
||||
|
||||
if (aq_ptp->a2_ptp)
|
||||
return 0;
|
||||
|
||||
err = aq_ring_init(&aq_ptp->hwts_rx, ATL_RING_RX);
|
||||
if (err < 0)
|
||||
goto err_rx_free;
|
||||
|
|
@ -912,10 +1128,12 @@ int aq_ptp_ring_start(struct aq_nic_s *aq_nic)
|
|||
if (err < 0)
|
||||
goto err_exit;
|
||||
|
||||
err = aq_nic->aq_hw_ops->hw_ring_rx_start(aq_nic->aq_hw,
|
||||
&aq_ptp->hwts_rx);
|
||||
if (err < 0)
|
||||
goto err_exit;
|
||||
if (aq_ptp->a1_ptp) {
|
||||
err = aq_nic->aq_hw_ops->hw_ring_rx_start(aq_nic->aq_hw,
|
||||
&aq_ptp->hwts_rx);
|
||||
if (err < 0)
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
napi_enable(&aq_ptp->napi);
|
||||
|
||||
|
|
@ -933,7 +1151,9 @@ void aq_ptp_ring_stop(struct aq_nic_s *aq_nic)
|
|||
aq_nic->aq_hw_ops->hw_ring_tx_stop(aq_nic->aq_hw, &aq_ptp->ptp_tx);
|
||||
aq_nic->aq_hw_ops->hw_ring_rx_stop(aq_nic->aq_hw, &aq_ptp->ptp_rx);
|
||||
|
||||
aq_nic->aq_hw_ops->hw_ring_rx_stop(aq_nic->aq_hw, &aq_ptp->hwts_rx);
|
||||
if (aq_ptp->a1_ptp)
|
||||
aq_nic->aq_hw_ops->hw_ring_rx_stop(aq_nic->aq_hw,
|
||||
&aq_ptp->hwts_rx);
|
||||
|
||||
napi_disable(&aq_ptp->napi);
|
||||
}
|
||||
|
|
@ -972,11 +1192,13 @@ int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic)
|
|||
if (err)
|
||||
goto err_exit_ptp_tx;
|
||||
|
||||
err = aq_ring_hwts_rx_alloc(&aq_ptp->hwts_rx, aq_nic, PTP_HWST_RING_IDX,
|
||||
aq_nic->aq_nic_cfg.rxds,
|
||||
aq_nic->aq_nic_cfg.aq_hw_caps->rxd_size);
|
||||
if (err)
|
||||
goto err_exit_ptp_rx;
|
||||
if (aq_ptp->a1_ptp) {
|
||||
err = aq_ring_hwts_rx_alloc(&aq_ptp->hwts_rx, aq_nic, PTP_HWST_RING_IDX,
|
||||
aq_nic->aq_nic_cfg.rxds,
|
||||
aq_nic->aq_nic_cfg.aq_hw_caps->rxd_size);
|
||||
if (err)
|
||||
goto err_exit_ptp_rx;
|
||||
}
|
||||
|
||||
err = aq_ptp_skb_ring_init(&aq_ptp->skb_ring, aq_nic->aq_nic_cfg.rxds);
|
||||
if (err != 0) {
|
||||
|
|
@ -984,7 +1206,7 @@ int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic)
|
|||
goto err_exit_hwts_rx;
|
||||
}
|
||||
|
||||
aq_ptp->ptp_ring_param.vec_idx = aq_ptp->idx_vector;
|
||||
aq_ptp->ptp_ring_param.vec_idx = aq_ptp->idx_ptp_vector;
|
||||
aq_ptp->ptp_ring_param.cpu = aq_ptp->ptp_ring_param.vec_idx +
|
||||
aq_nic_get_cfg(aq_nic)->aq_rss.base_cpu_number;
|
||||
cpumask_set_cpu(aq_ptp->ptp_ring_param.cpu,
|
||||
|
|
@ -993,7 +1215,8 @@ int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic)
|
|||
return 0;
|
||||
|
||||
err_exit_hwts_rx:
|
||||
aq_ring_hwts_rx_free(&aq_ptp->hwts_rx);
|
||||
if (aq_ptp->a1_ptp)
|
||||
aq_ring_hwts_rx_free(&aq_ptp->hwts_rx);
|
||||
err_exit_ptp_rx:
|
||||
aq_ring_free(&aq_ptp->ptp_rx);
|
||||
err_exit_ptp_tx:
|
||||
|
|
@ -1011,7 +1234,8 @@ void aq_ptp_ring_free(struct aq_nic_s *aq_nic)
|
|||
|
||||
aq_ring_free(&aq_ptp->ptp_tx);
|
||||
aq_ring_free(&aq_ptp->ptp_rx);
|
||||
aq_ring_hwts_rx_free(&aq_ptp->hwts_rx);
|
||||
if (aq_ptp->a1_ptp)
|
||||
aq_ring_hwts_rx_free(&aq_ptp->hwts_rx);
|
||||
|
||||
aq_ptp_skb_ring_release(&aq_ptp->skb_ring);
|
||||
}
|
||||
|
|
@ -1035,46 +1259,49 @@ static struct ptp_clock_info aq_ptp_clock = {
|
|||
.pin_config = NULL,
|
||||
};
|
||||
|
||||
#define ptp_offset_init(__idx, __mbps, __egress, __ingress) do { \
|
||||
ptp_offset[__idx].mbps = (__mbps); \
|
||||
ptp_offset[__idx].egress = (__egress); \
|
||||
ptp_offset[__idx].ingress = (__ingress); } \
|
||||
while (0)
|
||||
static void ptp_offset_init(struct aq_ptp_s *aq_ptp, int idx,
|
||||
unsigned int mbps, int egress, int ingress)
|
||||
{
|
||||
aq_ptp->ptp_offset[idx].mbps = mbps;
|
||||
aq_ptp->ptp_offset[idx].egress = egress;
|
||||
aq_ptp->ptp_offset[idx].ingress = ingress;
|
||||
}
|
||||
|
||||
static void aq_ptp_offset_init_from_fw(const struct hw_atl_ptp_offset *offsets)
|
||||
static void aq_ptp_offset_init_from_fw(struct aq_ptp_s *aq_ptp,
|
||||
const struct hw_atl_ptp_offset *offsets)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Load offsets for PTP */
|
||||
for (i = 0; i < ARRAY_SIZE(ptp_offset); i++) {
|
||||
for (i = 0; i < ARRAY_SIZE(aq_ptp->ptp_offset); i++) {
|
||||
switch (i) {
|
||||
/* 100M */
|
||||
case ptp_offset_idx_100:
|
||||
ptp_offset_init(i, 100,
|
||||
ptp_offset_init(aq_ptp, i, 100,
|
||||
offsets->egress_100,
|
||||
offsets->ingress_100);
|
||||
break;
|
||||
/* 1G */
|
||||
case ptp_offset_idx_1000:
|
||||
ptp_offset_init(i, 1000,
|
||||
ptp_offset_init(aq_ptp, i, 1000,
|
||||
offsets->egress_1000,
|
||||
offsets->ingress_1000);
|
||||
break;
|
||||
/* 2.5G */
|
||||
case ptp_offset_idx_2500:
|
||||
ptp_offset_init(i, 2500,
|
||||
ptp_offset_init(aq_ptp, i, 2500,
|
||||
offsets->egress_2500,
|
||||
offsets->ingress_2500);
|
||||
break;
|
||||
/* 5G */
|
||||
case ptp_offset_idx_5000:
|
||||
ptp_offset_init(i, 5000,
|
||||
ptp_offset_init(aq_ptp, i, 5000,
|
||||
offsets->egress_5000,
|
||||
offsets->ingress_5000);
|
||||
break;
|
||||
/* 10G */
|
||||
case ptp_offset_idx_10000:
|
||||
ptp_offset_init(i, 10000,
|
||||
ptp_offset_init(aq_ptp, i, 10000,
|
||||
offsets->egress_10000,
|
||||
offsets->ingress_10000);
|
||||
break;
|
||||
|
|
@ -1082,11 +1309,12 @@ static void aq_ptp_offset_init_from_fw(const struct hw_atl_ptp_offset *offsets)
|
|||
}
|
||||
}
|
||||
|
||||
static void aq_ptp_offset_init(const struct hw_atl_ptp_offset *offsets)
|
||||
static void aq_ptp_offset_init(struct aq_ptp_s *aq_ptp,
|
||||
const struct hw_atl_ptp_offset *offsets)
|
||||
{
|
||||
memset(ptp_offset, 0, sizeof(ptp_offset));
|
||||
memset(aq_ptp->ptp_offset, 0, sizeof(aq_ptp->ptp_offset));
|
||||
|
||||
aq_ptp_offset_init_from_fw(offsets);
|
||||
aq_ptp_offset_init_from_fw(aq_ptp, offsets);
|
||||
}
|
||||
|
||||
static void aq_ptp_gpio_init(struct ptp_clock_info *info,
|
||||
|
|
@ -1139,26 +1367,46 @@ static void aq_ptp_gpio_init(struct ptp_clock_info *info,
|
|||
sizeof(struct ptp_pin_desc) * info->n_pins);
|
||||
}
|
||||
|
||||
void aq_ptp_clock_init(struct aq_nic_s *aq_nic)
|
||||
void aq_ptp_clock_init(struct aq_nic_s *aq_nic, enum aq_ptp_state state)
|
||||
{
|
||||
struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
|
||||
struct timespec64 ts;
|
||||
|
||||
ktime_get_real_ts64(&ts);
|
||||
aq_ptp_settime(&aq_ptp->ptp_info, &ts);
|
||||
if (!aq_ptp)
|
||||
return;
|
||||
|
||||
if (aq_ptp->a1_ptp || state == AQ_PTP_FIRST_INIT) {
|
||||
struct timespec64 ts;
|
||||
|
||||
ktime_get_real_ts64(&ts);
|
||||
aq_ptp_settime(&aq_ptp->ptp_info, &ts);
|
||||
}
|
||||
|
||||
if (!aq_ptp->a1_ptp && state != AQ_PTP_FIRST_INIT) {
|
||||
mutex_lock(&aq_ptp->ptp_filter_lock);
|
||||
unsigned int ptp_en_flags =
|
||||
aq_ptp_parse_rx_filters(state == AQ_PTP_LINK_UP ?
|
||||
aq_ptp->hwtstamp_config.rx_filter :
|
||||
HWTSTAMP_FILTER_NONE);
|
||||
if (aq_ptp_dpath_enable(aq_ptp, ptp_en_flags, aq_ptp->ptp_rx.idx))
|
||||
netdev_warn(aq_nic->ndev,
|
||||
"PTP RX filter restore failed in link change\n");
|
||||
mutex_unlock(&aq_ptp->ptp_filter_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void aq_ptp_poll_sync_work_cb(struct work_struct *w);
|
||||
|
||||
int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec)
|
||||
int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_ptp_vec)
|
||||
{
|
||||
bool a1_ptp = ATL_HW_IS_CHIP_FEATURE(aq_nic->aq_hw, ATLANTIC);
|
||||
bool a2_ptp = ATL_HW_IS_CHIP_FEATURE(aq_nic->aq_hw, ANTIGUA);
|
||||
struct hw_atl_utils_mbox mbox;
|
||||
struct ptp_clock *clock;
|
||||
struct aq_ptp_s *aq_ptp;
|
||||
struct aq_ptp_s *aq_ptp = NULL;
|
||||
int err = 0;
|
||||
int i;
|
||||
|
||||
if (!a1_ptp) {
|
||||
if (!a1_ptp && !a2_ptp) {
|
||||
aq_nic->aq_ptp = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1168,20 +1416,44 @@ int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!aq_nic->aq_fw_ops->enable_ptp) {
|
||||
if (a1_ptp) {
|
||||
if (!aq_nic->aq_fw_ops->enable_ptp) {
|
||||
aq_nic->aq_ptp = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* PTP requires at least 1 free irq vector for itself */
|
||||
if (aq_nic->irqvecs <= AQ_HW_PTP_IRQS) {
|
||||
netdev_warn(aq_nic->ndev,
|
||||
"Disabling PTP due to insufficient number of available IRQ vectors.\n");
|
||||
aq_nic->aq_ptp = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
hw_atl_utils_mpi_read_stats(aq_nic->aq_hw, &mbox);
|
||||
if (a1_ptp) {
|
||||
hw_atl_utils_mpi_read_stats(aq_nic->aq_hw, &mbox);
|
||||
if (!(mbox.info.caps_ex & BIT(CAPS_EX_PHY_PTP_EN))) {
|
||||
aq_nic->aq_ptp = NULL;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
memset(&mbox, 0, sizeof(mbox));
|
||||
|
||||
if (!(mbox.info.caps_ex & BIT(CAPS_EX_PHY_PTP_EN))) {
|
||||
aq_nic->aq_ptp = NULL;
|
||||
return 0;
|
||||
if (a2_ptp) {
|
||||
mbox.info.ptp_offset.ingress_100 = HW_ATL2_PTP_OFFSET_INGRESS_100;
|
||||
mbox.info.ptp_offset.egress_100 = HW_ATL2_PTP_OFFSET_EGRESS_100;
|
||||
mbox.info.ptp_offset.ingress_1000 = HW_ATL2_PTP_OFFSET_INGRESS_1000;
|
||||
mbox.info.ptp_offset.egress_1000 = HW_ATL2_PTP_OFFSET_EGRESS_1000;
|
||||
mbox.info.ptp_offset.ingress_2500 = HW_ATL2_PTP_OFFSET_INGRESS_2500;
|
||||
mbox.info.ptp_offset.egress_2500 = HW_ATL2_PTP_OFFSET_EGRESS_2500;
|
||||
mbox.info.ptp_offset.ingress_5000 = HW_ATL2_PTP_OFFSET_INGRESS_5000;
|
||||
mbox.info.ptp_offset.egress_5000 = HW_ATL2_PTP_OFFSET_EGRESS_5000;
|
||||
mbox.info.ptp_offset.ingress_10000 = HW_ATL2_PTP_OFFSET_INGRESS_10000;
|
||||
mbox.info.ptp_offset.egress_10000 = HW_ATL2_PTP_OFFSET_EGRESS_10000;
|
||||
}
|
||||
}
|
||||
|
||||
aq_ptp_offset_init(&mbox.info.ptp_offset);
|
||||
|
||||
aq_ptp = kzalloc_obj(*aq_ptp);
|
||||
if (!aq_ptp) {
|
||||
err = -ENOMEM;
|
||||
|
|
@ -1190,10 +1462,13 @@ int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec)
|
|||
|
||||
aq_ptp->aq_nic = aq_nic;
|
||||
aq_ptp->a1_ptp = a1_ptp;
|
||||
aq_ptp->a2_ptp = a2_ptp;
|
||||
|
||||
spin_lock_init(&aq_ptp->ptp_lock);
|
||||
spin_lock_init(&aq_ptp->ptp_ring_lock);
|
||||
mutex_init(&aq_ptp->ptp_filter_lock);
|
||||
|
||||
aq_ptp_offset_init(aq_ptp, &mbox.info.ptp_offset);
|
||||
aq_ptp->ptp_info = aq_ptp_clock;
|
||||
aq_ptp_gpio_init(&aq_ptp->ptp_info, &mbox.info);
|
||||
clock = ptp_clock_register(&aq_ptp->ptp_info, &aq_nic->ndev->dev);
|
||||
|
|
@ -1210,22 +1485,34 @@ int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec)
|
|||
|
||||
netif_napi_add(aq_nic_get_ndev(aq_nic), &aq_ptp->napi, aq_ptp_poll);
|
||||
|
||||
aq_ptp->idx_vector = idx_vec;
|
||||
aq_ptp->idx_ptp_vector = idx_ptp_vec;
|
||||
|
||||
aq_nic->aq_ptp = aq_ptp;
|
||||
|
||||
/* enable ptp counter */
|
||||
aq_ptp->ptp_clock_sel = ATL_TSG_CLOCK_SEL_0;
|
||||
aq_utils_obj_set(&aq_nic->aq_hw->flags, AQ_HW_PTP_AVAILABLE);
|
||||
mutex_lock(&aq_nic->fwreq_mutex);
|
||||
aq_nic->aq_fw_ops->enable_ptp(aq_nic->aq_hw, 1);
|
||||
aq_ptp_clock_init(aq_nic);
|
||||
mutex_unlock(&aq_nic->fwreq_mutex);
|
||||
if (a1_ptp) {
|
||||
mutex_lock(&aq_nic->fwreq_mutex);
|
||||
aq_nic->aq_fw_ops->enable_ptp(aq_nic->aq_hw, 1);
|
||||
mutex_unlock(&aq_nic->fwreq_mutex);
|
||||
}
|
||||
if (a2_ptp)
|
||||
aq_nic->aq_hw_ops->enable_ptp(aq_nic->aq_hw, aq_ptp->ptp_clock_sel, 1);
|
||||
|
||||
INIT_DELAYED_WORK(&aq_ptp->poll_sync, &aq_ptp_poll_sync_work_cb);
|
||||
aq_ptp->eth_type_filter.location =
|
||||
aq_nic_reserve_filter(aq_nic, aq_rx_filter_ethertype);
|
||||
aq_ptp->udp_filter.location =
|
||||
aq_nic_reserve_filter(aq_nic, aq_rx_filter_ethertype);
|
||||
|
||||
for (i = 0; i < PTP_UDP_FILTERS_CNT; i++) {
|
||||
aq_ptp->udp_filter[i].location =
|
||||
aq_nic_reserve_filter(aq_nic, aq_rx_filter_l3l4);
|
||||
}
|
||||
|
||||
aq_ptp_clock_init(aq_nic, AQ_PTP_FIRST_INIT);
|
||||
netdev_info(aq_nic->ndev,
|
||||
"Enable PTP Support. %d GPIO(s)\n",
|
||||
aq_ptp->ptp_info.n_pins);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
@ -1244,31 +1531,47 @@ void aq_ptp_unregister(struct aq_nic_s *aq_nic)
|
|||
if (!aq_ptp)
|
||||
return;
|
||||
|
||||
ptp_clock_unregister(aq_ptp->ptp_clock);
|
||||
if (aq_ptp->ptp_clock) {
|
||||
ptp_clock_unregister(aq_ptp->ptp_clock);
|
||||
aq_ptp->ptp_clock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void aq_ptp_free(struct aq_nic_s *aq_nic)
|
||||
{
|
||||
struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
|
||||
int i;
|
||||
|
||||
if (!aq_ptp)
|
||||
return;
|
||||
|
||||
cancel_delayed_work_sync(&aq_ptp->poll_sync);
|
||||
|
||||
/* disable ptp */
|
||||
if (aq_ptp->a1_ptp) {
|
||||
mutex_lock(&aq_nic->fwreq_mutex);
|
||||
aq_nic->aq_fw_ops->enable_ptp(aq_nic->aq_hw, 0);
|
||||
mutex_unlock(&aq_nic->fwreq_mutex);
|
||||
}
|
||||
|
||||
if (aq_ptp->a2_ptp)
|
||||
aq_nic->aq_hw_ops->enable_ptp(aq_nic->aq_hw,
|
||||
aq_ptp->ptp_clock_sel, 0);
|
||||
|
||||
aq_nic_release_filter(aq_nic, aq_rx_filter_ethertype,
|
||||
aq_ptp->eth_type_filter.location);
|
||||
aq_nic_release_filter(aq_nic, aq_rx_filter_l3l4,
|
||||
aq_ptp->udp_filter.location);
|
||||
cancel_delayed_work_sync(&aq_ptp->poll_sync);
|
||||
/* disable ptp */
|
||||
mutex_lock(&aq_nic->fwreq_mutex);
|
||||
aq_nic->aq_fw_ops->enable_ptp(aq_nic->aq_hw, 0);
|
||||
mutex_unlock(&aq_nic->fwreq_mutex);
|
||||
for (i = 0; i < PTP_UDP_FILTERS_CNT; i++)
|
||||
aq_nic_release_filter(aq_nic, aq_rx_filter_l3l4,
|
||||
aq_ptp->udp_filter[i].location);
|
||||
|
||||
mutex_destroy(&aq_ptp->ptp_filter_lock);
|
||||
kfree(aq_ptp->ptp_info.pin_config);
|
||||
aq_ptp->ptp_info.pin_config = NULL;
|
||||
|
||||
netif_napi_del(&aq_ptp->napi);
|
||||
kfree(aq_ptp);
|
||||
aq_utils_obj_clear(&aq_nic->aq_hw->flags, AQ_HW_PTP_AVAILABLE);
|
||||
aq_nic->aq_ptp = NULL;
|
||||
kfree(aq_ptp);
|
||||
}
|
||||
|
||||
struct ptp_clock *aq_ptp_get_ptp_clock(struct aq_ptp_s *aq_ptp)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,12 @@
|
|||
|
||||
#include "aq_ring.h"
|
||||
|
||||
enum aq_ptp_state {
|
||||
AQ_PTP_NO_LINK = 0,
|
||||
AQ_PTP_FIRST_INIT = 1,
|
||||
AQ_PTP_LINK_UP = 2,
|
||||
};
|
||||
|
||||
#define PTP_8TC_RING_IDX 8
|
||||
#define PTP_4TC_RING_IDX 16
|
||||
#define PTP_HWST_RING_IDX 31
|
||||
|
|
@ -32,7 +38,7 @@ static inline unsigned int aq_ptp_ring_idx(const enum aq_tc_mode tc_mode)
|
|||
#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
|
||||
|
||||
/* Common functions */
|
||||
int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec);
|
||||
int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_ptp_vec);
|
||||
|
||||
void aq_ptp_unregister(struct aq_nic_s *aq_nic);
|
||||
void aq_ptp_free(struct aq_nic_s *aq_nic);
|
||||
|
|
@ -52,7 +58,8 @@ void aq_ptp_service_task(struct aq_nic_s *aq_nic);
|
|||
|
||||
void aq_ptp_tm_offset_set(struct aq_nic_s *aq_nic, unsigned int mbps);
|
||||
|
||||
void aq_ptp_clock_init(struct aq_nic_s *aq_nic);
|
||||
void aq_ptp_clock_init(struct aq_nic_s *aq_nic, enum aq_ptp_state state);
|
||||
void aq_ptp_tx_skb_drop_head(struct aq_nic_s *aq_nic);
|
||||
|
||||
/* Traffic processing functions */
|
||||
int aq_ptp_xmit(struct aq_nic_s *aq_nic, struct sk_buff *skb);
|
||||
|
|
@ -80,7 +87,7 @@ u64 *aq_ptp_get_stats(struct aq_nic_s *aq_nic, u64 *data);
|
|||
|
||||
#else
|
||||
|
||||
static inline int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec)
|
||||
static inline int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_ptp_vec)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -122,7 +129,9 @@ static inline void aq_ptp_ring_deinit(struct aq_nic_s *aq_nic) {}
|
|||
static inline void aq_ptp_service_task(struct aq_nic_s *aq_nic) {}
|
||||
static inline void aq_ptp_tm_offset_set(struct aq_nic_s *aq_nic,
|
||||
unsigned int mbps) {}
|
||||
static inline void aq_ptp_clock_init(struct aq_nic_s *aq_nic) {}
|
||||
static inline void aq_ptp_clock_init(struct aq_nic_s *aq_nic,
|
||||
enum aq_ptp_state state) {}
|
||||
static inline void aq_ptp_tx_skb_drop_head(struct aq_nic_s *aq_nic) {}
|
||||
static inline int aq_ptp_xmit(struct aq_nic_s *aq_nic, struct sk_buff *skb)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
|
|
|
|||
|
|
@ -311,6 +311,30 @@ bool aq_ring_tx_clean(struct aq_ring_s *self)
|
|||
if (likely(!buff->is_eop))
|
||||
goto out;
|
||||
|
||||
if (unlikely(buff->request_ts) &&
|
||||
self->aq_nic->aq_hw_ops->hw_ring_tx_ptp_get_ts) {
|
||||
u64 ts = self->aq_nic->aq_hw_ops->hw_ring_tx_ptp_get_ts(self);
|
||||
|
||||
if (!ts) {
|
||||
if (time_after(jiffies,
|
||||
self->ptp_ts_deadline)) {
|
||||
/* Timeout: drain skb_ring head to
|
||||
* keep in sync with buff_ring
|
||||
*/
|
||||
aq_ptp_tx_skb_drop_head(self->aq_nic);
|
||||
buff->request_ts = 0;
|
||||
dev_kfree_skb_any(buff->skb);
|
||||
buff->skb = NULL;
|
||||
goto out;
|
||||
} else {
|
||||
buff->is_mapped = 0;
|
||||
buff->pa = 0U;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
aq_ptp_tx_hwtstamp(self->aq_nic, ts);
|
||||
}
|
||||
if (buff->skb) {
|
||||
u64_stats_update_begin(&self->stats.tx.syncp);
|
||||
++self->stats.tx.packets;
|
||||
|
|
@ -570,7 +594,7 @@ static int __aq_ring_rx_clean(struct aq_ring_s *self, struct napi_struct *napi,
|
|||
self->hw_head);
|
||||
|
||||
if (unlikely(!is_rsc_completed) ||
|
||||
frag_cnt > MAX_SKB_FRAGS) {
|
||||
frag_cnt > MAX_SKB_FRAGS) {
|
||||
err = 0;
|
||||
goto err_exit;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,9 @@ struct __packed aq_ring_buff_s {
|
|||
u32 is_error:1;
|
||||
u32 is_vlan:1;
|
||||
u32 is_lro:1;
|
||||
u32 rsvd3:3;
|
||||
u32 request_ts:1;
|
||||
u32 clk_sel:1;
|
||||
u32 rsvd3:1;
|
||||
u16 eop_index;
|
||||
u16 rsvd4;
|
||||
};
|
||||
|
|
@ -152,6 +154,7 @@ struct aq_ring_s {
|
|||
struct bpf_prog *xdp_prog;
|
||||
enum atl_ring_type ring_type;
|
||||
struct xdp_rxq_info xdp_rxq;
|
||||
unsigned long ptp_ts_deadline;
|
||||
};
|
||||
|
||||
struct aq_ring_param_s {
|
||||
|
|
|
|||
|
|
@ -736,6 +736,15 @@ int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self, struct aq_ring_s *ring,
|
|||
txd->ctl |= HW_ATL_B0_TXD_CTL_CMD_WB;
|
||||
is_gso = false;
|
||||
is_vlan = false;
|
||||
|
||||
if (ATL_HW_IS_CHIP_FEATURE(self, ANTIGUA) &&
|
||||
unlikely(buff->request_ts)) {
|
||||
txd->ctl |= AQ_HW_TXD_CTL_TS_EN;
|
||||
if (buff->clk_sel != ATL_TSG_CLOCK_SEL_1)
|
||||
txd->ctl |= AQ_HW_TXD_CTL_TS_TSG0;
|
||||
/* The only DD+TS is required */
|
||||
txd->ctl &= ~HW_ATL_B0_TXD_CTL_CMD_WB;
|
||||
}
|
||||
}
|
||||
}
|
||||
ring->sw_tail = aq_ring_next_dx(ring, ring->sw_tail);
|
||||
|
|
@ -1323,8 +1332,8 @@ static int hw_atl_b0_adj_clock_freq(struct aq_hw_s *self, s32 ppb)
|
|||
return self->aq_fw_ops->send_fw_request(self, &fwreq, size);
|
||||
}
|
||||
|
||||
static int hw_atl_b0_gpio_pulse(struct aq_hw_s *self, u32 index,
|
||||
u64 start, u32 period)
|
||||
static int hw_atl_b0_gpio_pulse(struct aq_hw_s *self, u32 index, u32 clk_sel,
|
||||
u64 start, u32 period, u32 hightime)
|
||||
{
|
||||
struct hw_fw_request_iface fwreq;
|
||||
size_t size;
|
||||
|
|
@ -1342,7 +1351,7 @@ static int hw_atl_b0_gpio_pulse(struct aq_hw_s *self, u32 index,
|
|||
}
|
||||
|
||||
static int hw_atl_b0_extts_gpio_enable(struct aq_hw_s *self, u32 index,
|
||||
u32 enable)
|
||||
u32 channel, int enable)
|
||||
{
|
||||
/* Enable/disable Sync1588 GPIO Timestamping */
|
||||
aq_phy_write_reg(self, MDIO_MMD_PCS, 0xc611, enable ? 0x71 : 0);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -7,6 +7,18 @@
|
|||
#define HW_ATL2_H
|
||||
|
||||
#include "aq_common.h"
|
||||
#define HW_ATL2_RX_TS_SIZE 8
|
||||
|
||||
#define HW_ATL2_PTP_OFFSET_INGRESS_100 768
|
||||
#define HW_ATL2_PTP_OFFSET_EGRESS_100 336
|
||||
#define HW_ATL2_PTP_OFFSET_INGRESS_1000 510
|
||||
#define HW_ATL2_PTP_OFFSET_EGRESS_1000 105
|
||||
#define HW_ATL2_PTP_OFFSET_INGRESS_2500 2447
|
||||
#define HW_ATL2_PTP_OFFSET_EGRESS_2500 634
|
||||
#define HW_ATL2_PTP_OFFSET_INGRESS_5000 1426
|
||||
#define HW_ATL2_PTP_OFFSET_EGRESS_5000 361
|
||||
#define HW_ATL2_PTP_OFFSET_INGRESS_10000 997
|
||||
#define HW_ATL2_PTP_OFFSET_EGRESS_10000 203
|
||||
|
||||
extern const struct aq_hw_caps_s hw_atl2_caps_aqc113;
|
||||
extern const struct aq_hw_caps_s hw_atl2_caps_aqc115c;
|
||||
|
|
|
|||
|
|
@ -27,8 +27,11 @@
|
|||
#define HW_ATL2_INT_MASK (0xFFFFFFFFU)
|
||||
|
||||
#define HW_ATL2_TXBUF_MAX 128U
|
||||
#define HW_ATL2_RXBUF_MAX 192U
|
||||
#define HW_ATL2_PTP_TXBUF_SIZE 8U
|
||||
|
||||
/* hw_atl2 on-chip RX packet buffer available for data TCs */
|
||||
#define HW_ATL2_RXBUF_MAX 172U
|
||||
#define HW_ATL2_PTP_RXBUF_SIZE 16U
|
||||
#define HW_ATL2_RSS_REDIRECTION_MAX 64U
|
||||
|
||||
#define HW_ATL2_TC_MAX 8U
|
||||
|
|
@ -84,6 +87,19 @@ enum HW_ATL2_RPF_ART_INDEX {
|
|||
HW_ATL_VLAN_MAX_FILTERS,
|
||||
};
|
||||
|
||||
#define HW_ATL2_RPF_L3_CMD_EN BIT(0)
|
||||
#define HW_ATL2_RPF_L3_CMD_SA_EN BIT(1)
|
||||
#define HW_ATL2_RPF_L3_CMD_DA_EN BIT(2)
|
||||
#define HW_ATL2_RPF_L3_CMD_PROTO_EN BIT(3)
|
||||
#define HW_ATL2_RPF_L3_V6_CMD_EN BIT(0x10)
|
||||
#define HW_ATL2_RPF_L3_V6_CMD_SA_EN BIT(0x11)
|
||||
#define HW_ATL2_RPF_L3_V6_CMD_DA_EN BIT(0x12)
|
||||
#define HW_ATL2_RPF_L3_V6_CMD_PROTO_EN BIT(0x13)
|
||||
#define HW_ATL2_RPF_L4_CMD_EN BIT(0)
|
||||
#define HW_ATL2_RPF_L4_CMD_DP_EN BIT(1)
|
||||
#define HW_ATL2_RPF_L4_CMD_SP_EN BIT(2)
|
||||
#define HW_ATL2_ART_TOTAL_ENTRIES 128
|
||||
|
||||
#define HW_ATL2_ACTION(ACTION, RSS, INDEX, VALID) \
|
||||
((((ACTION) & 0x3U) << 8) | \
|
||||
(((RSS) & 0x1U) << 7) | \
|
||||
|
|
@ -94,6 +110,13 @@ enum HW_ATL2_RPF_ART_INDEX {
|
|||
#define HW_ATL2_ACTION_DISABLE HW_ATL2_ACTION(0, 0, 0, 0)
|
||||
#define HW_ATL2_ACTION_ASSIGN_QUEUE(QUEUE) HW_ATL2_ACTION(1, 0, (QUEUE), 1)
|
||||
#define HW_ATL2_ACTION_ASSIGN_TC(TC) HW_ATL2_ACTION(1, 1, (TC), 1)
|
||||
#define HW_ATL2_RPF_L3L4_FILTERS 8
|
||||
#define HW_ATL2_RPF_L3V4_FILTERS 8
|
||||
#define HW_ATL2_RPF_L3V6_FILTERS 6
|
||||
#define HW_ATL2_RPF_L4_FILTERS 8
|
||||
#define HW_ATL2_RPF_VLAN_FILTERS 16
|
||||
#define HW_ATL2_RPF_ETYPE_FILTERS 16
|
||||
#define HW_ATL2_RPF_ETYPE_TAGS 7
|
||||
|
||||
enum HW_ATL2_RPF_RSS_HASH_TYPE {
|
||||
HW_ATL2_RPF_RSS_HASH_TYPE_NONE = 0,
|
||||
|
|
@ -119,9 +142,54 @@ enum HW_ATL2_RPF_RSS_HASH_TYPE {
|
|||
|
||||
#define HW_ATL_MCAST_FLT_ANY_TO_HOST 0x00010FFFU
|
||||
|
||||
struct hw_atl2_l3_filter {
|
||||
u8 proto;
|
||||
u8 usage;
|
||||
u32 cmd;
|
||||
u32 srcip[4];
|
||||
u32 dstip[4];
|
||||
};
|
||||
|
||||
struct hw_atl2_l4_filter {
|
||||
u8 usage;
|
||||
u32 cmd;
|
||||
u16 sport;
|
||||
u16 dport;
|
||||
};
|
||||
|
||||
struct hw_atl2_l3l4_filter {
|
||||
s8 l3_index;
|
||||
s8 l4_index;
|
||||
u8 ipv6;
|
||||
};
|
||||
|
||||
struct hw_atl2_tag_policy {
|
||||
u16 action;
|
||||
u16 usage;
|
||||
};
|
||||
|
||||
struct hw_atl2_priv {
|
||||
struct hw_atl2_l3_filter l3_v4_filters[HW_ATL2_RPF_L3L4_FILTERS];
|
||||
struct hw_atl2_l3_filter l3_v6_filters[HW_ATL2_RPF_L3L4_FILTERS];
|
||||
struct hw_atl2_l4_filter l4_filters[HW_ATL2_RPF_L3L4_FILTERS];
|
||||
struct hw_atl2_l3l4_filter l3l4_filters[HW_ATL2_RPF_L3L4_FILTERS];
|
||||
struct hw_atl2_tag_policy etype_policy[HW_ATL2_RPF_ETYPE_FILTERS];
|
||||
struct statistics_s last_stats;
|
||||
unsigned int art_base_index;
|
||||
unsigned int art_count;
|
||||
unsigned int l2_filters_base_index;
|
||||
unsigned int l2_filter_count;
|
||||
unsigned int etype_filter_base_index;
|
||||
unsigned int etype_filter_count;
|
||||
unsigned int etype_filter_tag_top;
|
||||
unsigned int vlan_filter_base_index;
|
||||
unsigned int vlan_filter_count;
|
||||
unsigned int l3_v4_filter_base_index;
|
||||
unsigned int l3_v4_filter_count;
|
||||
unsigned int l3_v6_filter_base_index;
|
||||
unsigned int l3_v6_filter_count;
|
||||
unsigned int l4_filter_base_index;
|
||||
unsigned int l4_filter_count;
|
||||
};
|
||||
|
||||
#endif /* HW_ATL2_INTERNAL_H */
|
||||
|
|
|
|||
|
|
@ -7,6 +7,13 @@
|
|||
#include "hw_atl2_llh_internal.h"
|
||||
#include "aq_hw_utils.h"
|
||||
|
||||
u32 hw_atl2_phi_ext_tag_get(struct aq_hw_s *aq_hw)
|
||||
{
|
||||
return aq_hw_read_reg_bit(aq_hw, HW_ATL2_PHI_EXT_TAG_EN_ADR,
|
||||
HW_ATL2_PHI_EXT_TAG_EN_MSK,
|
||||
HW_ATL2_PHI_EXT_TAG_EN_SHIFT);
|
||||
}
|
||||
|
||||
void hw_atl2_rpf_redirection_table2_select_set(struct aq_hw_s *aq_hw,
|
||||
u32 select)
|
||||
{
|
||||
|
|
@ -66,6 +73,266 @@ void hw_atl2_rpf_vlan_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter)
|
|||
tag);
|
||||
}
|
||||
|
||||
void hw_atl2_rpf_etht_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter)
|
||||
{
|
||||
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_ET_TAG_ADR(filter),
|
||||
HW_ATL2_RPF_ET_TAG_MSK,
|
||||
HW_ATL2_RPF_ET_TAG_SHIFT, tag);
|
||||
}
|
||||
|
||||
u32 hw_atl2_rpf_etht_flr_tag_get(struct aq_hw_s *aq_hw, u32 filter)
|
||||
{
|
||||
return aq_hw_read_reg_bit(aq_hw, HW_ATL2_RPF_ET_TAG_ADR(filter),
|
||||
HW_ATL2_RPF_ET_TAG_MSK,
|
||||
HW_ATL2_RPF_ET_TAG_SHIFT);
|
||||
}
|
||||
|
||||
void hw_atl2_rpf_l3_v4_dest_addr_set(struct aq_hw_s *aq_hw, u32 filter, u32 val)
|
||||
{
|
||||
u32 addr_set = 6 + ((filter < 4) ? 0 : 1);
|
||||
u32 dword = filter % 4;
|
||||
|
||||
aq_hw_write_reg(aq_hw, HW_ATL2_RPF_L3_DA_DW_ADR(addr_set, dword), val);
|
||||
}
|
||||
|
||||
void hw_atl2_rpf_l3_v4_src_addr_set(struct aq_hw_s *aq_hw, u32 filter, u32 val)
|
||||
{
|
||||
u32 addr_set = 6 + ((filter < 4) ? 0 : 1);
|
||||
u32 dword = filter % 4;
|
||||
|
||||
aq_hw_write_reg(aq_hw, HW_ATL2_RPF_L3_SA_DW_ADR(addr_set, dword), val);
|
||||
}
|
||||
|
||||
void hw_atl2_rpf_l3_v6_dest_addr_set(struct aq_hw_s *aq_hw, u8 location,
|
||||
u32 *ipv6_dst)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
aq_hw_write_reg(aq_hw,
|
||||
HW_ATL2_RPF_L3_DA_DW_ADR(location, 3 - i),
|
||||
ipv6_dst[i]);
|
||||
}
|
||||
|
||||
void hw_atl2_rpf_l3_v6_src_addr_set(struct aq_hw_s *aq_hw, u8 location,
|
||||
u32 *ipv6_src)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
aq_hw_write_reg(aq_hw,
|
||||
HW_ATL2_RPF_L3_SA_DW_ADR(location, 3 - i),
|
||||
ipv6_src[i]);
|
||||
}
|
||||
|
||||
void hw_atl2_rpf_l3_v4_cmd_set(struct aq_hw_s *aq_hw, u32 val, u32 filter)
|
||||
{
|
||||
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_L3_V4_CMD_ADR(filter),
|
||||
HW_ATL2_RPF_L3_V4_CMD_MSK,
|
||||
HW_ATL2_RPF_L3_V4_CMD_SHIFT, val);
|
||||
}
|
||||
|
||||
void hw_atl2_rpf_l3_v6_cmd_set(struct aq_hw_s *aq_hw, u32 val, u32 filter)
|
||||
{
|
||||
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_L3_V6_CMD_ADR(filter),
|
||||
HW_ATL2_RPF_L3_V6_CMD_MSK,
|
||||
HW_ATL2_RPF_L3_V6_CMD_SHIFT, val);
|
||||
}
|
||||
|
||||
void hw_atl2_rpf_l3_v6_v4_select_set(struct aq_hw_s *aq_hw, u32 val)
|
||||
{
|
||||
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_L3_V6_V4_SELECT_ADR,
|
||||
HW_ATL2_RPF_L3_V6_V4_SELECT_MSK,
|
||||
HW_ATL2_RPF_L3_V6_V4_SELECT_SHIFT, val);
|
||||
}
|
||||
|
||||
void hw_atl2_rpf_l3_v4_tag_set(struct aq_hw_s *aq_hw, u32 val, u32 filter)
|
||||
{
|
||||
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_L3_V4_TAG_ADR(filter),
|
||||
HW_ATL2_RPF_L3_V4_TAG_MSK,
|
||||
HW_ATL2_RPF_L3_V4_TAG_SHIFT, val);
|
||||
}
|
||||
|
||||
void hw_atl2_rpf_l3_v6_tag_set(struct aq_hw_s *aq_hw, u32 val, u32 filter)
|
||||
{
|
||||
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_L3_V6_TAG_ADR(filter),
|
||||
HW_ATL2_RPF_L3_V6_TAG_MSK,
|
||||
HW_ATL2_RPF_L3_V6_TAG_SHIFT, val);
|
||||
}
|
||||
|
||||
void hw_atl2_rpf_l4_tag_set(struct aq_hw_s *aq_hw, u32 val, u32 filter)
|
||||
{
|
||||
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_L4_TAG_ADR(filter),
|
||||
HW_ATL2_RPF_L4_TAG_MSK,
|
||||
HW_ATL2_RPF_L4_TAG_SHIFT, val);
|
||||
}
|
||||
|
||||
void hw_atl2_rpf_l4_cmd_set(struct aq_hw_s *aq_hw, u32 val, u32 filter)
|
||||
{
|
||||
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_L4_CMD_ADR(filter),
|
||||
HW_ATL2_RPF_L4_CMD_MSK,
|
||||
HW_ATL2_RPF_L4_CMD_SHIFT, val);
|
||||
}
|
||||
|
||||
/* tsg */
|
||||
static void hw_atl2_clock_modif_value_set(struct aq_hw_s *aq_hw,
|
||||
u32 clock_sel, u64 ns)
|
||||
{
|
||||
aq_hw_write_reg64(aq_hw,
|
||||
HW_ATL2_TSG_REG_ADR(clock_sel, CLOCK_MODIF_VAL_LSW),
|
||||
ns);
|
||||
}
|
||||
|
||||
void hw_atl2_tsg_clock_en(struct aq_hw_s *aq_hw,
|
||||
u32 clock_sel, u32 clock_enable)
|
||||
{
|
||||
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TSG_REG_ADR(clock_sel, CLOCK_CFG),
|
||||
HW_ATL2_TSG_CLOCK_EN_MSK,
|
||||
HW_ATL2_TSG_CLOCK_EN_SHIFT,
|
||||
clock_enable);
|
||||
}
|
||||
|
||||
void hw_atl2_tsg_clock_reset(struct aq_hw_s *aq_hw, u32 clock_sel)
|
||||
{
|
||||
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TSG_REG_ADR(clock_sel, CLOCK_CFG),
|
||||
HW_ATL2_TSG_SYNC_RESET_MSK,
|
||||
HW_ATL2_TSG_SYNC_RESET_SHIFT, 1);
|
||||
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TSG_REG_ADR(clock_sel, CLOCK_CFG),
|
||||
HW_ATL2_TSG_SYNC_RESET_MSK,
|
||||
HW_ATL2_TSG_SYNC_RESET_SHIFT, 0);
|
||||
}
|
||||
|
||||
u64 hw_atl2_tsg_clock_read(struct aq_hw_s *aq_hw, u32 clock_sel)
|
||||
{
|
||||
return aq_hw_read_reg64(aq_hw,
|
||||
HW_ATL2_TSG_REG_ADR(clock_sel,
|
||||
READ_CUR_NS_LSW));
|
||||
}
|
||||
|
||||
void hw_atl2_tsg_clock_add(struct aq_hw_s *aq_hw, u32 clock_sel, u64 ns)
|
||||
{
|
||||
hw_atl2_clock_modif_value_set(aq_hw, clock_sel, ns);
|
||||
aq_hw_write_reg(aq_hw,
|
||||
HW_ATL2_TSG_REG_ADR(clock_sel, CLOCK_MODIF_CTRL),
|
||||
HW_ATL2_TSG_ADD_COUNTER_MSK);
|
||||
}
|
||||
|
||||
void hw_atl2_tsg_clock_sub(struct aq_hw_s *aq_hw, u32 clock_sel, u64 ns)
|
||||
{
|
||||
hw_atl2_clock_modif_value_set(aq_hw, clock_sel, ns);
|
||||
aq_hw_write_reg(aq_hw,
|
||||
HW_ATL2_TSG_REG_ADR(clock_sel, CLOCK_MODIF_CTRL),
|
||||
HW_ATL2_TSG_SUBTRACT_COUNTER_MSK);
|
||||
}
|
||||
|
||||
void hw_atl2_tsg_clock_increment_set(struct aq_hw_s *aq_hw,
|
||||
u32 clock_sel, u32 ns, u32 fns)
|
||||
{
|
||||
u32 nsfns = (ns & 0xff) | (fns & 0xffffff00);
|
||||
|
||||
aq_hw_write_reg(aq_hw,
|
||||
HW_ATL2_TSG_REG_ADR(clock_sel, CLOCK_INC_CFG),
|
||||
nsfns);
|
||||
aq_hw_write_reg(aq_hw,
|
||||
HW_ATL2_TSG_REG_ADR(clock_sel, CLOCK_MODIF_CTRL),
|
||||
HW_ATL2_TSG_LOAD_INC_CFG_MSK);
|
||||
}
|
||||
|
||||
void hw_atl2_tpb_tps_highest_priority_tc_enable_set(struct aq_hw_s *aq_hw,
|
||||
u32 tps_highest_prio_tc_en)
|
||||
{
|
||||
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TPB_HIGHEST_PRIO_TC_EN_ADR,
|
||||
HW_ATL2_TPB_HIGHEST_PRIO_TC_EN_MSK,
|
||||
HW_ATL2_TPB_HIGHEST_PRIO_TC_EN_SHIFT,
|
||||
tps_highest_prio_tc_en);
|
||||
}
|
||||
|
||||
void hw_atl2_tpb_tps_highest_priority_tc_set(struct aq_hw_s *aq_hw,
|
||||
u32 tps_highest_prio_tc)
|
||||
{
|
||||
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TPB_HIGHEST_PRIO_TC_ADR,
|
||||
HW_ATL2_TPB_HIGHEST_PRIO_TC_MSK,
|
||||
HW_ATL2_TPB_HIGHEST_PRIO_TC_SHIFT,
|
||||
tps_highest_prio_tc);
|
||||
}
|
||||
|
||||
void hw_atl2_tsg_gpio_isr_to_host_set(struct aq_hw_s *aq_hw,
|
||||
int on, u32 clock_sel)
|
||||
{
|
||||
aq_hw_write_reg_bit(aq_hw,
|
||||
HW_ATL2_GLOBAL_HIGH_PRIO_INTERRUPT_1_MASK_ADR,
|
||||
clock_sel == 1 ? HW_ATL2_TSG_TSG1_GPIO_INTERRUPT_MSK :
|
||||
HW_ATL2_TSG_TSG0_GPIO_INTERRUPT_MSK,
|
||||
clock_sel == 1 ? HW_ATL2_TSG_TSG1_GPIO_INTERRUPT_SHIFT :
|
||||
HW_ATL2_TSG_TSG0_GPIO_INTERRUPT_SHIFT,
|
||||
!!on);
|
||||
}
|
||||
|
||||
void hw_atl2_tsg_gpio_clear_status(struct aq_hw_s *aq_hw)
|
||||
{
|
||||
aq_hw_read_reg(aq_hw, HW_ATL2_GLOBAL_INTERNAL_ALARMS_1_ADR);
|
||||
}
|
||||
|
||||
void hw_atl2_tsg_gpio_input_event_info_get(struct aq_hw_s *aq_hw,
|
||||
u32 clock_sel,
|
||||
u32 *event_count,
|
||||
u64 *event_ts)
|
||||
{
|
||||
if (event_count)
|
||||
*event_count = aq_hw_read_reg(aq_hw,
|
||||
HW_ATL2_TSG_REG_ADR(clock_sel,
|
||||
EXT_CLK_COUNT));
|
||||
|
||||
if (event_ts)
|
||||
*event_ts = aq_hw_read_reg64(aq_hw,
|
||||
HW_ATL2_TSG_REG_ADR(clock_sel,
|
||||
GPIO_EVENT_TS_LSW));
|
||||
}
|
||||
|
||||
void hw_atl2_tsg_ptp_gpio_gen_pulse(struct aq_hw_s *aq_hw, u32 clk_sel,
|
||||
u64 ts, u32 period, u32 hightime)
|
||||
{
|
||||
u32 val = (HW_ATL2_TSG_GPIO_EVENT_MODE_SET_ON_TIME <<
|
||||
(HW_ATL2_TSG_GPIO_EVENT_MODE_SHIFT -
|
||||
HW_ATL2_TSG_GPIO_OUTPUT_EN_SHIFT)) |
|
||||
(HW_ATL2_TSG_GPIO_GEN_OUTPUT_EN_MSK) |
|
||||
(HW_ATL2_TSG_GPIO_OUTPUT_EN_MSK);
|
||||
|
||||
if (ts != 0) {
|
||||
aq_hw_write_reg64(aq_hw,
|
||||
HW_ATL2_TSG_REG_ADR(clk_sel,
|
||||
GPIO_EVENT_GEN_TS_LSW),
|
||||
ts);
|
||||
|
||||
aq_hw_write_reg64(aq_hw,
|
||||
HW_ATL2_TSG_REG_ADR(clk_sel,
|
||||
GPIO_EVENT_HIGH_TIME_LSW),
|
||||
hightime);
|
||||
|
||||
aq_hw_write_reg64(aq_hw,
|
||||
HW_ATL2_TSG_REG_ADR(clk_sel,
|
||||
GPIO_EVENT_LOW_TIME_LSW),
|
||||
(period - hightime));
|
||||
}
|
||||
|
||||
aq_hw_write_reg_bit(aq_hw,
|
||||
HW_ATL2_TSG_REG_ADR(clk_sel, GPIO_EVENT_GEN_CFG),
|
||||
HW_ATL2_TSG_GPIO_EVENT_MODE_MSK |
|
||||
HW_ATL2_TSG_GPIO_OUTPUT_EN_MSK |
|
||||
HW_ATL2_TSG_GPIO_GEN_OUTPUT_EN_MSK,
|
||||
HW_ATL2_TSG_GPIO_OUTPUT_EN_SHIFT,
|
||||
(!ts ? 0 : val));
|
||||
}
|
||||
|
||||
void hw_atl2_rpf_rx_desc_timestamp_req_set(struct aq_hw_s *aq_hw, u32 request,
|
||||
u32 descriptor)
|
||||
{
|
||||
aq_hw_write_reg_bit(aq_hw,
|
||||
HW_ATL2_RPF_TIMESTAMP_REQ_DESCD_ADR(descriptor),
|
||||
HW_ATL2_RPF_TIMESTAMP_REQ_DESCD_MSK,
|
||||
HW_ATL2_RPF_TIMESTAMP_REQ_DESCD_SHIFT, request);
|
||||
}
|
||||
|
||||
/* TX */
|
||||
|
||||
void hw_atl2_tpb_tx_tc_q_rand_map_en_set(struct aq_hw_s *aq_hw,
|
||||
|
|
@ -93,6 +360,30 @@ void hw_atl2_reg_tx_intr_moder_ctrl_set(struct aq_hw_s *aq_hw,
|
|||
tx_intr_moderation_ctl);
|
||||
}
|
||||
|
||||
void hw_atl2_tdm_tx_desc_timestamp_writeback_en_set(struct aq_hw_s *aq_hw,
|
||||
u32 enable, u32 descriptor)
|
||||
{
|
||||
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TDM_DESCD_TS_WRB_EN_ADR(descriptor),
|
||||
HW_ATL2_TDM_DESCD_TS_WRB_EN_MSK,
|
||||
HW_ATL2_TDM_DESCD_TS_WRB_EN_SHIFT, enable);
|
||||
}
|
||||
|
||||
void hw_atl2_tdm_tx_desc_timestamp_en_set(struct aq_hw_s *aq_hw, u32 enable,
|
||||
u32 descriptor)
|
||||
{
|
||||
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TDM_DESCD_TS_EN_ADR(descriptor),
|
||||
HW_ATL2_TDM_DESCD_TS_EN_MSK,
|
||||
HW_ATL2_TDM_DESCD_TS_EN_SHIFT, enable);
|
||||
}
|
||||
|
||||
void hw_atl2_tdm_tx_desc_avb_en_set(struct aq_hw_s *aq_hw, u32 enable,
|
||||
u32 descriptor)
|
||||
{
|
||||
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TDM_DESCD_AVB_EN_ADR(descriptor),
|
||||
HW_ATL2_TDM_DESCD_AVB_EN_MSK,
|
||||
HW_ATL2_TDM_DESCD_AVB_EN_SHIFT, enable);
|
||||
}
|
||||
|
||||
void hw_atl2_tps_tx_pkt_shed_data_arb_mode_set(struct aq_hw_s *aq_hw,
|
||||
const u32 data_arb_mode)
|
||||
{
|
||||
|
|
@ -122,6 +413,20 @@ void hw_atl2_tps_tx_pkt_shed_tc_data_weight_set(struct aq_hw_s *aq_hw,
|
|||
weight);
|
||||
}
|
||||
|
||||
void hw_atl2_tdm_tx_data_read_req_limit_set(struct aq_hw_s *aq_hw, u32 limit)
|
||||
{
|
||||
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TDM_TX_DATA_RD_REQ_LIMIT_ADR,
|
||||
HW_ATL2_TDM_TX_DATA_RD_REQ_LIMIT_MSK,
|
||||
HW_ATL2_TDM_TX_DATA_RD_REQ_LIMIT_SHIFT, limit);
|
||||
}
|
||||
|
||||
void hw_atl2_tdm_tx_desc_read_req_limit_set(struct aq_hw_s *aq_hw, u32 limit)
|
||||
{
|
||||
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TDM_TX_DESC_RD_REQ_LIMIT_ADR,
|
||||
HW_ATL2_TDM_TX_DESC_RD_REQ_LIMIT_MSK,
|
||||
HW_ATL2_TDM_TX_DESC_RD_REQ_LIMIT_SHIFT, limit);
|
||||
}
|
||||
|
||||
u32 hw_atl2_get_hw_version(struct aq_hw_s *aq_hw)
|
||||
{
|
||||
return aq_hw_read_reg(aq_hw, HW_ATL2_FPGA_VER_ADR);
|
||||
|
|
@ -164,6 +469,13 @@ void hw_atl2_rpf_act_rslvr_section_en_set(struct aq_hw_s *aq_hw, u32 sections)
|
|||
sections);
|
||||
}
|
||||
|
||||
u32 hw_atl2_rpf_act_rslvr_section_en_get(struct aq_hw_s *aq_hw)
|
||||
{
|
||||
return aq_hw_read_reg_bit(aq_hw, HW_ATL2_RPF_REC_TAB_EN_ADR,
|
||||
HW_ATL2_RPF_REC_TAB_EN_MSK,
|
||||
HW_ATL2_RPF_REC_TAB_EN_SHIFT);
|
||||
}
|
||||
|
||||
void hw_atl2_mif_shared_buf_get(struct aq_hw_s *aq_hw, int offset, u32 *data,
|
||||
int len)
|
||||
{
|
||||
|
|
@ -232,3 +544,13 @@ void hw_atl2_mif_host_req_int_clr(struct aq_hw_s *aq_hw, u32 val)
|
|||
return aq_hw_write_reg(aq_hw, HW_ATL2_MCP_HOST_REQ_INT_CLR_ADR,
|
||||
val);
|
||||
}
|
||||
|
||||
void hw_atl2_gpio_special_mode_set(struct aq_hw_s *aq_hw,
|
||||
u32 gpio_special_mode,
|
||||
u32 pin)
|
||||
{
|
||||
aq_hw_write_reg_bit(aq_hw, HW_ATL2_GPIO_PIN_SPEC_MODE_ADR(pin),
|
||||
HW_ATL2_GPIO_PIN_SPEC_MODE_MSK,
|
||||
HW_ATL2_GPIO_PIN_SPEC_MODE_SHIFT,
|
||||
gpio_special_mode);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@
|
|||
|
||||
struct aq_hw_s;
|
||||
|
||||
/* Get Enable usage of extended tags from 32-255. */
|
||||
u32 hw_atl2_phi_ext_tag_get(struct aq_hw_s *aq_hw);
|
||||
|
||||
/* Set TX Interrupt Moderation Control Register */
|
||||
void hw_atl2_reg_tx_intr_moder_ctrl_set(struct aq_hw_s *aq_hw,
|
||||
u32 tx_intr_moderation_ctl,
|
||||
|
|
@ -19,7 +22,7 @@ void hw_atl2_reg_tx_intr_moder_ctrl_set(struct aq_hw_s *aq_hw,
|
|||
void hw_atl2_rpf_redirection_table2_select_set(struct aq_hw_s *aq_hw,
|
||||
u32 select);
|
||||
|
||||
/** Set RSS HASH type */
|
||||
/* Set RSS HASH type */
|
||||
void hw_atl2_rpf_rss_hash_type_set(struct aq_hw_s *aq_hw, u32 rss_hash_type);
|
||||
|
||||
/* set new RPF enable */
|
||||
|
|
@ -37,14 +40,91 @@ void hw_atl2_new_rpf_rss_redir_set(struct aq_hw_s *aq_hw, u32 tc, u32 index,
|
|||
|
||||
/* Set VLAN filter tag */
|
||||
void hw_atl2_rpf_vlan_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter);
|
||||
/* set ethertype filter tag */
|
||||
void hw_atl2_rpf_etht_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter);
|
||||
|
||||
/* get ethertype filter tag */
|
||||
u32 hw_atl2_rpf_etht_flr_tag_get(struct aq_hw_s *aq_hw, u32 filter);
|
||||
|
||||
/* set L3 v4 dest address */
|
||||
void hw_atl2_rpf_l3_v4_dest_addr_set(struct aq_hw_s *aq_hw,
|
||||
u32 filter, u32 val);
|
||||
|
||||
/* set L3 v4 src address */
|
||||
void hw_atl2_rpf_l3_v4_src_addr_set(struct aq_hw_s *aq_hw, u32 filter, u32 val);
|
||||
|
||||
/* set L3 v4 cmd */
|
||||
void hw_atl2_rpf_l3_v4_cmd_set(struct aq_hw_s *aq_hw, u32 val, u32 filter);
|
||||
|
||||
/* set L3 v6 cmd */
|
||||
void hw_atl2_rpf_l3_v6_cmd_set(struct aq_hw_s *aq_hw, u32 val, u32 filter);
|
||||
|
||||
/* set L3 v6 dest address */
|
||||
void hw_atl2_rpf_l3_v6_dest_addr_set(struct aq_hw_s *aq_hw, u8 location,
|
||||
u32 *ipv6_dst);
|
||||
|
||||
/* set L3 v6 src address */
|
||||
void hw_atl2_rpf_l3_v6_src_addr_set(struct aq_hw_s *aq_hw, u8 location,
|
||||
u32 *ipv6_src);
|
||||
|
||||
/* set L3 v6 v4 select */
|
||||
void hw_atl2_rpf_l3_v6_v4_select_set(struct aq_hw_s *aq_hw, u32 val);
|
||||
|
||||
/* set L3 v4 tag */
|
||||
void hw_atl2_rpf_l3_v4_tag_set(struct aq_hw_s *aq_hw, u32 val, u32 filter);
|
||||
|
||||
/* set L3 v6 tag */
|
||||
void hw_atl2_rpf_l3_v6_tag_set(struct aq_hw_s *aq_hw, u32 val, u32 filter);
|
||||
|
||||
/* set L4 cmd */
|
||||
void hw_atl2_rpf_l4_cmd_set(struct aq_hw_s *aq_hw, u32 val, u32 filter);
|
||||
|
||||
/* set L4 tag */
|
||||
void hw_atl2_rpf_l4_tag_set(struct aq_hw_s *aq_hw, u32 val, u32 filter);
|
||||
|
||||
/* set tx random TC-queue mapping enable bit */
|
||||
void hw_atl2_tpb_tx_tc_q_rand_map_en_set(struct aq_hw_s *aq_hw,
|
||||
const u32 tc_q_rand_map_en);
|
||||
|
||||
void hw_atl2_tpb_tps_highest_priority_tc_enable_set(struct aq_hw_s *aq_hw,
|
||||
u32 tps_highest_prio_tc_en);
|
||||
|
||||
void hw_atl2_tpb_tps_highest_priority_tc_set(struct aq_hw_s *aq_hw,
|
||||
u32 tps_highest_prio_tc);
|
||||
|
||||
/* set tx buffer clock gate enable */
|
||||
void hw_atl2_tpb_tx_buf_clk_gate_en_set(struct aq_hw_s *aq_hw, u32 clk_gate_en);
|
||||
|
||||
/* tsg */
|
||||
|
||||
void hw_atl2_tsg_clock_en(struct aq_hw_s *aq_hw, u32 clock_sel,
|
||||
u32 clock_enable);
|
||||
|
||||
void hw_atl2_tsg_clock_reset(struct aq_hw_s *aq_hw, u32 clock_sel);
|
||||
u64 hw_atl2_tsg_clock_read(struct aq_hw_s *aq_hw, u32 clock_sel);
|
||||
void hw_atl2_tsg_clock_add(struct aq_hw_s *aq_hw, u32 clock_sel,
|
||||
u64 ns);
|
||||
void hw_atl2_tsg_clock_sub(struct aq_hw_s *aq_hw, u32 clock_sel,
|
||||
u64 ns);
|
||||
void hw_atl2_tsg_clock_increment_set(struct aq_hw_s *aq_hw, u32 clock_sel,
|
||||
u32 ns, u32 fns);
|
||||
void hw_atl2_tsg_gpio_isr_to_host_set(struct aq_hw_s *aq_hw, int on,
|
||||
u32 clock_sel);
|
||||
void hw_atl2_tsg_gpio_clear_status(struct aq_hw_s *aq_hw);
|
||||
void hw_atl2_tsg_gpio_input_event_info_get(struct aq_hw_s *aq_hw,
|
||||
u32 clock_sel,
|
||||
u32 *event_count,
|
||||
u64 *event_ts);
|
||||
/* Set Rx Descriptor0 Timestamp request */
|
||||
void hw_atl2_rpf_rx_desc_timestamp_req_set(struct aq_hw_s *aq_hw, u32 request,
|
||||
u32 descriptor);
|
||||
/* Set Tx Descriptor Timestamp writeback Enable */
|
||||
void hw_atl2_tdm_tx_desc_timestamp_writeback_en_set(struct aq_hw_s *aq_hw,
|
||||
u32 enable,
|
||||
u32 descriptor);
|
||||
/* Set Tx Descriptor Timestamp enable */
|
||||
void hw_atl2_tdm_tx_desc_timestamp_en_set(struct aq_hw_s *aq_hw, u32 enable,
|
||||
u32 descriptor);
|
||||
void hw_atl2_tps_tx_pkt_shed_data_arb_mode_set(struct aq_hw_s *aq_hw,
|
||||
const u32 data_arb_mode);
|
||||
|
||||
|
|
@ -57,6 +137,15 @@ void hw_atl2_tps_tx_pkt_shed_tc_data_max_credit_set(struct aq_hw_s *aq_hw,
|
|||
void hw_atl2_tps_tx_pkt_shed_tc_data_weight_set(struct aq_hw_s *aq_hw,
|
||||
const u32 tc,
|
||||
const u32 weight);
|
||||
/* Set Tx Descriptor AVB enable */
|
||||
void hw_atl2_tdm_tx_desc_avb_en_set(struct aq_hw_s *aq_hw, u32 enable,
|
||||
u32 descriptor);
|
||||
void hw_atl2_tsg_ptp_gpio_gen_pulse(struct aq_hw_s *aq_hw, u32 clk_sel,
|
||||
u64 ts, u32 period, u32 hightime);
|
||||
|
||||
void hw_atl2_tdm_tx_data_read_req_limit_set(struct aq_hw_s *aq_hw, u32 limit);
|
||||
|
||||
void hw_atl2_tdm_tx_desc_read_req_limit_set(struct aq_hw_s *aq_hw, u32 limit);
|
||||
|
||||
u32 hw_atl2_get_hw_version(struct aq_hw_s *aq_hw);
|
||||
|
||||
|
|
@ -69,6 +158,9 @@ void hw_atl2_rpf_act_rslvr_record_set(struct aq_hw_s *aq_hw, u8 location,
|
|||
/* set enable action resolver section */
|
||||
void hw_atl2_rpf_act_rslvr_section_en_set(struct aq_hw_s *aq_hw, u32 sections);
|
||||
|
||||
/* get enable action resolver section */
|
||||
u32 hw_atl2_rpf_act_rslvr_section_en_get(struct aq_hw_s *aq_hw);
|
||||
|
||||
/* get data from firmware shared input buffer */
|
||||
void hw_atl2_mif_shared_buf_get(struct aq_hw_s *aq_hw, int offset, u32 *data,
|
||||
int len);
|
||||
|
|
@ -99,4 +191,7 @@ u32 hw_atl2_mif_host_req_int_get(struct aq_hw_s *aq_hw);
|
|||
/* clear host interrupt request */
|
||||
void hw_atl2_mif_host_req_int_clr(struct aq_hw_s *aq_hw, u32 val);
|
||||
|
||||
/* Set GPIO Special Mode */
|
||||
void hw_atl2_gpio_special_mode_set(struct aq_hw_s *aq_hw,
|
||||
u32 gpio_special_mode, u32 pin);
|
||||
#endif /* HW_ATL2_LLH_H */
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@
|
|||
|
||||
#ifndef HW_ATL2_LLH_INTERNAL_H
|
||||
#define HW_ATL2_LLH_INTERNAL_H
|
||||
/* RX timestamp_req_desc{D} [1:0] Bitfield Definitions
|
||||
*/
|
||||
#define HW_ATL2_RPF_TIMESTAMP_REQ_DESCD_ADR(descr) (0x00005B08 + (descr) * 0x20)
|
||||
#define HW_ATL2_RPF_TIMESTAMP_REQ_DESCD_MSK 0x00030000
|
||||
#define HW_ATL2_RPF_TIMESTAMP_REQ_DESCD_SHIFT 16
|
||||
|
||||
/* RX pif_rpf_redir_2_en_i Bitfield Definitions
|
||||
* PORT="pif_rpf_redir_2_en_i"
|
||||
|
|
@ -114,7 +119,68 @@
|
|||
#define HW_ATL2_RPF_VL_TAG_WIDTH 4
|
||||
/* default value of bitfield vlan_req_tag0{f}[3:0] */
|
||||
#define HW_ATL2_RPF_VL_TAG_DEFAULT 0x0
|
||||
/* register address for bitfield etype_req_tag0{f}[2:0] */
|
||||
#define HW_ATL2_RPF_ET_TAG_ADR(filter) (0x00005340 + (filter) * 0x4)
|
||||
/* bitmask for bitfield etype_req_tag0{f}[2:0] */
|
||||
#define HW_ATL2_RPF_ET_TAG_MSK 0x00000007
|
||||
/* lower bit position of bitfield etype_req_tag0{f}[2:0] */
|
||||
#define HW_ATL2_RPF_ET_TAG_SHIFT 0
|
||||
/* Lower bit position of bitfield l3_l4_act{F}[2:0] */
|
||||
#define HW_ATL2_RPF_L3_L4_ACTF_SHIFT 16
|
||||
/* Bitmask for bitfield l3_l4_rxq{F}[4:0] */
|
||||
#define HW_ATL2_RPF_L3_L4_RXQF_MSK 0x00001F00u
|
||||
/* Lower bit position of bitfield l3_l4_rxq{F}[4:0] */
|
||||
#define HW_ATL2_RPF_L3_L4_RXQF_SHIFT 8
|
||||
/* Register address for bitfield rpf_l3_v6_sa{F}_dw{D}[1F:0] */
|
||||
#define HW_ATL2_RPF_L3_SA_DW_ADR(filter, dword) \
|
||||
(0x00006400u + (filter) * 0x10 + (dword) * 0x4)
|
||||
|
||||
/* Register address for bitfield rpf_l3_v6_da{F}_dw{D}[1F:0] */
|
||||
#define HW_ATL2_RPF_L3_DA_DW_ADR(filter, dword) \
|
||||
(0x00006480u + (filter) * 0x10 + (dword) * 0x4)
|
||||
|
||||
/* Register address for bitfield rpf_l3_cmd{F}[1F:0] */
|
||||
#define HW_ATL2_RPF_L3_V4_CMD_ADR(filter) (0x00006500u + (filter) * 0x4)
|
||||
/* Bitmask for bitfield rpf_l3_cmd{F}[F:0] */
|
||||
#define HW_ATL2_RPF_L3_V4_CMD_MSK 0x0000FFFFu
|
||||
/* Lower bit position of bitfield rpf_l3_cmd{F}[1F:0] */
|
||||
#define HW_ATL2_RPF_L3_V4_CMD_SHIFT 0
|
||||
/* Register address for bitfield rpf_l3_v6_cmd{F}[1F:0] */
|
||||
#define HW_ATL2_RPF_L3_V6_CMD_ADR(filter) (0x00006500u + (filter) * 0x4)
|
||||
/* Bitmask for bitfield rpf_l3_v6_cmd{F}[F:0] */
|
||||
#define HW_ATL2_RPF_L3_V6_CMD_MSK 0xFF7F0000u
|
||||
/* Lower bit position of bitfield rpf_l3_v6_cmd{F}[1F:0] */
|
||||
#define HW_ATL2_RPF_L3_V6_CMD_SHIFT 0
|
||||
/* Register address for bitfield rpf_l3_v6_cmd{F}[F:0] */
|
||||
#define HW_ATL2_RPF_L3_V6_V4_SELECT_ADR 0x00006500u
|
||||
/* Bitmask for bitfield pif_rpf_l3_v6_v4_select*/
|
||||
#define HW_ATL2_RPF_L3_V6_V4_SELECT_MSK 0x00800000u
|
||||
/* Lower bit position of bitfield pif_rpf_l3_v6_v4_select */
|
||||
#define HW_ATL2_RPF_L3_V6_V4_SELECT_SHIFT 23
|
||||
/* Register address for bitfield rpf_l3_v4_req_tag{F}[2:0] */
|
||||
#define HW_ATL2_RPF_L3_V4_TAG_ADR(filter) (0x00006500u + (filter) * 0x4)
|
||||
/* Bitmask for bitfield rpf_l3_v4_req_tag{F}[2:0] */
|
||||
#define HW_ATL2_RPF_L3_V4_TAG_MSK 0x00000070u
|
||||
/* Lower bit position of bitfield rpf_l3_v4_req_tag{F}[2:0] */
|
||||
#define HW_ATL2_RPF_L3_V4_TAG_SHIFT 4
|
||||
/* Register address for bitfield rpf_l3_v6_req_tag{F}[2:0] */
|
||||
#define HW_ATL2_RPF_L3_V6_TAG_ADR(filter) (0x00006500u + (filter) * 0x4)
|
||||
/* Bitmask for bitfield rpf_l3_v6_req_tag{F}[2:0] */
|
||||
#define HW_ATL2_RPF_L3_V6_TAG_MSK 0x00700000
|
||||
/* Lower bit position of bitfield rpf_l3_v6_req_tag{F}[2:0] */
|
||||
#define HW_ATL2_RPF_L3_V6_TAG_SHIFT 20
|
||||
/* Register address for bitfield rpf_l4_cmd{F}[2:0] */
|
||||
#define HW_ATL2_RPF_L4_CMD_ADR(filter) (0x00006520u + (filter) * 0x4)
|
||||
/* Bitmask for bitfield rpf_l4_cmd{F}[2:0] */
|
||||
#define HW_ATL2_RPF_L4_CMD_MSK 0x00000007u
|
||||
/* Lower bit position of bitfield rpf_l4_cmd{F}[2:0] */
|
||||
#define HW_ATL2_RPF_L4_CMD_SHIFT 0
|
||||
/* Register address for bitfield rpf_l4_tag{F}[2:0] */
|
||||
#define HW_ATL2_RPF_L4_TAG_ADR(filter) (0x00006520u + (filter) * 0x4)
|
||||
/* Bitmask for bitfield rpf_l4_tag{F}[2:0] */
|
||||
#define HW_ATL2_RPF_L4_TAG_MSK 0x00000070u
|
||||
/* Lower bit position of bitfield rpf_l4_tag{F}[2:0] */
|
||||
#define HW_ATL2_RPF_L4_TAG_SHIFT 4
|
||||
/* RX rx_q{Q}_tc_map[2:0] Bitfield Definitions
|
||||
* Preprocessor definitions for the bitfield "rx_q{Q}_tc_map[2:0]".
|
||||
* Parameter: Queue {Q} | bit-level stride | range [0, 31]
|
||||
|
|
@ -131,7 +197,24 @@
|
|||
#define HW_ATL2_RX_Q_TC_MAP_WIDTH 3
|
||||
/* Default value of bitfield rx_q{Q}_tc_map[2:0] */
|
||||
#define HW_ATL2_RX_Q_TC_MAP_DEFAULT 0x0
|
||||
|
||||
/* TX desc{D}_ts_wrb_en Bitfield Definitions
|
||||
*/
|
||||
#define HW_ATL2_TDM_DESCD_TS_WRB_EN_ADR(descriptor) \
|
||||
(0x00007C08 + (descriptor) * 0x40)
|
||||
#define HW_ATL2_TDM_DESCD_TS_WRB_EN_MSK 0x00040000
|
||||
#define HW_ATL2_TDM_DESCD_TS_WRB_EN_SHIFT 18
|
||||
/* TX desc{D}_ts_en Bitfield Definitions
|
||||
*/
|
||||
#define HW_ATL2_TDM_DESCD_TS_EN_ADR(descriptor) \
|
||||
(0x00007C08 + (descriptor) * 0x40)
|
||||
#define HW_ATL2_TDM_DESCD_TS_EN_MSK 0x00020000
|
||||
#define HW_ATL2_TDM_DESCD_TS_EN_SHIFT 17
|
||||
/* TX desc{D}_avb_en Bitfield Definitions
|
||||
*/
|
||||
#define HW_ATL2_TDM_DESCD_AVB_EN_ADR(descriptor) \
|
||||
(0x00007C08 + (descriptor) * 0x40)
|
||||
#define HW_ATL2_TDM_DESCD_AVB_EN_MSK 0x00010000
|
||||
#define HW_ATL2_TDM_DESCD_AVB_EN_SHIFT 16
|
||||
/* tx tx_tc_q_rand_map_en bitfield definitions
|
||||
* preprocessor definitions for the bitfield "tx_tc_q_rand_map_en".
|
||||
* port="pif_tpb_tx_tc_q_rand_map_en_i"
|
||||
|
|
@ -221,7 +304,18 @@
|
|||
#define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_WIDTH 16
|
||||
/* default value of bitfield data_tc{t}_credit_max[f:0] */
|
||||
#define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_DEFAULT 0x0
|
||||
|
||||
/* register address for bitfield pif_tpb_highest_prio_tc_en */
|
||||
#define HW_ATL2_TPB_HIGHEST_PRIO_TC_EN_ADR 0x00007180
|
||||
/* bitmask for bitfield pif_tpb_highest_prio_tc_en */
|
||||
#define HW_ATL2_TPB_HIGHEST_PRIO_TC_EN_MSK 0x00000100
|
||||
/* lower bit position of bitfield pif_tpb_highest_prio_tc_en */
|
||||
#define HW_ATL2_TPB_HIGHEST_PRIO_TC_EN_SHIFT 8
|
||||
/* register address for bitfield pif_tpb_highest_prio_tc */
|
||||
#define HW_ATL2_TPB_HIGHEST_PRIO_TC_ADR 0x00007180
|
||||
/* bitmask for bitfield pif_tpb_highest_prio_tc */
|
||||
#define HW_ATL2_TPB_HIGHEST_PRIO_TC_MSK 0x00000007
|
||||
/* lower bit position of bitfield pif_tpb_highest_prio_tc */
|
||||
#define HW_ATL2_TPB_HIGHEST_PRIO_TC_SHIFT 0
|
||||
/* tx data_tc{t}_weight[e:0] bitfield definitions
|
||||
* preprocessor definitions for the bitfield "data_tc{t}_weight[e:0]".
|
||||
* parameter: tc {t} | stride size 0x4 | range [0, 7]
|
||||
|
|
@ -248,7 +342,87 @@
|
|||
*/
|
||||
|
||||
#define HW_ATL2_TX_INTR_MODERATION_CTL_ADR(queue) (0x00007c28u + (queue) * 0x40)
|
||||
/* TX tx_data_rd_req_limit[7:0] Bitfield Definitions
|
||||
*/
|
||||
#define HW_ATL2_TDM_TX_DATA_RD_REQ_LIMIT_ADR 0x00007B04
|
||||
#define HW_ATL2_TDM_TX_DATA_RD_REQ_LIMIT_MSK 0x0000FF00
|
||||
#define HW_ATL2_TDM_TX_DATA_RD_REQ_LIMIT_SHIFT 8
|
||||
/* TX tx_desc_rd_req_limit[4:0] Bitfield Definitions
|
||||
*/
|
||||
#define HW_ATL2_TDM_TX_DESC_RD_REQ_LIMIT_ADR 0x00007B04
|
||||
#define HW_ATL2_TDM_TX_DESC_RD_REQ_LIMIT_MSK 0x0000001F
|
||||
#define HW_ATL2_TDM_TX_DESC_RD_REQ_LIMIT_SHIFT 0
|
||||
/* register address for bitfield uP Force Interrupt */
|
||||
#define HW_ATL2_GLB_CONTROL_2_ADR 0x00000404
|
||||
#define HW_ATL2_MIF_INTERRUPT_2_TO_ITR_MSK 0x00000100
|
||||
/* lower bit position of bitfield MIF Interrupt to ITR */
|
||||
#define HW_ATL2_MIF_INTERRUPT_TO_ITR_SHIFT 6
|
||||
#define HW_ATL2_EN_INTERRUPT_MIF2_TO_ITR_MSK 0x00001000
|
||||
/* lower bit position of bitfield Enable MIF Interrupt to ITR */
|
||||
#define HW_ATL2_EN_INTERRUPT_TO_ITR_SHIFT 0xA
|
||||
#define HW_ATL2_GLOBAL_INTERNAL_ALARMS_1_ADR 0x00000924
|
||||
#define HW_ATL2_GLOBAL_HIGH_PRIO_INTERRUPT_1_MASK_ADR 0x00000964
|
||||
/* bitmask for bitfield TSG PTM GPIO interrupt */
|
||||
#define HW_ATL2_TSG_TSG1_GPIO_INTERRUPT_MSK 0x00000200
|
||||
/* lower bit position of bitfield TSG PTM GPIO interrupt */
|
||||
#define HW_ATL2_TSG_TSG1_GPIO_INTERRUPT_SHIFT 9
|
||||
/* bitmask for bitfield TSG0 GPIO interrupt */
|
||||
#define HW_ATL2_TSG_TSG0_GPIO_INTERRUPT_MSK 0x00000020
|
||||
/* lower bit position of bitfield TSG0 GPIO interrupt */
|
||||
#define HW_ATL2_TSG_TSG0_GPIO_INTERRUPT_SHIFT 5
|
||||
/* TSG registers */
|
||||
#define HW_ATL2_TSG_REG_ADR(clk, reg_name) \
|
||||
((clk) == 0 ? HW_ATL2_CLK0_##reg_name##_ADR :\
|
||||
HW_ATL2_CLK1_##reg_name##_ADR)
|
||||
|
||||
#define HW_ATL2_CLK0_CLOCK_CFG_ADR 0x00000CA0u
|
||||
#define HW_ATL2_CLK1_CLOCK_CFG_ADR 0x00000D50u
|
||||
#define HW_ATL2_TSG_SYNC_RESET_MSK 0x00000001
|
||||
#define HW_ATL2_TSG_SYNC_RESET_SHIFT 0x00000000
|
||||
#define HW_ATL2_TSG_CLOCK_EN_MSK 0x00000002
|
||||
#define HW_ATL2_TSG_CLOCK_EN_SHIFT 0x00000001
|
||||
#define HW_ATL2_CLK0_CLOCK_MODIF_CTRL_ADR 0x00000CA4u
|
||||
#define HW_ATL2_CLK1_CLOCK_MODIF_CTRL_ADR 0x00000D54u
|
||||
#define HW_ATL2_TSG_SUBTRACT_COUNTER_MSK 0x00000002
|
||||
#define HW_ATL2_TSG_ADD_COUNTER_MSK 0x00000004
|
||||
#define HW_ATL2_TSG_LOAD_INC_CFG_MSK 0x00000008
|
||||
#define HW_ATL2_CLK0_CLOCK_MODIF_VAL_LSW_ADR 0x00000CA8u
|
||||
#define HW_ATL2_CLK1_CLOCK_MODIF_VAL_LSW_ADR 0x00000D58u
|
||||
#define HW_ATL2_CLK0_CLOCK_INC_CFG_ADR 0x00000CB0u
|
||||
#define HW_ATL2_CLK1_CLOCK_INC_CFG_ADR 0x00000D60u
|
||||
#define HW_ATL2_CLK0_READ_CUR_NS_LSW_ADR 0x00000CB8u
|
||||
#define HW_ATL2_CLK1_READ_CUR_NS_LSW_ADR 0x00000D68u
|
||||
|
||||
#define HW_ATL2_CLK0_GPIO_CFG_ADR 0x00000CC4u
|
||||
#define HW_ATL2_CLK1_GPIO_CFG_ADR 0x00000D74u
|
||||
#define HW_ATL2_TSG_GPIO_IN_MONITOR_EN_SHIFT 0x00000000
|
||||
#define HW_ATL2_TSG_GPIO_IN_MONITOR_EN_MSK 0x00000001
|
||||
#define HW_ATL2_TSG_GPIO_IN_MODE_SHIFT 0x00000001
|
||||
#define HW_ATL2_TSG_GPIO_IN_MODE_MSK 0x00000006
|
||||
#define HW_ATL2_TSG_GPIO_IN_MODE_POSEDGE 0x00000000
|
||||
#define HW_ATL2_CLK0_EXT_CLK_COUNT_ADR 0x00000CCCu
|
||||
#define HW_ATL2_CLK1_EXT_CLK_COUNT_ADR 0x00000D7Cu
|
||||
#define HW_ATL2_CLK0_GPIO_EVENT_TS_LSW_ADR 0x00000CD0u
|
||||
#define HW_ATL2_CLK1_GPIO_EVENT_TS_LSW_ADR 0x00000D80u
|
||||
#define HW_ATL2_CLK0_GPIO_EVENT_GEN_TS_LSW_ADR 0x00000CE0u
|
||||
#define HW_ATL2_CLK1_GPIO_EVENT_GEN_TS_LSW_ADR 0x00000D90u
|
||||
#define HW_ATL2_CLK0_GPIO_EVENT_GEN_CFG_ADR 0x00000CE8u
|
||||
#define HW_ATL2_CLK1_GPIO_EVENT_GEN_CFG_ADR 0x00000D98u
|
||||
#define HW_ATL2_TSG_GPIO_OUTPUT_EN_SHIFT 0x00000000
|
||||
#define HW_ATL2_TSG_GPIO_OUTPUT_EN_MSK 0x00000001
|
||||
#define HW_ATL2_TSG_GPIO_EVENT_MODE_SHIFT 0x00000001
|
||||
#define HW_ATL2_TSG_GPIO_EVENT_MODE_MSK 0x00000006
|
||||
#define HW_ATL2_TSG_GPIO_EVENT_MODE_SET_ON_TIME 0x00000003
|
||||
#define HW_ATL2_TSG_GPIO_GEN_OUTPUT_EN_MSK 0x00000008
|
||||
#define HW_ATL2_CLK0_GPIO_EVENT_HIGH_TIME_LSW_ADR 0x00000CF0u
|
||||
#define HW_ATL2_CLK1_GPIO_EVENT_HIGH_TIME_LSW_ADR 0x00000DA0u
|
||||
#define HW_ATL2_CLK0_GPIO_EVENT_LOW_TIME_LSW_ADR 0x00000CF8u
|
||||
#define HW_ATL2_CLK1_GPIO_EVENT_LOW_TIME_LSW_ADR 0x00000DA8u
|
||||
/* PCIE Extended tag enable Bitfield Definitions
|
||||
*/
|
||||
#define HW_ATL2_PHI_EXT_TAG_EN_ADR 0x00001000
|
||||
#define HW_ATL2_PHI_EXT_TAG_EN_MSK 0x00000020
|
||||
#define HW_ATL2_PHI_EXT_TAG_EN_SHIFT 5
|
||||
/* Launch time control register */
|
||||
#define HW_ATL2_LT_CTRL_ADR 0x00007a1c
|
||||
|
||||
|
|
@ -387,5 +561,25 @@
|
|||
#define HW_ATL2_MCP_HOST_REQ_INT_ADR 0x00000F00u
|
||||
#define HW_ATL2_MCP_HOST_REQ_INT_SET_ADR 0x00000F04u
|
||||
#define HW_ATL2_MCP_HOST_REQ_INT_CLR_ADR 0x00000F08u
|
||||
|
||||
/* Register address for bitfield PTP EXT GPIO TS SEL */
|
||||
#define HW_ATL2_TSG0_EXT_GPIO_TS_INPUT_SEL_ADR 0x00003664
|
||||
/* Bitmask for bitfield PTP EXT GPIO TS SEL */
|
||||
#define HW_ATL2_TSG0_EXT_GPIO_TS_INPUT_SEL_MSK 0x00001F00
|
||||
/* Lower bit position of bitfield PTP EXT GPIO TS SEL */
|
||||
#define HW_ATL2_TSG0_EXT_GPIO_TS_INPUT_SEL_SHIFT 8
|
||||
/* Register address for bitfield TSG EXT GPIO TS SEL */
|
||||
#define HW_ATL2_TSG1_EXT_GPIO_TS_INPUT_SEL_ADR 0x00003660
|
||||
/* Bitmask for bitfield TSG EXT GPIO TS SEL */
|
||||
#define HW_ATL2_TSG1_EXT_GPIO_TS_INPUT_SEL_MSK 0x00001F00
|
||||
/* Lower bit position of bitfield TSG EXT GPIO TS SEL */
|
||||
#define HW_ATL2_TSG1_EXT_GPIO_TS_INPUT_SEL_SHIFT 8
|
||||
/* Register address for bitfield GPIO{P} Special Mode */
|
||||
#define HW_ATL2_GPIO_PIN_SPEC_MODE_ADR(pin) (0x00003698 + (pin) * 0x4)
|
||||
/* Bitmask for bitfield GPIO{P} Special Mode */
|
||||
#define HW_ATL2_GPIO_PIN_SPEC_MODE_MSK 0x0000000C
|
||||
/* Lower bit position of bitfield GPIO{P} Special Mode */
|
||||
#define HW_ATL2_GPIO_PIN_SPEC_MODE_SHIFT 2
|
||||
#define HW_ATL2_GPIO_PIN_SPEC_MODE_TSG1_EVENT_OUTPUT 0
|
||||
#define HW_ATL2_GPIO_PIN_SPEC_MODE_TSG0_EVENT_OUTPUT 2
|
||||
#define HW_ATL2_GPIO_PIN_SPEC_MODE_GPIO 3
|
||||
#endif /* HW_ATL2_LLH_INTERNAL_H */
|
||||
|
|
|
|||
|
|
@ -128,3 +128,37 @@ int hw_atl2_utils_soft_reset(struct aq_hw_s *self)
|
|||
err_exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
static const u32 hw_atl2_utils_hw_mac_regs[] = {
|
||||
0x00005580U, 0x00005590U, 0x000055B0U, 0x000055B4U,
|
||||
0x000055C0U, 0x00005B00U, 0x00005B04U, 0x00005B08U,
|
||||
0x00005B0CU, 0x00005B10U, 0x00005B14U, 0x00005B18U,
|
||||
0x00005B1CU, 0x00005B20U, 0x00005B24U, 0x00005B28U,
|
||||
0x00005B2CU, 0x00005B30U, 0x00005B34U, 0x00005B38U,
|
||||
0x00005B3CU, 0x00005B40U, 0x00005B44U, 0x00005B48U,
|
||||
0x00005B4CU, 0x00005B50U, 0x00005B54U, 0x00005B58U,
|
||||
0x00005B5CU, 0x00005B60U, 0x00005B64U, 0x00005B68U,
|
||||
0x00005B6CU, 0x00005B70U, 0x00005B74U, 0x00005B78U,
|
||||
0x00005B7CU, 0x00007C00U, 0x00007C04U, 0x00007C08U,
|
||||
0x00007C0CU, 0x00007C10U, 0x00007C14U, 0x00007C18U,
|
||||
0x00007C1CU, 0x00007C20U, 0x00007C40U, 0x00007C44U,
|
||||
0x00007C48U, 0x00007C4CU, 0x00007C50U, 0x00007C54U,
|
||||
0x00007C58U, 0x00007C5CU, 0x00007C60U, 0x00007C80U,
|
||||
0x00007C84U, 0x00007C88U, 0x00007C8CU, 0x00007C90U,
|
||||
0x00007C94U, 0x00007C98U, 0x00007C9CU, 0x00007CA0U,
|
||||
0x00007CC0U, 0x00007CC4U, 0x00007CC8U, 0x00007CCCU,
|
||||
0x00007CD0U, 0x00007CD4U, 0x00007CD8U, 0x00007CDCU,
|
||||
};
|
||||
|
||||
int hw_atl2_utils_hw_get_regs(struct aq_hw_s *self,
|
||||
const struct aq_hw_caps_s *aq_hw_caps,
|
||||
u32 *regs_buff)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < min_t(u32, aq_hw_caps->mac_regs_count,
|
||||
ARRAY_SIZE(hw_atl2_utils_hw_mac_regs)); i++)
|
||||
regs_buff[i] = aq_hw_read_reg(self,
|
||||
hw_atl2_utils_hw_mac_regs[i]);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,16 @@
|
|||
|
||||
#include "aq_hw.h"
|
||||
|
||||
/* Hardware tx launch time descriptor */
|
||||
struct hw_atl2_txts_s {
|
||||
__le64 ts;
|
||||
__le32 ctrl;
|
||||
u32 reserved;
|
||||
};
|
||||
|
||||
#define HW_ATL2_TXTS_DD BIT(3)
|
||||
#define HW_ATL2_TXTS_TS_VALID BIT(20)
|
||||
|
||||
/* F W A P I */
|
||||
|
||||
struct link_options_s {
|
||||
|
|
@ -626,10 +636,13 @@ int hw_atl2_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops);
|
|||
|
||||
int hw_atl2_utils_soft_reset(struct aq_hw_s *self);
|
||||
|
||||
int hw_atl2_utils_hw_get_regs(struct aq_hw_s *self,
|
||||
const struct aq_hw_caps_s *aq_hw_caps,
|
||||
u32 *regs_buff);
|
||||
|
||||
u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self);
|
||||
|
||||
int hw_atl2_utils_get_action_resolve_table_caps(struct aq_hw_s *self,
|
||||
u8 *base_index, u8 *count);
|
||||
int hw_atl2_utils_get_filter_caps(struct aq_hw_s *self);
|
||||
|
||||
extern const struct aq_fw_ops aq_a2_fw_ops;
|
||||
|
||||
|
|
|
|||
|
|
@ -121,6 +121,10 @@ static int aq_a2_fw_init(struct aq_hw_s *self)
|
|||
u32 val;
|
||||
int err;
|
||||
|
||||
err = hw_atl2_utils_get_filter_caps(self);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
hw_atl2_shared_buffer_get(self, link_control, link_control);
|
||||
link_control.mode = AQ_HOST_MODE_ACTIVE;
|
||||
hw_atl2_shared_buffer_write(self, link_control, link_control);
|
||||
|
|
@ -606,18 +610,77 @@ u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self)
|
|||
version.bundle.build;
|
||||
}
|
||||
|
||||
int hw_atl2_utils_get_action_resolve_table_caps(struct aq_hw_s *self,
|
||||
u8 *base_index, u8 *count)
|
||||
int hw_atl2_utils_get_filter_caps(struct aq_hw_s *self)
|
||||
{
|
||||
struct hw_atl2_priv *priv = self->priv;
|
||||
struct filter_caps_s filter_caps;
|
||||
u32 tag_top;
|
||||
int err;
|
||||
|
||||
err = hw_atl2_shared_buffer_read_safe(self, filter_caps, &filter_caps);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*base_index = filter_caps.rslv_tbl_base_index;
|
||||
*count = filter_caps.rslv_tbl_count;
|
||||
priv->art_base_index = filter_caps.rslv_tbl_base_index * 8;
|
||||
priv->art_count = filter_caps.rslv_tbl_count * 8;
|
||||
if (priv->art_count == 0)
|
||||
priv->art_count = HW_ATL2_ART_TOTAL_ENTRIES;
|
||||
priv->l2_filters_base_index = filter_caps.l2_filters_base_index;
|
||||
if (priv->l2_filters_base_index >= HW_ATL2_MAC_MAX)
|
||||
priv->l2_filters_base_index = HW_ATL2_MAC_UC;
|
||||
priv->l2_filter_count = filter_caps.l2_filter_count;
|
||||
priv->etype_filter_base_index = filter_caps.ethertype_filter_base_index;
|
||||
priv->etype_filter_count = filter_caps.ethertype_filter_count;
|
||||
priv->etype_filter_tag_top =
|
||||
(priv->etype_filter_count >= HW_ATL2_RPF_ETYPE_TAGS) ?
|
||||
(HW_ATL2_RPF_ETYPE_TAGS) : (HW_ATL2_RPF_ETYPE_TAGS >> 1);
|
||||
priv->vlan_filter_base_index = filter_caps.vlan_filter_base_index;
|
||||
/* 0 - no tag, 1 - reserved for vlan-filter-offload filters */
|
||||
tag_top =
|
||||
(filter_caps.vlan_filter_count == HW_ATL2_RPF_VLAN_FILTERS) ?
|
||||
(HW_ATL2_RPF_VLAN_FILTERS - 2) :
|
||||
(HW_ATL2_RPF_VLAN_FILTERS / 2 - 2);
|
||||
|
||||
if (filter_caps.vlan_filter_count > 2) {
|
||||
priv->vlan_filter_count = min_t(u32,
|
||||
filter_caps.vlan_filter_count - 2,
|
||||
tag_top);
|
||||
} else {
|
||||
pr_debug("atlantic: FW vlan_filter_count=%u <= 2, no usable VLAN filters\n",
|
||||
filter_caps.vlan_filter_count);
|
||||
priv->vlan_filter_count = 0;
|
||||
}
|
||||
|
||||
priv->l3_v4_filter_base_index = filter_caps.l3_ip4_filter_base_index;
|
||||
if (priv->l3_v4_filter_base_index >= HW_ATL2_RPF_L3V4_FILTERS) {
|
||||
priv->l3_v4_filter_base_index = 0;
|
||||
priv->l3_v4_filter_count = 0;
|
||||
} else {
|
||||
priv->l3_v4_filter_count = min_t(u32,
|
||||
filter_caps.l3_ip4_filter_count,
|
||||
HW_ATL2_RPF_L3V4_FILTERS - 1);
|
||||
}
|
||||
|
||||
priv->l3_v6_filter_base_index = filter_caps.l3_ip6_filter_base_index;
|
||||
if (priv->l3_v6_filter_base_index >= HW_ATL2_RPF_L3V6_FILTERS) {
|
||||
priv->l3_v6_filter_base_index = 0;
|
||||
priv->l3_v6_filter_count = 0;
|
||||
} else {
|
||||
priv->l3_v6_filter_count = min_t(u32,
|
||||
filter_caps.l3_ip6_filter_count,
|
||||
HW_ATL2_RPF_L3V6_FILTERS - 1);
|
||||
}
|
||||
|
||||
priv->l4_filter_base_index = filter_caps.l4_filter_base_index;
|
||||
if (priv->l4_filter_base_index >= HW_ATL2_RPF_L4_FILTERS) {
|
||||
priv->l4_filter_base_index = 0;
|
||||
priv->l4_filter_count = 0;
|
||||
} else {
|
||||
priv->l4_filter_count = min_t(u32,
|
||||
filter_caps.l4_filter_count,
|
||||
HW_ATL2_RPF_L4_FILTERS - 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user