[PATCH 0/9][linux-oem] Enable AQUANTIA AQC107 10G & 2.5/5Gb NICs

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH 0/9][linux-oem] Enable AQUANTIA AQC107 10G & 2.5/5Gb NICs

AceLan Kao
BugLink: http://bugs.launchpad.net/bugs/1730544

From vendor's suggestion, there are some patches in v4.14-rc6
are required to enable the 2 NICs.
AQUANTIA AQC107 10G[1D6A:0001] & 2.5/5Gb [1D6A:D108] NIC

417a3ae net: aquantia: Bad udp rate on default interrupt coalescing
b82ee71 net: aquantia: Enable coalescing management via ethtool interface
6849540 net: aquantia: mmio unmap was not performed on driver removal
4c8bb60 net: aquantia: Limit number of MSIX irqs to the number of cpus
93d87b8 net: aquantia: Fixed transient link up/down/up notification
5d8d84e net: aquantia: Add queue restarts stats counter
65e665e net: aquantia: Reset nic statistics on interface up/down

And to avoid conflict, cherry pick 2 more commits

3aec641 aquantia: Fix Tx queue hangups
65e665e net: aquantia: Reset nic statistics on interface up/down

Igor Russkikh (9):
  net: aquantia: Bad udp rate on default interrupt coalescing
  aquantia: Fix Tx queue hangups
  net: aquantia: Reset nic statistics on interface up/down
  net: aquantia: Enable coalescing management via ethtool interface
  net: aquantia: mmio unmap was not performed on driver removal
  net: aquantia: Limit number of MSIX irqs to the number of cpus
  net: aquantia: Fixed transient link up/down/up notification
  net: aquantia: Add queue restarts stats counter
  net: aquantia: Reset nic statistics on interface up/down

 drivers/net/ethernet/aquantia/atlantic/aq_cfg.h    |  12 +-
 .../net/ethernet/aquantia/atlantic/aq_ethtool.c    | 157 +++++++++++++--------
 drivers/net/ethernet/aquantia/atlantic/aq_hw.h     |   5 +-
 drivers/net/ethernet/aquantia/atlantic/aq_nic.c    | 129 +++++++++--------
 drivers/net/ethernet/aquantia/atlantic/aq_nic.h    |   6 +-
 .../net/ethernet/aquantia/atlantic/aq_pci_func.c   |  14 +-
 drivers/net/ethernet/aquantia/atlantic/aq_ring.c   |  26 ++++
 drivers/net/ethernet/aquantia/atlantic/aq_ring.h   |   4 +
 drivers/net/ethernet/aquantia/atlantic/aq_vec.c    |  11 +-
 .../ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c  |  21 ++-
 .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c  |  89 ++++++------
 .../aquantia/atlantic/hw_atl/hw_atl_b0_internal.h  |   3 +
 .../aquantia/atlantic/hw_atl/hw_atl_utils.c        |  69 +++++++--
 .../aquantia/atlantic/hw_atl/hw_atl_utils.h        |  18 ++-
 14 files changed, 361 insertions(+), 203 deletions(-)

--
2.7.4


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 1/9] net: aquantia: Bad udp rate on default interrupt coalescing

AceLan Kao
From: Igor Russkikh <[hidden email]>

BugLink: http://bugs.launchpad.net/bugs/1730544

Default Tx rates cause very long ISR delays on Tx.
0xff is 510us delay, giving only ~ 2000 interrupts per seconds for
Tx rings cleanup. With these settings udp tx rate was never higher than
~800Mbps on a single stream. Changing min delay to 0xF makes it
way better with ~6Gbps

TCP stream performance is almost unaffected by this change, since LSO
optimizations play important role.

CPU load is affected insignificantly by this change.

Signed-off-by: Pavel Belous <[hidden email]>
Signed-off-by: Igor Russkikh <[hidden email]>
Signed-off-by: David S. Miller <[hidden email]>
(cherry picked from commit 417a3ae4b14909439bb49790f90201f450399845)
Signed-off-by: AceLan Kao <[hidden email]>
---
 drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
index 21784cc..a399203 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
@@ -815,12 +815,12 @@ static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self,
  PHAL_ATLANTIC_B0->itr_rx |= max_timer << 0x10U;
  } else {
  static unsigned int hw_atl_b0_timers_table_tx_[][2] = {
- {0xffU, 0xffU}, /* 10Gbit */
- {0xffU, 0x1ffU}, /* 5Gbit */
- {0xffU, 0x1ffU}, /* 5Gbit 5GS */
- {0xffU, 0x1ffU}, /* 2.5Gbit */
- {0xffU, 0x1ffU}, /* 1Gbit */
- {0xffU, 0x1ffU}, /* 100Mbit */
+ {0xfU, 0xffU}, /* 10Gbit */
+ {0xfU, 0x1ffU}, /* 5Gbit */
+ {0xfU, 0x1ffU}, /* 5Gbit 5GS */
+ {0xfU, 0x1ffU}, /* 2.5Gbit */
+ {0xfU, 0x1ffU}, /* 1Gbit */
+ {0xfU, 0x1ffU}, /* 100Mbit */
  };
 
  static unsigned int hw_atl_b0_timers_table_rx_[][2] = {
--
2.7.4


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 2/9] aquantia: Fix Tx queue hangups

AceLan Kao
In reply to this post by AceLan Kao
From: Igor Russkikh <[hidden email]>

BugLink: http://bugs.launchpad.net/bugs/1730544

Driver did a poor job in managing its Tx queues: Sometimes it could stop
tx queues due to link down condition in aq_nic_xmit - but never waked up
them. That led to Tx path total suspend.
This patch fixes this and improves generic queue management:
- introduces queue restart counter
- uses generic netif_ interface to disable and enable tx path
- refactors link up/down condition and introduces dmesg log event when
  link changes.
- introduces new constant for minimum descriptors count required for queue
  wakeup

Signed-off-by: Pavel Belous <[hidden email]>
Signed-off-by: Igor Russkikh <[hidden email]>
Signed-off-by: David S. Miller <[hidden email]>
(cherry picked from commit 3aec6412e007b294d4c135f5c7ed5e5ecf37dd2e)
Signed-off-by: AceLan Kao <[hidden email]>
---
 drivers/net/ethernet/aquantia/atlantic/aq_cfg.h  |  4 ++
 drivers/net/ethernet/aquantia/atlantic/aq_nic.c  | 91 +++++++++++-------------
 drivers/net/ethernet/aquantia/atlantic/aq_nic.h  |  2 -
 drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 26 +++++++
 drivers/net/ethernet/aquantia/atlantic/aq_ring.h |  4 ++
 drivers/net/ethernet/aquantia/atlantic/aq_vec.c  |  8 +--
 6 files changed, 76 insertions(+), 59 deletions(-)

diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h
index 2149864..0fdaaa6 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h
@@ -51,6 +51,10 @@
 
 #define AQ_CFG_SKB_FRAGS_MAX   32U
 
+/* Number of descriptors available in one ring to resume this ring queue
+ */
+#define AQ_CFG_RESTART_DESC_THRES   (AQ_CFG_SKB_FRAGS_MAX * 2)
+
 #define AQ_CFG_NAPI_WEIGHT     64U
 
 #define AQ_CFG_MULTICAST_ADDRESS_MAX     32U
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index 6ac9e26..45a2a9b 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -119,6 +119,35 @@ int aq_nic_cfg_start(struct aq_nic_s *self)
  return 0;
 }
 
