]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: atlantic: add AQC113 PTP support in aq_ptp and driver core
authorSukhdeep Singh <sukhdeeps@marvell.com>
Wed, 10 Jun 2026 11:54:48 +0000 (17:24 +0530)
committerJakub Kicinski <kuba@kernel.org>
Mon, 15 Jun 2026 22:38:44 +0000 (15:38 -0700)
aq_ptp.c / aq_ptp.h:
- Add aq_ptp_state enum (AQ_PTP_FIRST_INIT, AQ_PTP_LINK_UP,
  AQ_PTP_NO_LINK) to distinguish first init from link-change events;
  on AQC113 only reset the TSG clock on first init to avoid disrupting
  ongoing synchronization.
- Add aq_ptp_dpath_enable() for comprehensive L3/L4 PTP filter
  setup/teardown, replacing the previous single-filter approach with
  an array of 4 slots for IPv4 and IPv6 PTP multicast addresses
  (224.0.1.129, 224.0.0.107, ff0e::181, ff02::6b).
- Add aq_ptp_parse_rx_filters() to map hwtstamp_rx_filters to L2/L4
  enable flags and call aq_ptp_dpath_enable().
- Re-apply RX filters on link change (hardware state lost after reset).
- Extend PTP ring alloc/init/start/stop to handle AQC113 PTP ring ops.
- Add per-instance PTP offset table for AQC113 with empirically measured
  values at 100M/1G/2.5G/5G/10G link speeds.
- Export aq_ptp_dpath_enable() and updated ring helpers in aq_ptp.h.

aq_hw.h:
- Include hw_atl2/hw_atl2.h for AQC113 PTP type definitions.

aq_nic.c:
- Account for PTP IRQ vector (AQ_HW_PTP_IRQS) in vector count math.
- Call hw_atl2 PTP re-enable hook after hardware reset in
  aq_nic_update_link_status().

aq_pci_func.c:
- Pass PTP IRQ index to aq_ptp_irq_alloc() in probe path.

Signed-off-by: Sukhdeep Singh <sukhdeeps@marvell.com>
Link: https://patch.msgid.link/20260610115448.272-13-sukhdeeps@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/aquantia/atlantic/aq_hw.h
drivers/net/ethernet/aquantia/atlantic/aq_nic.c
drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
drivers/net/ethernet/aquantia/atlantic/aq_ptp.c
drivers/net/ethernet/aquantia/atlantic/aq_ptp.h

index 0ba29b8f95ab28dab2735442abf3b57014880aba..338c956ad1f7553a866d655610ec1fcd1687e10b 100644 (file)
@@ -15,6 +15,7 @@
 #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
index 09c90c969fb1d5a7ea5e74ae562fd696f2e02d61..01792f7abf9627b41224a24d3757f08bdfc3eac5 100644 (file)
@@ -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;
 
@@ -691,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;
@@ -803,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:
index 2cd6cca66fcc6fe328ad284e240e6647cabc86c6..005d6ef4fc36fb2e22bb4b4081efc57bbe2ea8f0 100644 (file)
@@ -294,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 */
index 6bb2329f1a682b309c7b728d2f7f30f1828783eb..558ac9237f759eb5eb4e713df5a2c51c78a86f03 100644 (file)
 
 #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;
                }
        }
@@ -378,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",
@@ -392,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,
-                                        0, start, (u32)period, 0);
+                                        aq_ptp->ptp_clock_sel, start,
+                                        (u32)period, PTP_GPIO_HIGHTIME);
        mutex_unlock(&aq_nic->fwreq_mutex);
 
        return 0;
@@ -466,7 +485,8 @@ 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,
-                                                       0, enable);
+                                                       aq_ptp->ptp_clock_sel,
+                                                       enable);
 }
 
 static int aq_ptp_extts_pin_configure(struct ptp_clock_info *ptp,
@@ -555,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
@@ -584,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;
-
-       aq_ptp->eth_type_filter.ethertype = ETH_P_1588;
-       aq_ptp->eth_type_filter.queue = aq_ptp->ptp_rx.idx;
+       unsigned int ptp_en_flags = AQ_HW_PTP_DISABLE;
+
+       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;
 }
 
@@ -685,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 */
@@ -830,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;
@@ -849,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)
@@ -887,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;
@@ -924,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);
 
@@ -945,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);
 }
@@ -984,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) {
@@ -996,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,
@@ -1005,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:
@@ -1023,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);
 }
@@ -1047,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;
@@ -1094,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,
@@ -1151,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;
        }
@@ -1180,19 +1416,43 @@ int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec)
                return 0;
        }
 
-       if (!aq_nic->aq_fw_ops->enable_ptp) {
-               aq_nic->aq_ptp = NULL;
-               return 0;
+       if (a1_ptp) {
+               if (!aq_nic->aq_fw_ops->enable_ptp) {
+                       aq_nic->aq_ptp = NULL;
+                       return 0;
+               }
        }
 
-       hw_atl_utils_mpi_read_stats(aq_nic->aq_hw, &mbox);
-
-       if (!(mbox.info.caps_ex & BIT(CAPS_EX_PHY_PTP_EN))) {
+       /* 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;
        }
 
-       aq_ptp_offset_init(&mbox.info.ptp_offset);
+       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 (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 = kzalloc_obj(*aq_ptp);
        if (!aq_ptp) {
@@ -1202,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);
@@ -1222,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;
 
@@ -1256,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;
 
-       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);
+       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);
+       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)
index 1658ef788de8a902f335e5e7de7daaf1c64bffd4..96cbfa59ac75231876bd76a5c0760d1d4d1f3189 100644 (file)
 
 #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,7 @@ 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 */
@@ -81,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;
 }
@@ -123,7 +129,8 @@ 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)
 {