net: atlantic: Fix DMA mapping for PTP hwts ring
[platform/kernel/linux-starfive.git] / drivers / net / ethernet / aquantia / atlantic / aq_ring.c
index 4de22ee..f7433ab 100644 (file)
@@ -132,8 +132,8 @@ static int aq_get_rxpages(struct aq_ring_s *self, struct aq_ring_buff_s *rxbuf)
        return 0;
 }
 
-static struct aq_ring_s *aq_ring_alloc(struct aq_ring_s *self,
-                                      struct aq_nic_s *aq_nic)
+static int aq_ring_alloc(struct aq_ring_s *self,
+                        struct aq_nic_s *aq_nic)
 {
        int err = 0;
 
@@ -156,46 +156,29 @@ static struct aq_ring_s *aq_ring_alloc(struct aq_ring_s *self,
 err_exit:
        if (err < 0) {
                aq_ring_free(self);
-               self = NULL;
        }
 
-       return self;
+       return err;
 }
 
-struct aq_ring_s *aq_ring_tx_alloc(struct aq_ring_s *self,
-                                  struct aq_nic_s *aq_nic,
-                                  unsigned int idx,
-                                  struct aq_nic_cfg_s *aq_nic_cfg)
+int aq_ring_tx_alloc(struct aq_ring_s *self,
+                    struct aq_nic_s *aq_nic,
+                    unsigned int idx,
+                    struct aq_nic_cfg_s *aq_nic_cfg)
 {
-       int err = 0;
-
        self->aq_nic = aq_nic;
        self->idx = idx;
        self->size = aq_nic_cfg->txds;
        self->dx_size = aq_nic_cfg->aq_hw_caps->txd_size;
 
-       self = aq_ring_alloc(self, aq_nic);
-       if (!self) {
-               err = -ENOMEM;
-               goto err_exit;
-       }
-
-err_exit:
-       if (err < 0) {
-               aq_ring_free(self);
-               self = NULL;
-       }
-
-       return self;
+       return aq_ring_alloc(self, aq_nic);
 }
 
-struct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self,
-                                  struct aq_nic_s *aq_nic,
-                                  unsigned int idx,
-                                  struct aq_nic_cfg_s *aq_nic_cfg)
+int aq_ring_rx_alloc(struct aq_ring_s *self,
+                    struct aq_nic_s *aq_nic,
+                    unsigned int idx,
+                    struct aq_nic_cfg_s *aq_nic_cfg)
 {
-       int err = 0;
-
        self->aq_nic = aq_nic;
        self->idx = idx;
        self->size = aq_nic_cfg->rxds;
@@ -217,22 +200,10 @@ struct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self,
                self->tail_size = 0;
        }
 
-       self = aq_ring_alloc(self, aq_nic);
-       if (!self) {
-               err = -ENOMEM;
-               goto err_exit;
-       }
-
-err_exit:
-       if (err < 0) {
-               aq_ring_free(self);
-               self = NULL;
-       }
-
-       return self;
+       return aq_ring_alloc(self, aq_nic);
 }
 
-struct aq_ring_s *
+int
 aq_ring_hwts_rx_alloc(struct aq_ring_s *self, struct aq_nic_s *aq_nic,
                      unsigned int idx, unsigned int size, unsigned int dx_size)
 {
@@ -250,10 +221,10 @@ aq_ring_hwts_rx_alloc(struct aq_ring_s *self, struct aq_nic_s *aq_nic,
                                           GFP_KERNEL);
        if (!self->dx_ring) {
                aq_ring_free(self);
-               return NULL;
+               return -ENOMEM;
        }
 
-       return self;
+       return 0;
 }
 
 int aq_ring_init(struct aq_ring_s *self, const enum atl_ring_type ring_type)
@@ -647,7 +618,7 @@ static int __aq_ring_rx_clean(struct aq_ring_s *self, struct napi_struct *napi,
                }
                if (is_ptp_ring)
                        buff->len -=
-                               aq_ptp_extract_ts(self->aq_nic, skb,
+                               aq_ptp_extract_ts(self->aq_nic, skb_hwtstamps(skb),
                                                  aq_buf_vaddr(&buff->rxdata),
                                                  buff->len);
 
@@ -742,6 +713,8 @@ static int __aq_ring_xdp_clean(struct aq_ring_s *rx_ring,
                struct aq_ring_buff_s *buff = &rx_ring->buff_ring[rx_ring->sw_head];
                bool is_ptp_ring = aq_ptp_ring(rx_ring->aq_nic, rx_ring);
                struct aq_ring_buff_s *buff_ = NULL;
+               u16 ptp_hwtstamp_len = 0;
+               struct skb_shared_hwtstamps shhwtstamps;
                struct sk_buff *skb = NULL;
                unsigned int next_ = 0U;
                struct xdp_buff xdp;
@@ -810,11 +783,12 @@ static int __aq_ring_xdp_clean(struct aq_ring_s *rx_ring,
                hard_start = page_address(buff->rxdata.page) +
                             buff->rxdata.pg_off - rx_ring->page_offset;
 
-               if (is_ptp_ring)
-                       buff->len -=
-                               aq_ptp_extract_ts(rx_ring->aq_nic, skb,
-                                                 aq_buf_vaddr(&buff->rxdata),
-                                                 buff->len);
+               if (is_ptp_ring) {
+                       ptp_hwtstamp_len = aq_ptp_extract_ts(rx_ring->aq_nic, &shhwtstamps,
+                                                            aq_buf_vaddr(&buff->rxdata),
+                                                            buff->len);
+                       buff->len -= ptp_hwtstamp_len;
+               }
 
                xdp_init_buff(&xdp, frame_sz, &rx_ring->xdp_rxq);
                xdp_prepare_buff(&xdp, hard_start, rx_ring->page_offset,
@@ -834,6 +808,9 @@ static int __aq_ring_xdp_clean(struct aq_ring_s *rx_ring,
                if (IS_ERR(skb) || !skb)
                        continue;
 
+               if (ptp_hwtstamp_len > 0)
+                       *skb_hwtstamps(skb) = shhwtstamps;
+
                if (buff->is_vlan)
                        __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
                                               buff->vlan_rx_tag);
@@ -932,11 +909,27 @@ void aq_ring_free(struct aq_ring_s *self)
                return;
 
        kfree(self->buff_ring);
+       self->buff_ring = NULL;
 
-       if (self->dx_ring)
+       if (self->dx_ring) {
                dma_free_coherent(aq_nic_get_dev(self->aq_nic),
                                  self->size * self->dx_size, self->dx_ring,
                                  self->dx_ring_pa);
+               self->dx_ring = NULL;
+       }
+}
+
+void aq_ring_hwts_rx_free(struct aq_ring_s *self)
+{
+       if (!self)
+               return;
+
+       if (self->dx_ring) {
+               dma_free_coherent(aq_nic_get_dev(self->aq_nic),
+                                 self->size * self->dx_size + AQ_CFG_RXDS_DEF,
+                                 self->dx_ring, self->dx_ring_pa);
+               self->dx_ring = NULL;
+       }
 }
 
 unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data)