+static int aq_nic_update_link_status(struct aq_nic_s *self)
+{
+ int err = self->aq_hw_ops.hw_get_link_status(self->aq_hw);
+
+ if (err)
+ return err;
+
+ if (self->link_status.mbps != self->aq_hw->aq_link_status.mbps)
+ pr_info("%s: link change old %d new %d\n",
+ AQ_CFG_DRV_NAME, self->link_status.mbps,
+ self->aq_hw->aq_link_status.mbps);
+
+ self->link_status = self->aq_hw->aq_link_status;
+ if (!netif_carrier_ok(self->ndev) && self->link_status.mbps) {
+ aq_utils_obj_set(&self->header.flags,
+ AQ_NIC_FLAG_STARTED);
+ aq_utils_obj_clear(&self->header.flags,
+   AQ_NIC_LINK_DOWN);
+ netif_carrier_on(self->ndev);
+ netif_tx_wake_all_queues(self->ndev);
+ }
+ if (netif_carrier_ok(self->ndev) && !self->link_status.mbps) {
+ netif_carrier_off(self->ndev);
+ netif_tx_disable(self->ndev);
+ aq_utils_obj_set(&self->header.flags, AQ_NIC_LINK_DOWN);
+ }
+ return 0;
+}
+
 static void aq_nic_service_timer_cb(unsigned long param)
 {
  struct aq_nic_s *self = (struct aq_nic_s *)param;
@@ -131,26 +160,13 @@ static void aq_nic_service_timer_cb(unsigned long param)
  if (aq_utils_obj_test(&self->header.flags, AQ_NIC_FLAGS_IS_NOT_READY))
  goto err_exit;
 
- err = self->aq_hw_ops.hw_get_link_status(self->aq_hw);
- if (err < 0)
+ err = aq_nic_update_link_status(self);
+ if (err)
  goto err_exit;
 
- self->link_status = self->aq_hw->aq_link_status;
-
  self->aq_hw_ops.hw_interrupt_moderation_set(self->aq_hw,
     self->aq_nic_cfg.is_interrupt_moderation);
 
- if (self->link_status.mbps) {
- aq_utils_obj_set(&self->header.flags,
- AQ_NIC_FLAG_STARTED);
- aq_utils_obj_clear(&self->header.flags,
-   AQ_NIC_LINK_DOWN);
- netif_carrier_on(self->ndev);
- } else {
- netif_carrier_off(self->ndev);
- aq_utils_obj_set(&self->header.flags, AQ_NIC_LINK_DOWN);
- }
-
  memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s));
  memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s));
  for (i = AQ_DIMOF(self->aq_vec); i--;) {
@@ -241,7 +257,6 @@ struct aq_nic_s *aq_nic_alloc_cold(const struct net_device_ops *ndev_ops,
 int aq_nic_ndev_register(struct aq_nic_s *self)
 {
  int err = 0;
- unsigned int i = 0U;
 
  if (!self->ndev) {
  err = -EINVAL;
@@ -263,8 +278,7 @@ int aq_nic_ndev_register(struct aq_nic_s *self)
 
  netif_carrier_off(self->ndev);
 
- for (i = AQ_CFG_VECS_MAX; i--;)
- aq_nic_ndev_queue_stop(self, i);
+ netif_tx_disable(self->ndev);
 
  err = register_netdev(self->ndev);
  if (err < 0)
@@ -318,12 +332,8 @@ struct aq_nic_s *aq_nic_alloc_hot(struct net_device *ndev)
  err = -EINVAL;
  goto err_exit;
  }
- if (netif_running(ndev)) {
- unsigned int i;
-
- for (i = AQ_CFG_VECS_MAX; i--;)
- netif_stop_subqueue(ndev, i);
- }
+ if (netif_running(ndev))
+ netif_tx_disable(ndev);
 
  for (self->aq_vecs = 0; self->aq_vecs < self->aq_nic_cfg.vecs;
  self->aq_vecs++) {
@@ -383,16 +393,6 @@ int aq_nic_init(struct aq_nic_s *self)
  return err;
 }
 
-void aq_nic_ndev_queue_start(struct aq_nic_s *self, unsigned int idx)
-{
- netif_start_subqueue(self->ndev, idx);
-}
-
-void aq_nic_ndev_queue_stop(struct aq_nic_s *self, unsigned int idx)
-{
- netif_stop_subqueue(self->ndev, idx);
-}
-
 int aq_nic_start(struct aq_nic_s *self)
 {
  struct aq_vec_s *aq_vec = NULL;
@@ -451,10 +451,6 @@ int aq_nic_start(struct aq_nic_s *self)
  goto err_exit;
  }
 
- for (i = 0U, aq_vec = self->aq_vec[0];
- self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i])
- aq_nic_ndev_queue_start(self, i);
-
  err = netif_set_real_num_tx_queues(self->ndev, self->aq_vecs);
  if (err < 0)
  goto err_exit;
@@ -463,6 +459,8 @@ int aq_nic_start(struct aq_nic_s *self)
  if (err < 0)
  goto err_exit;
 
+ netif_tx_start_all_queues(self->ndev);
+
 err_exit:
  return err;
 }
@@ -602,7 +600,6 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb)
  unsigned int vec = skb->queue_mapping % self->aq_nic_cfg.vecs;
  unsigned int tc = 0U;
  int err = NETDEV_TX_OK;
- bool is_nic_in_bad_state;
 
  frags = skb_shinfo(skb)->nr_frags + 1;
 
@@ -613,13 +610,10 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb)
  goto err_exit;
  }
 
- is_nic_in_bad_state = aq_utils_obj_test(&self->header.flags,
- AQ_NIC_FLAGS_IS_NOT_TX_READY) ||
- (aq_ring_avail_dx(ring) <
- AQ_CFG_SKB_FRAGS_MAX);
+ aq_ring_update_queue_state(ring);
 
- if (is_nic_in_bad_state) {
- aq_nic_ndev_queue_stop(self, ring->idx);
+ /* Above status update may stop the queue. Check this. */
+ if (__netif_subqueue_stopped(self->ndev, ring->idx)) {
  err = NETDEV_TX_BUSY;
  goto err_exit;
  }
@@ -631,9 +625,6 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb)
       ring,
       frags);
  if (err >= 0) {
- if (aq_ring_avail_dx(ring) < AQ_CFG_SKB_FRAGS_MAX + 1)
- aq_nic_ndev_queue_stop(self, ring->idx);
-
  ++ring->stats.tx.packets;
  ring->stats.tx.bytes += skb->len;
  }
@@ -905,9 +896,7 @@ int aq_nic_stop(struct aq_nic_s *self)
  struct aq_vec_s *aq_vec = NULL;
  unsigned int i = 0U;
 
- for (i = 0U, aq_vec = self->aq_vec[0];
- self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i])
- aq_nic_ndev_queue_stop(self, i);
+ netif_tx_disable(self->ndev);
 
  del_timer_sync(&self->service_timer);
 
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
index 7fc2a5e..0ddd556 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
@@ -83,8 +83,6 @@ struct net_device *aq_nic_get_ndev(struct aq_nic_s *self);
 int aq_nic_init(struct aq_nic_s *self);
 int aq_nic_cfg_start(struct aq_nic_s *self);
 int aq_nic_ndev_register(struct aq_nic_s *self);
-void aq_nic_ndev_queue_start(struct aq_nic_s *self, unsigned int idx);
-void aq_nic_ndev_queue_stop(struct aq_nic_s *self, unsigned int idx);
 void aq_nic_ndev_free(struct aq_nic_s *self);
 int aq_nic_start(struct aq_nic_s *self);
 int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb);
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
index ec5579f..8a38494 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
@@ -104,6 +104,32 @@ int aq_ring_init(struct aq_ring_s *self)
  return 0;
 }
 
+void aq_ring_update_queue_state(struct aq_ring_s *ring)
+{
+ if (aq_ring_avail_dx(ring) <= AQ_CFG_SKB_FRAGS_MAX)
+ aq_ring_queue_stop(ring);
+ else if (aq_ring_avail_dx(ring) > AQ_CFG_RESTART_DESC_THRES)
+ aq_ring_queue_wake(ring);
+}
+
+void aq_ring_queue_wake(struct aq_ring_s *ring)
+{
+ struct net_device *ndev = aq_nic_get_ndev(ring->aq_nic);
+
+ if (__netif_subqueue_stopped(ndev, ring->idx)) {
+ netif_wake_subqueue(ndev, ring->idx);
+ ring->stats.tx.queue_restarts++;
+ }
+}
+
+void aq_ring_queue_stop(struct aq_ring_s *ring)
+{
+ struct net_device *ndev = aq_nic_get_ndev(ring->aq_nic);
+
+ if (!__netif_subqueue_stopped(ndev, ring->idx))
+ netif_stop_subqueue(ndev, ring->idx);
+}
+
 void aq_ring_tx_clean(struct aq_ring_s *self)
 {
  struct device *dev = aq_nic_get_dev(self->aq_nic);
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h
index eecd6d1..93a4feb 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h
@@ -94,6 +94,7 @@ struct aq_ring_stats_tx_s {
  u64 errors;
  u64 packets;
  u64 bytes;
+ u64 queue_restarts;
 };
 
 union aq_ring_stats_s {
@@ -147,6 +148,9 @@ struct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self,
 int aq_ring_init(struct aq_ring_s *self);
 void aq_ring_rx_deinit(struct aq_ring_s *self);
 void aq_ring_free(struct aq_ring_s *self);
+void aq_ring_update_queue_state(struct aq_ring_s *ring);
+void aq_ring_queue_wake(struct aq_ring_s *ring);
+void aq_ring_queue_stop(struct aq_ring_s *ring);
 void aq_ring_tx_clean(struct aq_ring_s *self);
 int aq_ring_rx_clean(struct aq_ring_s *self, int *work_done, int budget);
 int aq_ring_rx_fill(struct aq_ring_s *self);
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c
index fee446a..996160b 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c
@@ -59,12 +59,7 @@ static int aq_vec_poll(struct napi_struct *napi, int budget)
  if (ring[AQ_VEC_TX_ID].sw_head !=
     ring[AQ_VEC_TX_ID].hw_head) {
  aq_ring_tx_clean(&ring[AQ_VEC_TX_ID]);
-
- if (aq_ring_avail_dx(&ring[AQ_VEC_TX_ID]) >
-    AQ_CFG_SKB_FRAGS_MAX) {
- aq_nic_ndev_queue_start(self->aq_nic,
- ring[AQ_VEC_TX_ID].idx);
- }
+ aq_ring_update_queue_state(&ring[AQ_VEC_TX_ID]);
  was_tx_cleaned = true;
  }
 
@@ -363,6 +358,7 @@ void aq_vec_add_stats(struct aq_vec_s *self,
  stats_tx->packets += tx->packets;
  stats_tx->bytes += tx->bytes;
  stats_tx->errors += tx->errors;
+ stats_tx->queue_restarts += tx->queue_restarts;
  }
 }
 
--
2.7.4


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 3/9] net: aquantia: Reset nic statistics on interface up/down

AceLan Kao
In reply to this post by AceLan Kao
From: Igor Russkikh <[hidden email]>

BugLink: http://bugs.launchpad.net/bugs/1730544

Internal statistics system on chip never gets reset until hardware
reboot. This is quite inconvenient in terms of ethtool statistics usage.

This patch implements incremental statistics update inside of
service callback.

Upon nic initialization, first request is done to fetch
initial stat data, current collected stat data gets cleared.
Internal statistics mailbox readout is improved to save space and
increase readability

Signed-off-by: Pavel Belous <[hidden email]>
Signed-off-by: Igor Russkikh <[hidden email]>
Signed-off-by: David S. Miller <[hidden email]>
(cherry picked from commit 65e665e68d097edfe667372f13d54f3e4edcb69c)
Signed-off-by: AceLan Kao <[hidden email]>
---
 drivers/net/ethernet/aquantia/atlantic/aq_hw.h     |  2 +
 drivers/net/ethernet/aquantia/atlantic/aq_nic.c    |  3 +
 .../ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c  |  1 +
 .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c  |  1 +
 .../aquantia/atlantic/hw_atl/hw_atl_utils.c        | 69 +++++++++++++++++-----
 .../aquantia/atlantic/hw_atl/hw_atl_utils.h        | 16 ++++-
 6 files changed, 75 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
index bf9b3f0..3a8baae 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
@@ -163,6 +163,8 @@ struct aq_hw_ops {
  int (*hw_get_regs)(struct aq_hw_s *self,
    struct aq_hw_caps_s *aq_hw_caps, u32 *regs_buff);
 
+ int (*hw_update_stats)(struct aq_hw_s *self);
+
  int (*hw_get_hw_stats)(struct aq_hw_s *self, u64 *data,
        unsigned int *p_count);
 
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index 45a2a9b..935f67c 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -167,6 +167,9 @@ static void aq_nic_service_timer_cb(unsigned long param)
  self->aq_hw_ops.hw_interrupt_moderation_set(self->aq_hw,
     self->aq_nic_cfg.is_interrupt_moderation);
 
+ if (self->aq_hw_ops.hw_update_stats)
+ self->aq_hw_ops.hw_update_stats(self->aq_hw);
+
  memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s));
  memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s));
  for (i = AQ_DIMOF(self->aq_vec); i--;) {
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
index c5a02df..b0747b2 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
@@ -885,6 +885,7 @@ static struct aq_hw_ops hw_atl_ops_ = {
  .hw_rss_set                  = hw_atl_a0_hw_rss_set,
  .hw_rss_hash_set             = hw_atl_a0_hw_rss_hash_set,
  .hw_get_regs                 = hw_atl_utils_hw_get_regs,
+ .hw_update_stats             = hw_atl_utils_update_stats,
  .hw_get_hw_stats             = hw_atl_utils_get_hw_stats,
  .hw_get_fw_version           = hw_atl_utils_get_fw_version,
 };
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
index a399203..1bb8520 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
@@ -939,6 +939,7 @@ static struct aq_hw_ops hw_atl_ops_ = {
  .hw_rss_set                  = hw_atl_b0_hw_rss_set,
  .hw_rss_hash_set             = hw_atl_b0_hw_rss_hash_set,
  .hw_get_regs                 = hw_atl_utils_hw_get_regs,
+ .hw_update_stats             = hw_atl_utils_update_stats,
  .hw_get_hw_stats             = hw_atl_utils_get_hw_stats,
  .hw_get_fw_version           = hw_atl_utils_get_fw_version,
 };
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
index 4f5ec9a..58a9d2c 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
@@ -255,6 +255,15 @@ static int hw_atl_utils_mpi_create(struct aq_hw_s *self,
  return err;
 }
 
+int hw_atl_utils_mpi_read_mbox(struct aq_hw_s *self,
+       struct hw_aq_atl_utils_mbox_header *pmbox)
+{
+ return hw_atl_utils_fw_downld_dwords(self,
+      PHAL_ATLANTIC->mbox_addr,
+      (u32 *)(void *)pmbox,
+      sizeof(*pmbox) / sizeof(u32));
+}
+
 void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
  struct hw_aq_atl_utils_mbox *pmbox)
 {
@@ -267,9 +276,6 @@ void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
  if (err < 0)
  goto err_exit;
 
- if (pmbox != &PHAL_ATLANTIC->mbox)
- memcpy(pmbox, &PHAL_ATLANTIC->mbox, sizeof(*pmbox));
-
  if (IS_CHIP_FEATURE(REVISION_A0)) {
  unsigned int mtu = self->aq_nic_cfg ?
  self->aq_nic_cfg->mtu : 1514U;
@@ -299,17 +305,17 @@ void hw_atl_utils_mpi_set(struct aq_hw_s *self,
 {
  int err = 0;
  u32 transaction_id = 0;
+ struct hw_aq_atl_utils_mbox_header mbox;
 
  if (state == MPI_RESET) {
- hw_atl_utils_mpi_read_stats(self, &PHAL_ATLANTIC->mbox);
+ hw_atl_utils_mpi_read_mbox(self, &mbox);
 
- transaction_id = PHAL_ATLANTIC->mbox.transaction_id;
+ transaction_id = mbox.transaction_id;
 
  AQ_HW_WAIT_FOR(transaction_id !=
- (hw_atl_utils_mpi_read_stats
- (self, &PHAL_ATLANTIC->mbox),
- PHAL_ATLANTIC->mbox.transaction_id),
- 1000U, 100U);
+ (hw_atl_utils_mpi_read_mbox(self, &mbox),
+ mbox.transaction_id),
+       1000U, 100U);
  if (err < 0)
  goto err_exit;
  }
@@ -493,16 +499,51 @@ int hw_atl_utils_hw_set_power(struct aq_hw_s *self,
  return 0;
 }
 
+int hw_atl_utils_update_stats(struct aq_hw_s *self)
+{
+ struct hw_atl_s *hw_self = PHAL_ATLANTIC;
+ struct hw_aq_atl_utils_mbox mbox;
+
+ if (!self->aq_link_status.mbps)
+ return 0;
+
+ hw_atl_utils_mpi_read_stats(self, &mbox);
+
+#define AQ_SDELTA(_N_) (hw_self->curr_stats._N_ += \
+ mbox.stats._N_ - hw_self->last_stats._N_)
+
+ AQ_SDELTA(uprc);
+ AQ_SDELTA(mprc);
+ AQ_SDELTA(bprc);
+ AQ_SDELTA(erpt);
+
+ AQ_SDELTA(uptc);
+ AQ_SDELTA(mptc);
+ AQ_SDELTA(bptc);
+ AQ_SDELTA(erpr);
+
+ AQ_SDELTA(ubrc);
+ AQ_SDELTA(ubtc);
+ AQ_SDELTA(mbrc);
+ AQ_SDELTA(mbtc);
+ AQ_SDELTA(bbrc);
+ AQ_SDELTA(bbtc);
+ AQ_SDELTA(dpc);
+
+#undef AQ_SDELTA
+
+ memcpy(&hw_self->last_stats, &mbox.stats, sizeof(mbox.stats));
+
+ return 0;
+}
+
 int hw_atl_utils_get_hw_stats(struct aq_hw_s *self,
       u64 *data, unsigned int *p_count)
 {
- struct hw_atl_stats_s *stats = NULL;
+ struct hw_atl_s *hw_self = PHAL_ATLANTIC;
+ struct hw_atl_stats_s *stats = &hw_self->curr_stats;
  int i = 0;
 
- hw_atl_utils_mpi_read_stats(self, &PHAL_ATLANTIC->mbox);
-
- stats = &PHAL_ATLANTIC->mbox.stats;
-
  data[i] = stats->uprc + stats->mprc + stats->bprc;
  data[++i] = stats->uprc;
  data[++i] = stats->mprc;
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
index e0360a6..2218bdb 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
@@ -115,16 +115,21 @@ struct __packed hw_aq_atl_utils_fw_rpc {
  };
 };
 
-struct __packed hw_aq_atl_utils_mbox {
+struct __packed hw_aq_atl_utils_mbox_header {
  u32 version;
  u32 transaction_id;
- int error;
+ u32 error;
+};
+
+struct __packed hw_aq_atl_utils_mbox {
+ struct hw_aq_atl_utils_mbox_header header;
  struct hw_atl_stats_s stats;
 };
 
 struct __packed hw_atl_s {
  struct aq_hw_s base;
- struct hw_aq_atl_utils_mbox mbox;
+ struct hw_atl_stats_s last_stats;
+ struct hw_atl_stats_s curr_stats;
  u64 speed;
  u32 itr_tx;
  u32 itr_rx;
@@ -170,6 +175,9 @@ enum hal_atl_utils_fw_state_e {
 
 void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p);
 
+int hw_atl_utils_mpi_read_mbox(struct aq_hw_s *self,
+       struct hw_aq_atl_utils_mbox_header *pmbox);
+
 void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
  struct hw_aq_atl_utils_mbox *pmbox);
 
@@ -199,6 +207,8 @@ int hw_atl_utils_hw_deinit(struct aq_hw_s *self);
 
 int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version);
 
+int hw_atl_utils_update_stats(struct aq_hw_s *self);
+
 int hw_atl_utils_get_hw_stats(struct aq_hw_s *self,
       u64 *data,
       unsigned int *p_count);
--
2.7.4


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 4/9] net: aquantia: Enable coalescing management via ethtool interface

AceLan Kao
In reply to this post by AceLan Kao
From: Igor Russkikh <[hidden email]>

BugLink: http://bugs.launchpad.net/bugs/1730544

Aquantia NIC allows both TX and RX interrupt throttle rate (ITR)
management, but this was used in a very limited way via predefined
values. This patch allows to setup ITR default values via module
command line arguments and via standard ethtool coalescing settings.

Signed-off-by: Pavel Belous <[hidden email]>
Signed-off-by: Igor Russkikh <[hidden email]>
Signed-off-by: David S. Miller <[hidden email]>
(cherry picked from commit b82ee71a86b0ea66da79a91959d800ffb696a5cb)
Signed-off-by: AceLan Kao <[hidden email]>
---
 drivers/net/ethernet/aquantia/atlantic/aq_cfg.h    |  8 ++-
 .../net/ethernet/aquantia/atlantic/aq_ethtool.c    | 65 ++++++++++++++++++
 drivers/net/ethernet/aquantia/atlantic/aq_hw.h     |  3 +-
 drivers/net/ethernet/aquantia/atlantic/aq_nic.c    | 36 +++++++---
 drivers/net/ethernet/aquantia/atlantic/aq_nic.h    |  4 +-
 .../ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c  | 20 +++---
 .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c  | 76 ++++++++++++----------
 .../aquantia/atlantic/hw_atl/hw_atl_b0_internal.h  |  3 +
 .../aquantia/atlantic/hw_atl/hw_atl_utils.h        |  2 -
 9 files changed, 155 insertions(+), 62 deletions(-)

diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h
index 0fdaaa6..57e7968 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h
@@ -22,8 +22,12 @@
 
 #define AQ_CFG_FORCE_LEGACY_INT 0U
 
-#define AQ_CFG_IS_INTERRUPT_MODERATION_DEF   1U
-#define AQ_CFG_INTERRUPT_MODERATION_RATE_DEF 0xFFFFU
+#define AQ_CFG_INTERRUPT_MODERATION_OFF 0
+#define AQ_CFG_INTERRUPT_MODERATION_ON 1
+#define AQ_CFG_INTERRUPT_MODERATION_AUTO 0xFFFFU
+
+#define AQ_CFG_INTERRUPT_MODERATION_USEC_MAX (0x1FF * 2)
+
 #define AQ_CFG_IRQ_MASK                      0x1FFU
 
 #define AQ_CFG_VECS_MAX   8U
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
index a761e91..86f82bb 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
@@ -245,6 +245,69 @@ static int aq_ethtool_get_rxnfc(struct net_device *ndev,
  return err;
 }
 
+int aq_ethtool_get_coalesce(struct net_device *ndev,
+    struct ethtool_coalesce *coal)
+{
+ struct aq_nic_s *aq_nic = netdev_priv(ndev);
+ struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
+
+ if (cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON ||
+    cfg->itr == AQ_CFG_INTERRUPT_MODERATION_AUTO) {
+ coal->rx_coalesce_usecs = cfg->rx_itr;
+ coal->tx_coalesce_usecs = cfg->tx_itr;
+ coal->rx_max_coalesced_frames = 0;
+ coal->tx_max_coalesced_frames = 0;
+ } else {
+ coal->rx_coalesce_usecs = 0;
+ coal->tx_coalesce_usecs = 0;
+ coal->rx_max_coalesced_frames = 1;
+ coal->tx_max_coalesced_frames = 1;
+ }
+ return 0;
+}
+
+int aq_ethtool_set_coalesce(struct net_device *ndev,
+    struct ethtool_coalesce *coal)
+{
+ struct aq_nic_s *aq_nic = netdev_priv(ndev);
+ struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
+
+ /* This is not yet supported
+ */
+ if (coal->use_adaptive_rx_coalesce || coal->use_adaptive_tx_coalesce)
+ return -EOPNOTSUPP;
+
+ /* Atlantic only supports timing based coalescing
+ */
+ if (coal->rx_max_coalesced_frames > 1 ||
+    coal->rx_coalesce_usecs_irq ||
+    coal->rx_max_coalesced_frames_irq)
+ return -EOPNOTSUPP;
+
+ if (coal->tx_max_coalesced_frames > 1 ||
+    coal->tx_coalesce_usecs_irq ||
+    coal->tx_max_coalesced_frames_irq)
+ return -EOPNOTSUPP;
+
+ /* We do not support frame counting. Check this
+ */
+ if (!(coal->rx_max_coalesced_frames == !coal->rx_coalesce_usecs))
+ return -EOPNOTSUPP;
+ if (!(coal->tx_max_coalesced_frames == !coal->tx_coalesce_usecs))
+ return -EOPNOTSUPP;
+
+ if (coal->rx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX ||
+    coal->tx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX)
+ return -EINVAL;
+
+ cfg->itr = AQ_CFG_INTERRUPT_MODERATION_ON;
+
+ cfg->rx_itr = coal->rx_coalesce_usecs;
+ cfg->tx_itr = coal->tx_coalesce_usecs;
+
+ return aq_nic_update_interrupt_moderation_settings(aq_nic);
+}
+
 const struct ethtool_ops aq_ethtool_ops = {
  .get_link            = aq_ethtool_get_link,
  .get_regs_len        = aq_ethtool_get_regs_len,
@@ -259,4 +322,6 @@ const struct ethtool_ops aq_ethtool_ops = {
  .get_ethtool_stats   = aq_ethtool_stats,
  .get_link_ksettings  = aq_ethtool_get_link_ksettings,
  .set_link_ksettings  = aq_ethtool_set_link_ksettings,
+ .get_coalesce     = aq_ethtool_get_coalesce,
+ .set_coalesce     = aq_ethtool_set_coalesce,
 };
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
index 3a8baae..0207927 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
@@ -151,8 +151,7 @@ struct aq_hw_ops {
      [ETH_ALEN],
      u32 count);
 
- int (*hw_interrupt_moderation_set)(struct aq_hw_s *self,
-   bool itr_enabled);
+ int (*hw_interrupt_moderation_set)(struct aq_hw_s *self);
 
  int (*hw_rss_set)(struct aq_hw_s *self,
   struct aq_rss_parameters *rss_params);
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index 935f67c..5ba63d5 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -16,6 +16,7 @@
 #include "aq_pci_func.h"
 #include "aq_nic_internal.h"
 
+#include <linux/moduleparam.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/timer.h>
@@ -24,6 +25,18 @@
 #include <linux/tcp.h>
 #include <net/ip.h>
 
+static unsigned int aq_itr = AQ_CFG_INTERRUPT_MODERATION_AUTO;
+module_param_named(aq_itr, aq_itr, uint, 0644);
+MODULE_PARM_DESC(aq_itr, "Interrupt throttling mode");
+
+static unsigned int aq_itr_tx;
+module_param_named(aq_itr_tx, aq_itr_tx, uint, 0644);
+MODULE_PARM_DESC(aq_itr_tx, "TX interrupt throttle rate");
+
+static unsigned int aq_itr_rx;
+module_param_named(aq_itr_rx, aq_itr_rx, uint, 0644);
+MODULE_PARM_DESC(aq_itr_rx, "RX interrupt throttle rate");
+
 static void aq_nic_rss_init(struct aq_nic_s *self, unsigned int num_rss_queues)
 {
  struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg;
@@ -61,9 +74,9 @@ static void aq_nic_cfg_init_defaults(struct aq_nic_s *self)
 
  cfg->is_polling = AQ_CFG_IS_POLLING_DEF;
 
- cfg->is_interrupt_moderation = AQ_CFG_IS_INTERRUPT_MODERATION_DEF;
- cfg->itr = cfg->is_interrupt_moderation ?
- AQ_CFG_INTERRUPT_MODERATION_RATE_DEF : 0U;
+ cfg->itr = aq_itr;
+ cfg->tx_itr = aq_itr_tx;
+ cfg->rx_itr = aq_itr_rx;
 
  cfg->is_rss = AQ_CFG_IS_RSS_DEF;
  cfg->num_rss_queues = AQ_CFG_NUM_RSS_QUEUES_DEF;
@@ -126,10 +139,12 @@ static int aq_nic_update_link_status(struct aq_nic_s *self)
  if (err)
  return err;
 
- if (self->link_status.mbps != self->aq_hw->aq_link_status.mbps)
+ if (self->link_status.mbps != self->aq_hw->aq_link_status.mbps) {
  pr_info("%s: link change old %d new %d\n",
  AQ_CFG_DRV_NAME, self->link_status.mbps,
  self->aq_hw->aq_link_status.mbps);
+ aq_nic_update_interrupt_moderation_settings(self);
+ }
 
  self->link_status = self->aq_hw->aq_link_status;
  if (!netif_carrier_ok(self->ndev) && self->link_status.mbps) {
@@ -164,9 +179,6 @@ static void aq_nic_service_timer_cb(unsigned long param)
  if (err)
  goto err_exit;
 
- self->aq_hw_ops.hw_interrupt_moderation_set(self->aq_hw,
-    self->aq_nic_cfg.is_interrupt_moderation);
-
  if (self->aq_hw_ops.hw_update_stats)
  self->aq_hw_ops.hw_update_stats(self->aq_hw);
 
@@ -424,9 +436,8 @@ int aq_nic_start(struct aq_nic_s *self)
  if (err < 0)
  goto err_exit;
 
- err = self->aq_hw_ops.hw_interrupt_moderation_set(self->aq_hw,
-    self->aq_nic_cfg.is_interrupt_moderation);
- if (err < 0)
+ err = aq_nic_update_interrupt_moderation_settings(self);
+ if (err)
  goto err_exit;
  setup_timer(&self->service_timer, &aq_nic_service_timer_cb,
     (unsigned long)self);
@@ -639,6 +650,11 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb)
  return err;
 }
 
+int aq_nic_update_interrupt_moderation_settings(struct aq_nic_s *self)
+{
+ return self->aq_hw_ops.hw_interrupt_moderation_set(self->aq_hw);
+}
+
 int aq_nic_set_packet_filter(struct aq_nic_s *self, unsigned int flags)
 {
  int err = 0;
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
index 0ddd556..4309983 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
@@ -40,6 +40,8 @@ struct aq_nic_cfg_s {
  u32 vecs; /* vecs==allocated irqs */
  u32 irq_type;
  u32 itr;
+ u16 rx_itr;
+ u16 tx_itr;
  u32 num_rss_queues;
  u32 mtu;
  u32 ucp_0x364;
@@ -49,7 +51,6 @@ struct aq_nic_cfg_s {
  u16 is_mc_list_enabled;
  u16 mc_list_count;
  bool is_autoneg;
- bool is_interrupt_moderation;
  bool is_polling;
  bool is_rss;
  bool is_lro;
@@ -104,5 +105,6 @@ int aq_nic_set_link_ksettings(struct aq_nic_s *self,
 struct aq_nic_cfg_s *aq_nic_get_cfg(struct aq_nic_s *self);
 u32 aq_nic_get_fw_version(struct aq_nic_s *self);
 int aq_nic_change_pm_state(struct aq_nic_s *self, pm_message_t *pm_msg);
+int aq_nic_update_interrupt_moderation_settings(struct aq_nic_s *self);
 
 #endif /* AQ_NIC_H */
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
index b0747b2..07b3c49 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
@@ -765,24 +765,23 @@ static int hw_atl_a0_hw_multicast_list_set(struct aq_hw_s *self,
  return err;
 }
 
-static int hw_atl_a0_hw_interrupt_moderation_set(struct aq_hw_s *self,
- bool itr_enabled)
+static int hw_atl_a0_hw_interrupt_moderation_set(struct aq_hw_s *self)
 {
  unsigned int i = 0U;
+ u32 itr_rx;
 
- if (itr_enabled && self->aq_nic_cfg->itr) {
- if (self->aq_nic_cfg->itr != 0xFFFFU) {
+ if (self->aq_nic_cfg->itr) {
+ if (self->aq_nic_cfg->itr != AQ_CFG_INTERRUPT_MODERATION_AUTO) {
  u32 itr_ = (self->aq_nic_cfg->itr >> 1);
 
  itr_ = min(AQ_CFG_IRQ_MASK, itr_);
 
- PHAL_ATLANTIC_A0->itr_rx = 0x80000000U |
- (itr_ << 0x10);
+ itr_rx = 0x80000000U | (itr_ << 0x10);
  } else  {
  u32 n = 0xFFFFU & aq_hw_read_reg(self, 0x00002A00U);
 
  if (n < self->aq_link_status.mbps) {
- PHAL_ATLANTIC_A0->itr_rx = 0U;
+ itr_rx = 0U;
  } else {
  static unsigned int hw_timers_tbl_[] = {
  0x01CU, /* 10Gbit */
@@ -797,8 +796,7 @@ static int hw_atl_a0_hw_interrupt_moderation_set(struct aq_hw_s *self,
  hw_atl_utils_mbps_2_speed_index(
  self->aq_link_status.mbps);
 
- PHAL_ATLANTIC_A0->itr_rx =
- 0x80000000U |
+ itr_rx = 0x80000000U |
  (hw_timers_tbl_[speed_index] << 0x10U);
  }
 
@@ -806,11 +804,11 @@ static int hw_atl_a0_hw_interrupt_moderation_set(struct aq_hw_s *self,
  aq_hw_write_reg(self, 0x00002A00U, 0x8D000000U);
  }
  } else {
- PHAL_ATLANTIC_A0->itr_rx = 0U;
+ itr_rx = 0U;
  }
 
  for (i = HW_ATL_A0_RINGS_MAX; i--;)
- reg_irq_thr_set(self, PHAL_ATLANTIC_A0->itr_rx, i);
+ reg_irq_thr_set(self, itr_rx, i);
 
  return aq_hw_err_from_flags(self);
 }
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
index 1bb8520..ec68c20 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
@@ -788,31 +788,37 @@ static int hw_atl_b0_hw_multicast_list_set(struct aq_hw_s *self,
  return err;
 }
 
-static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self,
- bool itr_enabled)
+static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self)
 {
  unsigned int i = 0U;
+ u32 itr_tx = 2U;
+ u32 itr_rx = 2U;
 
- if (itr_enabled && self->aq_nic_cfg->itr) {
+ switch (self->aq_nic_cfg->itr) {
+ case  AQ_CFG_INTERRUPT_MODERATION_ON:
+ case  AQ_CFG_INTERRUPT_MODERATION_AUTO:
  tdm_tx_desc_wr_wb_irq_en_set(self, 0U);
  tdm_tdm_intr_moder_en_set(self, 1U);
  rdm_rx_desc_wr_wb_irq_en_set(self, 0U);
  rdm_rdm_intr_moder_en_set(self, 1U);
 
- PHAL_ATLANTIC_B0->itr_tx = 2U;
- PHAL_ATLANTIC_B0->itr_rx = 2U;
+ if (self->aq_nic_cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON) {
+ /* HW timers are in 2us units */
+ int tx_max_timer = self->aq_nic_cfg->tx_itr / 2;
+ int tx_min_timer = tx_max_timer / 2;
 
- if (self->aq_nic_cfg->itr != 0xFFFFU) {
- unsigned int max_timer = self->aq_nic_cfg->itr / 2U;
- unsigned int min_timer = self->aq_nic_cfg->itr / 32U;
+ int rx_max_timer = self->aq_nic_cfg->rx_itr / 2;
+ int rx_min_timer = rx_max_timer / 2;
 
- max_timer = min(0x1FFU, max_timer);
- min_timer = min(0xFFU, min_timer);
+ tx_max_timer = min(HW_ATL_INTR_MODER_MAX, tx_max_timer);
+ tx_min_timer = min(HW_ATL_INTR_MODER_MIN, tx_min_timer);
+ rx_max_timer = min(HW_ATL_INTR_MODER_MAX, rx_max_timer);
+ rx_min_timer = min(HW_ATL_INTR_MODER_MIN, rx_min_timer);
 
- PHAL_ATLANTIC_B0->itr_tx |= min_timer << 0x8U;
- PHAL_ATLANTIC_B0->itr_tx |= max_timer << 0x10U;
- PHAL_ATLANTIC_B0->itr_rx |= min_timer << 0x8U;
- PHAL_ATLANTIC_B0->itr_rx |= max_timer << 0x10U;
+ itr_tx |= tx_min_timer << 0x8U;
+ itr_tx |= tx_max_timer << 0x10U;
+ itr_rx |= rx_min_timer << 0x8U;
+ itr_rx |= rx_max_timer << 0x10U;
  } else {
  static unsigned int hw_atl_b0_timers_table_tx_[][2] = {
  {0xfU, 0xffU}, /* 10Gbit */
@@ -836,34 +842,36 @@ static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self,
  hw_atl_utils_mbps_2_speed_index(
  self->aq_link_status.mbps);
 
- PHAL_ATLANTIC_B0->itr_tx |=
- hw_atl_b0_timers_table_tx_[speed_index]
- [0] << 0x8U; /* set min timer value */
- PHAL_ATLANTIC_B0->itr_tx |=
- hw_atl_b0_timers_table_tx_[speed_index]
- [1] << 0x10U; /* set max timer value */
-
- PHAL_ATLANTIC_B0->itr_rx |=
- hw_atl_b0_timers_table_rx_[speed_index]
- [0] << 0x8U; /* set min timer value */
- PHAL_ATLANTIC_B0->itr_rx |=
- hw_atl_b0_timers_table_rx_[speed_index]
- [1] << 0x10U; /* set max timer value */
+ /* Update user visible ITR settings */
+ self->aq_nic_cfg->tx_itr = hw_atl_b0_timers_table_tx_
+ [speed_index][1] * 2;
+ self->aq_nic_cfg->rx_itr = hw_atl_b0_timers_table_rx_
+ [speed_index][1] * 2;
+
+ itr_tx |= hw_atl_b0_timers_table_tx_
+ [speed_index][0] << 0x8U;
+ itr_tx |= hw_atl_b0_timers_table_tx_
+ [speed_index][1] << 0x10U;
+
+ itr_rx |= hw_atl_b0_timers_table_rx_
+ [speed_index][0] << 0x8U;
+ itr_rx |= hw_atl_b0_timers_table_rx_
+ [speed_index][1] << 0x10U;
  }
- } else {
+ break;
+ case AQ_CFG_INTERRUPT_MODERATION_OFF:
  tdm_tx_desc_wr_wb_irq_en_set(self, 1U);
  tdm_tdm_intr_moder_en_set(self, 0U);
  rdm_rx_desc_wr_wb_irq_en_set(self, 1U);
  rdm_rdm_intr_moder_en_set(self, 0U);
- PHAL_ATLANTIC_B0->itr_tx = 0U;
- PHAL_ATLANTIC_B0->itr_rx = 0U;
+ itr_tx = 0U;
+ itr_rx = 0U;
+ break;
  }
 
  for (i = HW_ATL_B0_RINGS_MAX; i--;) {
- reg_tx_intr_moder_ctrl_set(self,
-   PHAL_ATLANTIC_B0->itr_tx, i);
- reg_rx_intr_moder_ctrl_set(self,
-   PHAL_ATLANTIC_B0->itr_rx, i);
+ reg_tx_intr_moder_ctrl_set(self, itr_tx, i);
+ reg_rx_intr_moder_ctrl_set(self, itr_rx, i);
  }
 
  return aq_hw_err_from_flags(self);
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h
index f3957e93..120f058 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h
@@ -139,6 +139,9 @@
 
 #define HW_ATL_B0_FW_VER_EXPECTED 0x01050006U
 
+#define HW_ATL_INTR_MODER_MAX  0x1FF
+#define HW_ATL_INTR_MODER_MIN  0xFF
+
 /* Hardware tx descriptor */
 struct __packed hw_atl_txd_s {
  u64 buf_addr;
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
index 2218bdb..c99cc69 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
@@ -131,8 +131,6 @@ struct __packed hw_atl_s {
  struct hw_atl_stats_s last_stats;
  struct hw_atl_stats_s curr_stats;
  u64 speed;
- u32 itr_tx;
- u32 itr_rx;
  unsigned int chip_features;
  u32 fw_ver_actual;
  atomic_t dpc;
--
2.7.4


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 5/9] net: aquantia: mmio unmap was not performed on driver removal

AceLan Kao
In reply to this post by AceLan Kao
From: Igor Russkikh <[hidden email]>

BugLink: http://bugs.launchpad.net/bugs/1730544

That may lead to mmio resource leakage.

Signed-off-by: Pavel Belous <[hidden email]>
Signed-off-by: Igor Russkikh <[hidden email]>
Signed-off-by: David S. Miller <[hidden email]>
(cherry picked from commit 6849540adc0bcc8c648d7c11be169d2ca267fbca)
Signed-off-by: AceLan Kao <[hidden email]>
---
 drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
index 4c6c882..dca1b86 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
@@ -265,6 +265,9 @@ void aq_pci_func_free(struct aq_pci_func_s *self)
  aq_nic_ndev_free(self->port[port]);
  }
 
+ if (self->mmio)
+ iounmap(self->mmio);
+
  kfree(self);
 
 err_exit:;
--
2.7.4


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 6/9] net: aquantia: Limit number of MSIX irqs to the number of cpus

AceLan Kao
In reply to this post by AceLan Kao
From: Igor Russkikh <[hidden email]>

BugLink: http://bugs.launchpad.net/bugs/1730544

There is no much practical use from having MSIX vectors more that number
of cpus, thus cap this first with preconfigured limit, then with number
of cpus online.

Signed-off-by: Pavel Belous <[hidden email]>
Signed-off-by: Igor Russkikh <[hidden email]>
Signed-off-by: David S. Miller <[hidden email]>
(cherry picked from commit 4c8bb609d304df72858aa2e5e74abab5246bd24b)
Signed-off-by: AceLan Kao <[hidden email]>
---
 drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
index dca1b86..cadaa64 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
@@ -85,6 +85,7 @@ int aq_pci_func_init(struct aq_pci_func_s *self)
  int err = 0;
  unsigned int bar = 0U;
  unsigned int port = 0U;
+ unsigned int numvecs = 0U;
 
  err = pci_enable_device(self->pdev);
  if (err < 0)
@@ -142,10 +143,12 @@ int aq_pci_func_init(struct aq_pci_func_s *self)
  }
  }
 
- /*enable interrupts */
+ numvecs = min((u8)AQ_CFG_VECS_DEF, self->aq_hw_caps.msix_irqs);
+ numvecs = min(numvecs, num_online_cpus());
+
+ /* enable interrupts */
 #if !AQ_CFG_FORCE_LEGACY_INT
- err = pci_alloc_irq_vectors(self->pdev, self->aq_hw_caps.msix_irqs,
-      self->aq_hw_caps.msix_irqs, PCI_IRQ_MSIX);
+ err = pci_alloc_irq_vectors(self->pdev, numvecs, numvecs, PCI_IRQ_MSIX);
 
  if (err < 0) {
  err = pci_alloc_irq_vectors(self->pdev, 1, 1,
@@ -153,7 +156,7 @@ int aq_pci_func_init(struct aq_pci_func_s *self)
  if (err < 0)
  goto err_exit;
  }
-#endif
+#endif /* AQ_CFG_FORCE_LEGACY_INT */
 
  /* net device init */
  for (port = 0; port < self->ports; ++port) {
--
2.7.4


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 7/9] net: aquantia: Fixed transient link up/down/up notification

AceLan Kao
In reply to this post by AceLan Kao
From: Igor Russkikh <[hidden email]>

BugLink: http://bugs.launchpad.net/bugs/1730544

When doing ifconfig down/up, driver did not reported carrier_off neither
in nic_stop nor in nic_start. That caused link to be visible as "up"
during couple of seconds immediately after "ifconfig up".

Signed-off-by: Pavel Belous <[hidden email]>
Signed-off-by: Igor Russkikh <[hidden email]>
Signed-off-by: David S. Miller <[hidden email]>
(cherry picked from commit 93d87b8fbe6cf17f0ad9552a934b5a6623ccd7d1)
Signed-off-by: AceLan Kao <[hidden email]>
---
 drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index 5ba63d5..c628089 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -349,6 +349,7 @@ struct aq_nic_s *aq_nic_alloc_hot(struct net_device *ndev)
  }
  if (netif_running(ndev))
  netif_tx_disable(ndev);
+ netif_carrier_off(self->ndev);
 
  for (self->aq_vecs = 0; self->aq_vecs < self->aq_nic_cfg.vecs;
  self->aq_vecs++) {
@@ -916,6 +917,7 @@ int aq_nic_stop(struct aq_nic_s *self)
  unsigned int i = 0U;
 
  netif_tx_disable(self->ndev);
+ netif_carrier_off(self->ndev);
 
  del_timer_sync(&self->service_timer);
 
--
2.7.4


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 8/9] net: aquantia: Add queue restarts stats counter

AceLan Kao
In reply to this post by AceLan Kao
From: Igor Russkikh <[hidden email]>

BugLink: http://bugs.launchpad.net/bugs/1730544

Queue stat strings are cleaned up, duplicate stat name strings removed,
queue restarts counter added

Signed-off-by: Pavel Belous <[hidden email]>
Signed-off-by: Igor Russkikh <[hidden email]>
Signed-off-by: David S. Miller <[hidden email]>
(cherry picked from commit 5d8d84e91d7432cd206b27ad791a11220689ac53)
Signed-off-by: AceLan Kao <[hidden email]>
---
 .../net/ethernet/aquantia/atlantic/aq_ethtool.c    | 92 ++++++++--------------
 drivers/net/ethernet/aquantia/atlantic/aq_vec.c    |  3 +
 2 files changed, 37 insertions(+), 58 deletions(-)

diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
index 86f82bb..d5e99b4 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
@@ -56,10 +56,6 @@ aq_ethtool_set_link_ksettings(struct net_device *ndev,
  return aq_nic_set_link_ksettings(aq_nic, cmd);
 }
 
-/* there "5U" is number of queue[#] stats lines (InPackets+...+InErrors) */
-static const unsigned int aq_ethtool_stat_queue_lines = 5U;
-static const unsigned int aq_ethtool_stat_queue_chars =
- 5U * ETH_GSTRING_LEN;
 static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
  "InPackets",
  "InUCast",
@@ -83,56 +79,26 @@ static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
  "InOctetsDma",
  "OutOctetsDma",
  "InDroppedDma",
- "Queue[0] InPackets",
- "Queue[0] OutPackets",
- "Queue[0] InJumboPackets",
- "Queue[0] InLroPackets",
- "Queue[0] InErrors",
- "Queue[1] InPackets",
- "Queue[1] OutPackets",
- "Queue[1] InJumboPackets",
- "Queue[1] InLroPackets",
- "Queue[1] InErrors",
- "Queue[2] InPackets",
- "Queue[2] OutPackets",
- "Queue[2] InJumboPackets",
- "Queue[2] InLroPackets",
- "Queue[2] InErrors",
- "Queue[3] InPackets",
- "Queue[3] OutPackets",
- "Queue[3] InJumboPackets",
- "Queue[3] InLroPackets",
- "Queue[3] InErrors",
- "Queue[4] InPackets",
- "Queue[4] OutPackets",
- "Queue[4] InJumboPackets",
- "Queue[4] InLroPackets",
- "Queue[4] InErrors",
- "Queue[5] InPackets",
- "Queue[5] OutPackets",
- "Queue[5] InJumboPackets",
- "Queue[5] InLroPackets",
- "Queue[5] InErrors",
- "Queue[6] InPackets",
- "Queue[6] OutPackets",
- "Queue[6] InJumboPackets",
- "Queue[6] InLroPackets",
- "Queue[6] InErrors",
- "Queue[7] InPackets",
- "Queue[7] OutPackets",
- "Queue[7] InJumboPackets",
- "Queue[7] InLroPackets",
- "Queue[7] InErrors",
+};
+
+static const char aq_ethtool_queue_stat_names[][ETH_GSTRING_LEN] = {
+ "Queue[%d] InPackets",
+ "Queue[%d] OutPackets",
+ "Queue[%d] Restarts",
+ "Queue[%d] InJumboPackets",
+ "Queue[%d] InLroPackets",
+ "Queue[%d] InErrors",
 };
 
 static void aq_ethtool_stats(struct net_device *ndev,
      struct ethtool_stats *stats, u64 *data)
 {
  struct aq_nic_s *aq_nic = netdev_priv(ndev);
+ struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
 
-/* ASSERT: Need add lines to aq_ethtool_stat_names if AQ_CFG_VECS_MAX > 8 */
- BUILD_BUG_ON(AQ_CFG_VECS_MAX > 8);
- memset(data, 0, ARRAY_SIZE(aq_ethtool_stat_names) * sizeof(u64));
+ memset(data, 0, (ARRAY_SIZE(aq_ethtool_stat_names) +
+ ARRAY_SIZE(aq_ethtool_queue_stat_names) *
+ cfg->vecs) * sizeof(u64));
  aq_nic_get_stats(aq_nic, data);
 }
 
@@ -154,8 +120,8 @@ static void aq_ethtool_get_drvinfo(struct net_device *ndev,
 
  strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "",
  sizeof(drvinfo->bus_info));
- drvinfo->n_stats = ARRAY_SIZE(aq_ethtool_stat_names) -
- (AQ_CFG_VECS_MAX - cfg->vecs) * aq_ethtool_stat_queue_lines;
+ drvinfo->n_stats = ARRAY_SIZE(aq_ethtool_stat_names) +
+ cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names);
  drvinfo->testinfo_len = 0;
  drvinfo->regdump_len = regs_count;
  drvinfo->eedump_len = 0;
@@ -164,14 +130,25 @@ static void aq_ethtool_get_drvinfo(struct net_device *ndev,
 static void aq_ethtool_get_strings(struct net_device *ndev,
    u32 stringset, u8 *data)
 {
+ int i, si;
  struct aq_nic_s *aq_nic = netdev_priv(ndev);
  struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
-
- if (stringset == ETH_SS_STATS)
- memcpy(data, *aq_ethtool_stat_names,
-       sizeof(aq_ethtool_stat_names) -
-       (AQ_CFG_VECS_MAX - cfg->vecs) *
-       aq_ethtool_stat_queue_chars);
+ u8 *p = data;
+
+ if (stringset == ETH_SS_STATS) {
+ memcpy(p, *aq_ethtool_stat_names,
+       sizeof(aq_ethtool_stat_names));
+ p = p + sizeof(aq_ethtool_stat_names);
+ for (i = 0; i < cfg->vecs; i++) {
+ for (si = 0;
+ si < ARRAY_SIZE(aq_ethtool_queue_stat_names);
+ si++) {
+ snprintf(p, ETH_GSTRING_LEN,
+ aq_ethtool_queue_stat_names[si], i);
+ p += ETH_GSTRING_LEN;
+ }
+ }
+ }
 }
 
 static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)
@@ -182,9 +159,8 @@ static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)
 
  switch (stringset) {
  case ETH_SS_STATS:
- ret = ARRAY_SIZE(aq_ethtool_stat_names) -
- (AQ_CFG_VECS_MAX - cfg->vecs) *
- aq_ethtool_stat_queue_lines;
+ ret = ARRAY_SIZE(aq_ethtool_stat_names) +
+ cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names);
  break;
  default:
  ret = -EOPNOTSUPP;
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c
index 996160b..fe1c4bd 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c
@@ -372,8 +372,11 @@ int aq_vec_get_sw_stats(struct aq_vec_s *self, u64 *data, unsigned int *p_count)
  memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s));
  aq_vec_add_stats(self, &stats_rx, &stats_tx);
 
+ /* This data should mimic aq_ethtool_queue_stat_names structure
+ */
  data[count] += stats_rx.packets;
  data[++count] += stats_tx.packets;
+ data[++count] += stats_tx.queue_restarts;
  data[++count] += stats_rx.jumbo_packets;
  data[++count] += stats_rx.lro_packets;
  data[++count] += stats_rx.errors;
--
2.7.4


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 9/9] net: aquantia: Reset nic statistics on interface up/down

AceLan Kao
In reply to this post by AceLan Kao
From: Igor Russkikh <[hidden email]>

BugLink: http://bugs.launchpad.net/bugs/1730544

Internal statistics system on chip never gets reset until hardware
reboot. This is quite inconvenient in terms of ethtool statistics usage.

This patch implements incremental statistics update inside of
service callback.

Upon nic initialization, first request is done to fetch
initial stat data, current collected stat data gets cleared.
Internal statistics mailbox readout is improved to save space and
increase readability

Signed-off-by: Pavel Belous <[hidden email]>
Signed-off-by: Igor Russkikh <[hidden email]>
Signed-off-by: David S. Miller <[hidden email]>
(cherry picked from commit 65e665e68d097edfe667372f13d54f3e4edcb69c)
Signed-off-by: AceLan Kao <[hidden email]>
---
 drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index c628089..a9176e4 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -182,6 +182,9 @@ static void aq_nic_service_timer_cb(unsigned long param)
  if (self->aq_hw_ops.hw_update_stats)
  self->aq_hw_ops.hw_update_stats(self->aq_hw);
 
+ if (self->aq_hw_ops.hw_update_stats)
+ self->aq_hw_ops.hw_update_stats(self->aq_hw);
+
  memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s));
  memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s));
  for (i = AQ_DIMOF(self->aq_vec); i--;) {
--
2.7.4


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

ACK: [PATCH 0/9][linux-oem] Enable AQUANTIA AQC107 10G & 2.5/5Gb NICs

Wen-chien Jesse Sung
In reply to this post by AceLan Kao
Clean cherry-pick, and changes are in the driver only.

Acked-By: Wen-chien Jesse Sung <[hidden email]>


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

ACK: [PATCH 0/9][linux-oem] Enable AQUANTIA AQC107 10G & 2.5/5Gb NICs

Stefan Bader-2
In reply to this post by AceLan Kao
On 07.11.2017 02:51, AceLan Kao wrote:

> BugLink: http://bugs.launchpad.net/bugs/1730544
>
> From vendor's suggestion, there are some patches in v4.14-rc6
> are required to enable the 2 NICs.
> AQUANTIA AQC107 10G[1D6A:0001] & 2.5/5Gb [1D6A:D108] NIC
>
> 417a3ae net: aquantia: Bad udp rate on default interrupt coalescing
> b82ee71 net: aquantia: Enable coalescing management via ethtool interface
> 6849540 net: aquantia: mmio unmap was not performed on driver removal
> 4c8bb60 net: aquantia: Limit number of MSIX irqs to the number of cpus
> 93d87b8 net: aquantia: Fixed transient link up/down/up notification
> 5d8d84e net: aquantia: Add queue restarts stats counter
> 65e665e net: aquantia: Reset nic statistics on interface up/down
>
> And to avoid conflict, cherry pick 2 more commits
>
> 3aec641 aquantia: Fix Tx queue hangups
> 65e665e net: aquantia: Reset nic statistics on interface up/down
>
> Igor Russkikh (9):
>   net: aquantia: Bad udp rate on default interrupt coalescing
>   aquantia: Fix Tx queue hangups
>   net: aquantia: Reset nic statistics on interface up/down
>   net: aquantia: Enable coalescing management via ethtool interface
>   net: aquantia: mmio unmap was not performed on driver removal
>   net: aquantia: Limit number of MSIX irqs to the number of cpus
>   net: aquantia: Fixed transient link up/down/up notification
>   net: aquantia: Add queue restarts stats counter
>   net: aquantia: Reset nic statistics on interface up/down
>
>  drivers/net/ethernet/aquantia/atlantic/aq_cfg.h    |  12 +-
>  .../net/ethernet/aquantia/atlantic/aq_ethtool.c    | 157 +++++++++++++--------
>  drivers/net/ethernet/aquantia/atlantic/aq_hw.h     |   5 +-
>  drivers/net/ethernet/aquantia/atlantic/aq_nic.c    | 129 +++++++++--------
>  drivers/net/ethernet/aquantia/atlantic/aq_nic.h    |   6 +-
>  .../net/ethernet/aquantia/atlantic/aq_pci_func.c   |  14 +-
>  drivers/net/ethernet/aquantia/atlantic/aq_ring.c   |  26 ++++
>  drivers/net/ethernet/aquantia/atlantic/aq_ring.h   |   4 +
>  drivers/net/ethernet/aquantia/atlantic/aq_vec.c    |  11 +-
>  .../ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c  |  21 ++-
>  .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c  |  89 ++++++------
>  .../aquantia/atlantic/hw_atl/hw_atl_b0_internal.h  |   3 +
>  .../aquantia/atlantic/hw_atl/hw_atl_utils.c        |  69 +++++++--
>  .../aquantia/atlantic/hw_atl/hw_atl_utils.h        |  18 ++-
>  14 files changed, 361 insertions(+), 203 deletions(-)
>
At least isolated to a single driver (testable) and from the 4.14 upstream, so:

Acked-by: Stefan Bader <[hidden email]>



--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team

signature.asc (836 bytes) Download Attachment