* [PATCH v2 net-next 01/16] net: aquantia: add infrastructure to readout chip temperature
2019-04-23 13:17 [PATCH v2 net-next 00/16] net: atlantic: Aquantia driver updates 2019-04 Igor Russkikh
@ 2019-04-23 13:17 ` Igor Russkikh
2019-04-23 19:12 ` Andrew Lunn
2019-04-23 13:17 ` [PATCH v2 net-next 02/16] net: aquantia: implement hwmon api for " Igor Russkikh
` (14 subsequent siblings)
15 siblings, 1 reply; 24+ messages in thread
From: Igor Russkikh @ 2019-04-23 13:17 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Nikita Danilov, Dmitry Bogdanov, Igor Russkikh, Yana Esina
From: Yana Esina <yana.esina@aquantia.com>
Ability to read the chip temperature from memory
via hwmon interface
Signed-off-by: Yana Esina <yana.esina@aquantia.com>
Signed-off-by: Nikita Danilov <nikita.danilov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
.../net/ethernet/aquantia/atlantic/aq_hw.h | 2 ++
.../aquantia/atlantic/hw_atl/hw_atl_utils.c | 1 +
.../atlantic/hw_atl/hw_atl_utils_fw2x.c | 36 +++++++++++++++++++
3 files changed, 39 insertions(+)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
index 81aab73dc22f..538593261ae3 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
@@ -259,6 +259,8 @@ struct aq_fw_ops {
int (*update_stats)(struct aq_hw_s *self);
+ int (*get_temp)(struct aq_hw_s *self, int *temp);
+
u32 (*get_flow_control)(struct aq_hw_s *self, u32 *fcmode);
int (*set_flow_control)(struct aq_hw_s *self);
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 eb4b99d56081..35df424e3af3 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
@@ -960,6 +960,7 @@ const struct aq_fw_ops aq_fw_1x_ops = {
.set_state = hw_atl_utils_mpi_set_state,
.update_link_status = hw_atl_utils_mpi_get_link_status,
.update_stats = hw_atl_utils_update_stats,
+ .get_temp = NULL,
.set_power = aq_fw1x_set_power,
.set_eee_rate = NULL,
.get_eee_rate = NULL,
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c
index fe6c5658e016..a0515067d912 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c
@@ -38,6 +38,7 @@
#define HW_ATL_FW2X_CTRL_WOL BIT(CTRL_WOL)
#define HW_ATL_FW2X_CTRL_LINK_DROP BIT(CTRL_LINK_DROP)
#define HW_ATL_FW2X_CTRL_PAUSE BIT(CTRL_PAUSE)
+#define HW_ATL_FW2X_CTRL_TEMPERATURE BIT(CTRL_TEMPERATURE)
#define HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE BIT(CTRL_ASYMMETRIC_PAUSE)
#define HW_ATL_FW2X_CTRL_FORCE_RECONNECT BIT(CTRL_FORCE_RECONNECT)
@@ -310,6 +311,40 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
return hw_atl_utils_update_stats(self);
}
+static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
+{
+ u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
+ u32 temp_val = mpi_opts & HW_ATL_FW2X_CTRL_TEMPERATURE;
+ u32 phy_temp_offset;
+ u32 temp_res;
+ int err = 0;
+ u32 val;
+
+ phy_temp_offset = self->mbox_addr +
+ offsetof(struct hw_atl_utils_mbox, info) +
+ offsetof(struct hw_aq_info, phy_temperature);
+ /* Toggle statistics bit for FW to 0x36C.18 (CTRL_TEMPERATURE) */
+ mpi_opts = mpi_opts ^ HW_ATL_FW2X_CTRL_TEMPERATURE;
+ aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
+ /* Wait FW to report back */
+ err = readx_poll_timeout_atomic(aq_fw2x_state2_get, self, val,
+ temp_val !=
+ (val & HW_ATL_FW2X_CTRL_TEMPERATURE),
+ 1U, 10000U);
+ err = hw_atl_utils_fw_downld_dwords(self, phy_temp_offset,
+ &temp_res, 1);
+
+ if (err)
+ return err;
+
+ /* Convert PHY temperature from 1/256 degree Celsius
+ * to 1/1000 degree Celsius.
+ */
+ *temp = temp_res * 1000 / 256;
+
+ return 0;
+}
+
static int aq_fw2x_set_sleep_proxy(struct aq_hw_s *self, u8 *mac)
{
struct hw_atl_utils_fw_rpc *rpc = NULL;
@@ -509,6 +544,7 @@ const struct aq_fw_ops aq_fw_2x_ops = {
.set_state = aq_fw2x_set_state,
.update_link_status = aq_fw2x_update_link_status,
.update_stats = aq_fw2x_update_stats,
+ .get_temp = aq_fw2x_get_temp,
.set_power = aq_fw2x_set_power,
.set_eee_rate = aq_fw2x_set_eee_rate,
.get_eee_rate = aq_fw2x_get_eee_rate,
--
2.17.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH v2 net-next 01/16] net: aquantia: add infrastructure to readout chip temperature
2019-04-23 13:17 ` [PATCH v2 net-next 01/16] net: aquantia: add infrastructure to readout chip temperature Igor Russkikh
@ 2019-04-23 19:12 ` Andrew Lunn
2019-04-24 8:29 ` Igor Russkikh
0 siblings, 1 reply; 24+ messages in thread
From: Andrew Lunn @ 2019-04-23 19:12 UTC (permalink / raw)
To: Igor Russkikh
Cc: David S . Miller, netdev, Nikita Danilov, Dmitry Bogdanov, Yana Esina
On Tue, Apr 23, 2019 at 01:17:29PM +0000, Igor Russkikh wrote:
> From: Yana Esina <yana.esina@aquantia.com>
>
> Ability to read the chip temperature from memory
> via hwmon interface
>
> Signed-off-by: Yana Esina <yana.esina@aquantia.com>
> Signed-off-by: Nikita Danilov <nikita.danilov@aquantia.com>
> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
> ---
> .../net/ethernet/aquantia/atlantic/aq_hw.h | 2 ++
> .../aquantia/atlantic/hw_atl/hw_atl_utils.c | 1 +
> .../atlantic/hw_atl/hw_atl_utils_fw2x.c | 36 +++++++++++++++++++
> 3 files changed, 39 insertions(+)
>
> diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
> index 81aab73dc22f..538593261ae3 100644
> --- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
> +++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
> @@ -259,6 +259,8 @@ struct aq_fw_ops {
>
> int (*update_stats)(struct aq_hw_s *self);
>
> + int (*get_temp)(struct aq_hw_s *self, int *temp);
> +
We talked about renaming this get_phy_temp so you could later add
get_mac_temp?
Andrew
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 net-next 01/16] net: aquantia: add infrastructure to readout chip temperature
2019-04-23 19:12 ` Andrew Lunn
@ 2019-04-24 8:29 ` Igor Russkikh
0 siblings, 0 replies; 24+ messages in thread
From: Igor Russkikh @ 2019-04-24 8:29 UTC (permalink / raw)
To: Andrew Lunn
Cc: David S . Miller, netdev, Nikita Danilov, Dmitry Bogdanov, Yana Esina
>>
>> + int (*get_temp)(struct aq_hw_s *self, int *temp);
>> +
>
> We talked about renaming this get_phy_temp so you could later add
> get_mac_temp?
Lost that comment, sorry. Will do rename.
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v2 net-next 02/16] net: aquantia: implement hwmon api for chip temperature
2019-04-23 13:17 [PATCH v2 net-next 00/16] net: atlantic: Aquantia driver updates 2019-04 Igor Russkikh
2019-04-23 13:17 ` [PATCH v2 net-next 01/16] net: aquantia: add infrastructure to readout chip temperature Igor Russkikh
@ 2019-04-23 13:17 ` Igor Russkikh
2019-04-23 19:17 ` Andrew Lunn
2019-04-23 13:17 ` [PATCH v2 net-next 03/16] net: aquantia: add link interrupt fields Igor Russkikh
` (13 subsequent siblings)
15 siblings, 1 reply; 24+ messages in thread
From: Igor Russkikh @ 2019-04-23 13:17 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Nikita Danilov, Dmitry Bogdanov, Igor Russkikh, Yana Esina
From: Yana Esina <yana.esina@aquantia.com>
Added support for hwmon api to fetch out chip temperature
Signed-off-by: Yana Esina <yana.esina@aquantia.com>
Signed-off-by: Nikita Danilov <nikita.danilov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
.../net/ethernet/aquantia/atlantic/Makefile | 1 +
.../ethernet/aquantia/atlantic/aq_drvinfo.c | 129 ++++++++++++++++++
.../ethernet/aquantia/atlantic/aq_drvinfo.h | 16 +++
.../ethernet/aquantia/atlantic/aq_pci_func.c | 4 +
4 files changed, 150 insertions(+)
create mode 100644 drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.c
create mode 100644 drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.h
diff --git a/drivers/net/ethernet/aquantia/atlantic/Makefile b/drivers/net/ethernet/aquantia/atlantic/Makefile
index 4556630ee286..1f99cf832476 100644
--- a/drivers/net/ethernet/aquantia/atlantic/Makefile
+++ b/drivers/net/ethernet/aquantia/atlantic/Makefile
@@ -36,6 +36,7 @@ atlantic-objs := aq_main.o \
aq_ring.o \
aq_hw_utils.o \
aq_ethtool.o \
+ aq_drvinfo.o \
aq_filters.o \
hw_atl/hw_atl_a0.o \
hw_atl/hw_atl_b0.o \
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.c b/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.c
new file mode 100644
index 000000000000..ca2ffd6432e8
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Copyright (C) 2014-2019 aQuantia Corporation. */
+
+/* File aq_drvinfo.c: Definition of common code for firmware info in sys.*/
+
+#include <linux/init.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/hwmon.h>
+#include <linux/uaccess.h>
+
+#include "aq_drvinfo.h"
+
+static int aq_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *value)
+{
+ struct aq_nic_s *aq_nic = dev_get_drvdata(dev);
+ int temp;
+ int err;
+
+ if (!aq_nic)
+ return -EIO;
+
+ if (type != hwmon_temp)
+ return -EOPNOTSUPP;
+
+ if (!aq_nic->aq_fw_ops->get_temp)
+ return -EOPNOTSUPP;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ err = aq_nic->aq_fw_ops->get_temp(aq_nic->aq_hw, &temp);
+ *value = temp;
+ return err;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int aq_hwmon_read_string(struct device *dev,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel, const char **str)
+{
+ struct aq_nic_s *aq_nic = dev_get_drvdata(dev);
+
+ if (!aq_nic)
+ return -EIO;
+
+ if (type != hwmon_temp)
+ return -EOPNOTSUPP;
+
+ if (!aq_nic->aq_fw_ops->get_temp)
+ return -EOPNOTSUPP;
+
+ switch (attr) {
+ case hwmon_temp_label:
+ *str = "PHY Temperature";
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static umode_t aq_hwmon_is_visible(const void *data,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ if (type != hwmon_temp)
+ return 0;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ case hwmon_temp_label:
+ return 0444;
+ default:
+ return 0;
+ }
+}
+
+static const struct hwmon_ops aq_hwmon_ops = {
+ .is_visible = aq_hwmon_is_visible,
+ .read = aq_hwmon_read,
+ .read_string = aq_hwmon_read_string,
+};
+
+static u32 aq_hwmon_temp_config[] = {
+ HWMON_T_INPUT | HWMON_T_LABEL,
+ 0,
+};
+
+static const struct hwmon_channel_info aq_hwmon_temp = {
+ .type = hwmon_temp,
+ .config = aq_hwmon_temp_config,
+};
+
+static const struct hwmon_channel_info *aq_hwmon_info[] = {
+ &aq_hwmon_temp,
+ NULL,
+};
+
+static const struct hwmon_chip_info aq_hwmon_chip_info = {
+ .ops = &aq_hwmon_ops,
+ .info = aq_hwmon_info,
+};
+
+int aq_drvinfo_init(struct net_device *ndev)
+{
+ struct aq_nic_s *aq_nic = netdev_priv(ndev);
+ struct device *dev = &aq_nic->pdev->dev;
+ struct device *hwmon_dev;
+ int err = 0;
+
+ hwmon_dev = devm_hwmon_device_register_with_info(dev,
+ ndev->name,
+ aq_nic,
+ &aq_hwmon_chip_info,
+ NULL);
+
+ if (IS_ERR(hwmon_dev))
+ err = PTR_ERR(hwmon_dev);
+
+ return err;
+}
+
+void aq_drvinfo_exit(struct net_device *ndev)
+{
+}
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.h b/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.h
new file mode 100644
index 000000000000..4adb1f84f550
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Copyright (C) 2014-2017 aQuantia Corporation. */
+
+/* File aq_drvinfo.h: Declaration of common code for firmware info in sys.*/
+
+#ifndef AQ_DRVINFO_H
+#define AQ_DRVINFO_H
+
+#include "aq_nic.h"
+#include "aq_hw.h"
+#include "hw_atl/hw_atl_utils.h"
+
+int aq_drvinfo_init(struct net_device *ndev);
+void aq_drvinfo_exit(struct net_device *ndev);
+
+#endif /* AQ_DRVINFO_H */
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
index 0217ff4669a4..556b735e5a32 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
@@ -20,6 +20,7 @@
#include "hw_atl/hw_atl_a0.h"
#include "hw_atl/hw_atl_b0.h"
#include "aq_filters.h"
+#include "aq_drvinfo.h"
static const struct pci_device_id aq_pci_tbl[] = {
{ PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_0001), },
@@ -289,6 +290,8 @@ static int aq_pci_probe(struct pci_dev *pdev,
if (err < 0)
goto err_register;
+ aq_drvinfo_init(ndev);
+
return 0;
err_register:
@@ -317,6 +320,7 @@ static void aq_pci_remove(struct pci_dev *pdev)
unregister_netdev(self->ndev);
aq_nic_free_vectors(self);
aq_pci_free_irq_vectors(self);
+ aq_drvinfo_exit(self->ndev);
iounmap(self->aq_hw->mmio);
kfree(self->aq_hw);
pci_release_regions(pdev);
--
2.17.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH v2 net-next 02/16] net: aquantia: implement hwmon api for chip temperature
2019-04-23 13:17 ` [PATCH v2 net-next 02/16] net: aquantia: implement hwmon api for " Igor Russkikh
@ 2019-04-23 19:17 ` Andrew Lunn
2019-04-24 8:28 ` Igor Russkikh
0 siblings, 1 reply; 24+ messages in thread
From: Andrew Lunn @ 2019-04-23 19:17 UTC (permalink / raw)
To: Igor Russkikh
Cc: David S . Miller, netdev, Nikita Danilov, Dmitry Bogdanov, Yana Esina
> +static u32 aq_hwmon_temp_config[] = {
> + HWMON_T_INPUT | HWMON_T_LABEL,
> + 0,
It would be nice to also have
HWMON_T_MAX | HWMON_T_MIN |
HWMON_T_CRIT | HWMON_T_LCRIT |
which the PHY probably has.
At gives some degree of context. A temperature on its own of say 65C
is hard to interpret. Is it too hot? But if we have a critical of 85C
and a max of 95C we know we are O.K.
Andrew
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 net-next 02/16] net: aquantia: implement hwmon api for chip temperature
2019-04-23 19:17 ` Andrew Lunn
@ 2019-04-24 8:28 ` Igor Russkikh
2019-04-24 12:32 ` Andrew Lunn
0 siblings, 1 reply; 24+ messages in thread
From: Igor Russkikh @ 2019-04-24 8:28 UTC (permalink / raw)
To: Andrew Lunn
Cc: David S . Miller, netdev, Nikita Danilov, Dmitry Bogdanov, Yana Esina
>> +static u32 aq_hwmon_temp_config[] = {
>> + HWMON_T_INPUT | HWMON_T_LABEL,
>> + 0,
>
> It would be nice to also have
>
> HWMON_T_MAX | HWMON_T_MIN |
> HWMON_T_CRIT | HWMON_T_LCRIT |
>
> which the PHY probably has.
>
> At gives some degree of context. A temperature on its own of say 65C
> is hard to interpret. Is it too hot? But if we have a critical of 85C
> and a max of 95C we know we are O.K.
I can give here only suggested constants, since we don't have now any interface
on reading/configuring these.
Do you think that will be ok?
Regards,
Igor
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 net-next 02/16] net: aquantia: implement hwmon api for chip temperature
2019-04-24 8:28 ` Igor Russkikh
@ 2019-04-24 12:32 ` Andrew Lunn
0 siblings, 0 replies; 24+ messages in thread
From: Andrew Lunn @ 2019-04-24 12:32 UTC (permalink / raw)
To: Igor Russkikh
Cc: David S . Miller, netdev, Nikita Danilov, Dmitry Bogdanov, Yana Esina
On Wed, Apr 24, 2019 at 08:28:46AM +0000, Igor Russkikh wrote:
>
> >> +static u32 aq_hwmon_temp_config[] = {
> >> + HWMON_T_INPUT | HWMON_T_LABEL,
> >> + 0,
> >
> > It would be nice to also have
> >
> > HWMON_T_MAX | HWMON_T_MIN |
> > HWMON_T_CRIT | HWMON_T_LCRIT |
> >
> > which the PHY probably has.
> >
> > At gives some degree of context. A temperature on its own of say 65C
> > is hard to interpret. Is it too hot? But if we have a critical of 85C
> > and a max of 95C we know we are O.K.
>
> I can give here only suggested constants, since we don't have now any interface
> on reading/configuring these.
Hi Igor
You mean your firmware is blocking you from accessing these PHY
registers?
> Do you think that will be ok?
I think the HWMON maintainer prefers they come from the hardware. You
are also going to get odd results, when the provisioning data for the
PHY is different to what you hard code in the driver. The PHY shuts
down to protect itself, but your hard coded values indicate everything
should be O.K.
I would suggest you stick with the current patch, until you can add
more features to the firmware to allow access to these registers.
Andrew
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v2 net-next 03/16] net: aquantia: add link interrupt fields
2019-04-23 13:17 [PATCH v2 net-next 00/16] net: atlantic: Aquantia driver updates 2019-04 Igor Russkikh
2019-04-23 13:17 ` [PATCH v2 net-next 01/16] net: aquantia: add infrastructure to readout chip temperature Igor Russkikh
2019-04-23 13:17 ` [PATCH v2 net-next 02/16] net: aquantia: implement hwmon api for " Igor Russkikh
@ 2019-04-23 13:17 ` Igor Russkikh
2019-04-23 13:17 ` [PATCH v2 net-next 04/16] net: aquantia: link interrupt handling function Igor Russkikh
` (12 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Igor Russkikh @ 2019-04-23 13:17 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Nikita Danilov, Dmitry Bogdanov, Igor Russkikh, Nikita Danilov
Declare macroes and nic fields to support link interrupt
handling
Signed-off-by: Nikita Danilov <ndanilov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 2 ++
drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 3 ++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
index 538593261ae3..76d8156779df 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
@@ -88,6 +88,8 @@ struct aq_stats_s {
#define AQ_HW_IRQ_MSI 2U
#define AQ_HW_IRQ_MSIX 3U
+#define AQ_HW_SERVICE_IRQS 1U
+
#define AQ_HW_POWER_STATE_D0 0U
#define AQ_HW_POWER_STATE_D3 3U
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
index b1372430f62f..0409cf5ca3ab 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
@@ -26,7 +26,8 @@ struct aq_nic_cfg_s {
u64 features;
u32 rxds; /* rx ring size, descriptors # */
u32 txds; /* tx ring size, descriptors # */
- u32 vecs; /* vecs==allocated irqs */
+ u32 vecs; /* allocated rx/tx vectors */
+ u32 link_irq_vec;
u32 irq_type;
u32 itr;
u16 rx_itr;
--
2.17.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 net-next 04/16] net: aquantia: link interrupt handling function
2019-04-23 13:17 [PATCH v2 net-next 00/16] net: atlantic: Aquantia driver updates 2019-04 Igor Russkikh
` (2 preceding siblings ...)
2019-04-23 13:17 ` [PATCH v2 net-next 03/16] net: aquantia: add link interrupt fields Igor Russkikh
@ 2019-04-23 13:17 ` Igor Russkikh
2019-04-23 13:17 ` [PATCH v2 net-next 05/16] net: aquantia: create global service workqueue Igor Russkikh
` (11 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Igor Russkikh @ 2019-04-23 13:17 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Nikita Danilov, Dmitry Bogdanov, Igor Russkikh, Nikita Danilov
Define link interrupt handler
Signed-off-by: Nikita Danilov <ndanilov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index 059df86e8e37..4851fc0a3ae5 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -161,6 +161,20 @@ static int aq_nic_update_link_status(struct aq_nic_s *self)
return 0;
}
+static irqreturn_t aq_linkstate_threaded_isr(int irq, void *private)
+{
+ struct aq_nic_s *self = private;
+
+ if (!self)
+ return IRQ_NONE;
+
+ aq_nic_update_link_status(self);
+
+ self->aq_hw_ops->hw_irq_enable(self->aq_hw,
+ BIT(self->aq_nic_cfg.link_irq_vec));
+ return IRQ_HANDLED;
+}
+
static void aq_nic_service_timer_cb(struct timer_list *t)
{
struct aq_nic_s *self = from_timer(self, t, service_timer);
--
2.17.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 net-next 05/16] net: aquantia: create global service workqueue
2019-04-23 13:17 [PATCH v2 net-next 00/16] net: atlantic: Aquantia driver updates 2019-04 Igor Russkikh
` (3 preceding siblings ...)
2019-04-23 13:17 ` [PATCH v2 net-next 04/16] net: aquantia: link interrupt handling function Igor Russkikh
@ 2019-04-23 13:17 ` Igor Russkikh
2019-04-23 13:17 ` [PATCH v2 net-next 06/16] net: aquantia: link status irq handling Igor Russkikh
` (10 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Igor Russkikh @ 2019-04-23 13:17 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Nikita Danilov, Dmitry Bogdanov, Igor Russkikh, Nikita Danilov
From: Nikita Danilov <ndanilov@aquantia.com>
We need this to schedule link interrupt handling and
various service tasks.
Signed-off-by: Nikita Danilov <ndanilov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
.../net/ethernet/aquantia/atlantic/aq_main.c | 41 +++++++++++++++++++
.../net/ethernet/aquantia/atlantic/aq_main.h | 2 +
.../ethernet/aquantia/atlantic/aq_pci_func.c | 11 ++++-
.../ethernet/aquantia/atlantic/aq_pci_func.h | 3 ++
4 files changed, 56 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
index 2a11c1eefd8f..7f45e9908582 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
@@ -23,8 +23,17 @@ MODULE_VERSION(AQ_CFG_DRV_VERSION);
MODULE_AUTHOR(AQ_CFG_DRV_AUTHOR);
MODULE_DESCRIPTION(AQ_CFG_DRV_DESC);
+const char aq_ndev_driver_name[] = AQ_CFG_DRV_NAME;
+
static const struct net_device_ops aq_ndev_ops;
+static struct workqueue_struct *aq_ndev_wq;
+
+void aq_ndev_schedule_work(struct work_struct *work)
+{
+ queue_work(aq_ndev_wq, work);
+}
+
struct net_device *aq_ndev_alloc(void)
{
struct net_device *ndev = NULL;
@@ -209,3 +218,35 @@ static const struct net_device_ops aq_ndev_ops = {
.ndo_vlan_rx_add_vid = aq_ndo_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = aq_ndo_vlan_rx_kill_vid,
};
+
+static int __init aq_ndev_init_module(void)
+{
+ int ret;
+
+ aq_ndev_wq = create_singlethread_workqueue(aq_ndev_driver_name);
+ if (!aq_ndev_wq) {
+ pr_err("Failed to create workqueue\n");
+ return -ENOMEM;
+ }
+
+ ret = aq_pci_func_register_driver();
+ if (ret) {
+ destroy_workqueue(aq_ndev_wq);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void __exit aq_ndev_exit_module(void)
+{
+ aq_pci_func_unregister_driver();
+
+ if (aq_ndev_wq) {
+ destroy_workqueue(aq_ndev_wq);
+ aq_ndev_wq = NULL;
+ }
+}
+
+module_init(aq_ndev_init_module);
+module_exit(aq_ndev_exit_module);
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.h b/drivers/net/ethernet/aquantia/atlantic/aq_main.h
index ce92152eb43e..5448b82fb7ea 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.h
@@ -13,7 +13,9 @@
#define AQ_MAIN_H
#include "aq_common.h"
+#include "aq_nic.h"
+void aq_ndev_schedule_work(struct work_struct *work);
struct net_device *aq_ndev_alloc(void);
#endif /* AQ_MAIN_H */
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
index 556b735e5a32..151efd8f21d8 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
@@ -369,4 +369,13 @@ static struct pci_driver aq_pci_ops = {
.shutdown = aq_pci_shutdown,
};
-module_pci_driver(aq_pci_ops);
+int aq_pci_func_register_driver(void)
+{
+ return pci_register_driver(&aq_pci_ops);
+}
+
+void aq_pci_func_unregister_driver(void)
+{
+ pci_unregister_driver(&aq_pci_ops);
+}
+
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h
index aeee67bf69fa..799c5e0d653b 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h
@@ -29,4 +29,7 @@ int aq_pci_func_alloc_irq(struct aq_nic_s *self, unsigned int i,
void aq_pci_func_free_irqs(struct aq_nic_s *self);
unsigned int aq_pci_func_get_irq_type(struct aq_nic_s *self);
+int aq_pci_func_register_driver(void);
+void aq_pci_func_unregister_driver(void);
+
#endif /* AQ_PCI_FUNC_H */
--
2.17.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 net-next 06/16] net: aquantia: link status irq handling
2019-04-23 13:17 [PATCH v2 net-next 00/16] net: atlantic: Aquantia driver updates 2019-04 Igor Russkikh
` (4 preceding siblings ...)
2019-04-23 13:17 ` [PATCH v2 net-next 05/16] net: aquantia: create global service workqueue Igor Russkikh
@ 2019-04-23 13:17 ` Igor Russkikh
2019-04-23 13:17 ` [PATCH v2 net-next 07/16] net: aquantia: improve ifup link detection Igor Russkikh
` (9 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Igor Russkikh @ 2019-04-23 13:17 UTC (permalink / raw)
To: David S . Miller; +Cc: netdev, Nikita Danilov, Dmitry Bogdanov, Igor Russkikh
Here we define and request an extra interrupt line,
assign it on link isr handler and restructure abit aq_pci code
to better support that.
We also remove logic for using different timer intervals
depending on link state, since thats now useless.
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
.../net/ethernet/aquantia/atlantic/aq_nic.c | 36 ++++++++++++++-----
.../ethernet/aquantia/atlantic/aq_pci_func.c | 24 ++++++++-----
.../ethernet/aquantia/atlantic/aq_pci_func.h | 4 +--
.../aquantia/atlantic/hw_atl/hw_atl_b0.c | 5 +++
4 files changed, 50 insertions(+), 19 deletions(-)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index 4851fc0a3ae5..0251566b66af 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -14,6 +14,7 @@
#include "aq_vec.h"
#include "aq_hw.h"
#include "aq_pci_func.h"
+#include "aq_main.h"
#include <linux/moduleparam.h>
#include <linux/netdevice.h>
@@ -92,7 +93,8 @@ void aq_nic_cfg_start(struct aq_nic_s *self)
/*rss rings */
cfg->vecs = min(cfg->aq_hw_caps->vecs, AQ_CFG_VECS_DEF);
cfg->vecs = min(cfg->vecs, num_online_cpus());
- cfg->vecs = min(cfg->vecs, self->irqvecs);
+ if (self->irqvecs > AQ_HW_SERVICE_IRQS)
+ cfg->vecs = min(cfg->vecs, self->irqvecs - AQ_HW_SERVICE_IRQS);
/* cfg->vecs should be power of 2 for RSS */
if (cfg->vecs >= 8U)
cfg->vecs = 8U;
@@ -116,6 +118,15 @@ void aq_nic_cfg_start(struct aq_nic_s *self)
cfg->vecs = 1U;
}
+ /* Check if we have enough vectors allocated for
+ * 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)
+ cfg->link_irq_vec = cfg->vecs;
+ else
+ cfg->link_irq_vec = 0;
+
cfg->link_speed_msk &= cfg->aq_hw_caps->link_speed_msk;
cfg->features = cfg->aq_hw_caps->hw_features;
}
@@ -178,7 +189,6 @@ static irqreturn_t aq_linkstate_threaded_isr(int irq, void *private)
static void aq_nic_service_timer_cb(struct timer_list *t)
{
struct aq_nic_s *self = from_timer(self, t, service_timer);
- int ctimer = AQ_CFG_SERVICE_TIMER_INTERVAL;
int err = 0;
if (aq_utils_obj_test(&self->flags, AQ_NIC_FLAGS_IS_NOT_READY))
@@ -193,12 +203,8 @@ static void aq_nic_service_timer_cb(struct timer_list *t)
aq_nic_update_ndev_stats(self);
- /* If no link - use faster timer rate to detect link up asap */
- if (!netif_carrier_ok(self->ndev))
- ctimer = max(ctimer / 2, 1);
-
err_exit:
- mod_timer(&self->service_timer, jiffies + ctimer);
+ mod_timer(&self->service_timer, jiffies + AQ_CFG_SERVICE_TIMER_INTERVAL);
}
static void aq_nic_polling_timer_cb(struct timer_list *t)
@@ -359,13 +365,25 @@ int aq_nic_start(struct aq_nic_s *self)
} else {
for (i = 0U, aq_vec = self->aq_vec[0];
self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) {
- err = aq_pci_func_alloc_irq(self, i,
- self->ndev->name, aq_vec,
+ err = aq_pci_func_alloc_irq(self, i, self->ndev->name,
+ aq_vec_isr, aq_vec,
aq_vec_get_affinity_mask(aq_vec));
if (err < 0)
goto err_exit;
}
+ if (self->aq_nic_cfg.link_irq_vec) {
+ int irqvec = pci_irq_vector(self->pdev,
+ self->aq_nic_cfg.link_irq_vec);
+ err = request_threaded_irq(irqvec, NULL,
+ aq_linkstate_threaded_isr,
+ IRQF_SHARED,
+ self->ndev->name, self);
+ if (err < 0)
+ goto err_exit;
+ self->msix_entry_mask |= (1 << self->aq_nic_cfg.link_irq_vec);
+ }
+
err = self->aq_hw_ops->hw_irq_enable(self->aq_hw,
AQ_CFG_IRQ_MASK);
if (err < 0)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
index 151efd8f21d8..9cb8dc7656aa 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
@@ -140,26 +140,27 @@ int aq_pci_func_init(struct pci_dev *pdev)
}
int aq_pci_func_alloc_irq(struct aq_nic_s *self, unsigned int i,
- char *name, void *aq_vec, cpumask_t *affinity_mask)
+ char *name, irq_handler_t irq_handler,
+ void *irq_arg, cpumask_t *affinity_mask)
{
struct pci_dev *pdev = self->pdev;
int err;
if (pdev->msix_enabled || pdev->msi_enabled)
- err = request_irq(pci_irq_vector(pdev, i), aq_vec_isr, 0,
- name, aq_vec);
+ err = request_irq(pci_irq_vector(pdev, i), irq_handler, 0,
+ name, irq_arg);
else
err = request_irq(pci_irq_vector(pdev, i), aq_vec_isr_legacy,
- IRQF_SHARED, name, aq_vec);
+ IRQF_SHARED, name, irq_arg);
if (err >= 0) {
self->msix_entry_mask |= (1 << i);
- self->aq_vec[i] = aq_vec;
- if (pdev->msix_enabled)
+ if (pdev->msix_enabled && affinity_mask)
irq_set_affinity_hint(pci_irq_vector(pdev, i),
affinity_mask);
}
+
return err;
}
@@ -167,16 +168,22 @@ void aq_pci_func_free_irqs(struct aq_nic_s *self)
{
struct pci_dev *pdev = self->pdev;
unsigned int i;
+ void *irq_data;
for (i = 32U; i--;) {
if (!((1U << i) & self->msix_entry_mask))
continue;
- if (i >= AQ_CFG_VECS_MAX)
+ if (self->aq_nic_cfg.link_irq_vec &&
+ i == self->aq_nic_cfg.link_irq_vec)
+ irq_data = self;
+ else if (i < AQ_CFG_VECS_MAX)
+ irq_data = self->aq_vec[i];
+ else
continue;
if (pdev->msix_enabled)
irq_set_affinity_hint(pci_irq_vector(pdev, i), NULL);
- free_irq(pci_irq_vector(pdev, i), self->aq_vec[i]);
+ free_irq(pci_irq_vector(pdev, i), irq_data);
self->msix_entry_mask &= ~(1U << i);
}
}
@@ -269,6 +276,7 @@ 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());
+ numvecs += AQ_HW_SERVICE_IRQS;
/*enable interrupts */
#if !AQ_CFG_FORCE_LEGACY_INT
err = pci_alloc_irq_vectors(self->pdev, 1, numvecs,
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h
index 799c5e0d653b..670f9a940d65 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h
@@ -24,8 +24,8 @@ struct aq_board_revision_s {
int aq_pci_func_init(struct pci_dev *pdev);
int aq_pci_func_alloc_irq(struct aq_nic_s *self, unsigned int i,
- char *name, void *aq_vec,
- cpumask_t *affinity_mask);
+ char *name, irq_handler_t irq_handler,
+ void *irq_arg, cpumask_t *affinity_mask);
void aq_pci_func_free_irqs(struct aq_nic_s *self);
unsigned int aq_pci_func_get_irq_type(struct aq_nic_s *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 7e95804e2180..d54566bab0e9 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
@@ -443,6 +443,11 @@ static int hw_atl_b0_hw_init(struct aq_hw_s *self, u8 *mac_addr)
((HW_ATL_B0_ERR_INT << 0x18) | (1U << 0x1F)) |
((HW_ATL_B0_ERR_INT << 0x10) | (1U << 0x17)), 0U);
+ /* Enable link interrupt */
+ if (aq_nic_cfg->link_irq_vec)
+ hw_atl_reg_gen_irq_map_set(self, BIT(7) |
+ aq_nic_cfg->link_irq_vec, 3U);
+
hw_atl_b0_hw_offload_set(self, aq_nic_cfg);
err_exit:
--
2.17.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 net-next 07/16] net: aquantia: improve ifup link detection
2019-04-23 13:17 [PATCH v2 net-next 00/16] net: atlantic: Aquantia driver updates 2019-04 Igor Russkikh
` (5 preceding siblings ...)
2019-04-23 13:17 ` [PATCH v2 net-next 06/16] net: aquantia: link status irq handling Igor Russkikh
@ 2019-04-23 13:17 ` Igor Russkikh
2019-04-23 13:17 ` [PATCH v2 net-next 08/16] net: aquantia: use macros for better visibility Igor Russkikh
` (8 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Igor Russkikh @ 2019-04-23 13:17 UTC (permalink / raw)
To: David S . Miller; +Cc: netdev, Nikita Danilov, Dmitry Bogdanov, Igor Russkikh
Original code detected link only after 1 sec is passed after up.
Here we replace this with direct service callback which updates
link status immediately
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index 0251566b66af..6de0d1c0ed79 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -355,8 +355,7 @@ int aq_nic_start(struct aq_nic_s *self)
if (err)
goto err_exit;
timer_setup(&self->service_timer, aq_nic_service_timer_cb, 0);
- mod_timer(&self->service_timer, jiffies +
- AQ_CFG_SERVICE_TIMER_INTERVAL);
+ aq_nic_service_timer_cb(&self->service_timer);
if (self->aq_nic_cfg.is_polling) {
timer_setup(&self->polling_timer, aq_nic_polling_timer_cb, 0);
--
2.17.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 net-next 08/16] net: aquantia: use macros for better visibility
2019-04-23 13:17 [PATCH v2 net-next 00/16] net: atlantic: Aquantia driver updates 2019-04 Igor Russkikh
` (6 preceding siblings ...)
2019-04-23 13:17 ` [PATCH v2 net-next 07/16] net: aquantia: improve ifup link detection Igor Russkikh
@ 2019-04-23 13:17 ` Igor Russkikh
2019-04-23 13:17 ` [PATCH v2 net-next 09/16] net: aquantia: user correct MSI irq type Igor Russkikh
` (7 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Igor Russkikh @ 2019-04-23 13:17 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Nikita Danilov, Dmitry Bogdanov, Igor Russkikh, Nikita Danilov
Improve for better readability
Signed-off-by: Nikita Danilov <ndanilov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 8 ++++----
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 8 ++++----
2 files changed, 8 insertions(+), 8 deletions(-)
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 65ffaa7ad69e..9fe507fe2d7f 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
@@ -350,10 +350,10 @@ static int hw_atl_a0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr)
static int hw_atl_a0_hw_init(struct aq_hw_s *self, u8 *mac_addr)
{
static u32 aq_hw_atl_igcr_table_[4][2] = {
- { 0x20000000U, 0x20000000U }, /* AQ_IRQ_INVALID */
- { 0x20000080U, 0x20000080U }, /* AQ_IRQ_LEGACY */
- { 0x20000021U, 0x20000025U }, /* AQ_IRQ_MSI */
- { 0x20000022U, 0x20000026U } /* AQ_IRQ_MSIX */
+ [AQ_HW_IRQ_INVALID] = { 0x20000000U, 0x20000000U },
+ [AQ_HW_IRQ_LEGACY] = { 0x20000080U, 0x20000080U },
+ [AQ_HW_IRQ_MSI] = { 0x20000021U, 0x20000025U },
+ [AQ_HW_IRQ_MSIX] = { 0x20000022U, 0x20000026U },
};
int err = 0;
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 d54566bab0e9..bfcda12d73de 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
@@ -388,10 +388,10 @@ static int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr)
static int hw_atl_b0_hw_init(struct aq_hw_s *self, u8 *mac_addr)
{
static u32 aq_hw_atl_igcr_table_[4][2] = {
- { 0x20000000U, 0x20000000U }, /* AQ_IRQ_INVALID */
- { 0x20000080U, 0x20000080U }, /* AQ_IRQ_LEGACY */
- { 0x20000021U, 0x20000025U }, /* AQ_IRQ_MSI */
- { 0x20000022U, 0x20000026U } /* AQ_IRQ_MSIX */
+ [AQ_HW_IRQ_INVALID] = { 0x20000000U, 0x20000000U },
+ [AQ_HW_IRQ_LEGACY] = { 0x20000080U, 0x20000080U },
+ [AQ_HW_IRQ_MSI] = { 0x20000021U, 0x20000025U },
+ [AQ_HW_IRQ_MSIX] = { 0x20000022U, 0x20000026U },
};
int err = 0;
--
2.17.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 net-next 09/16] net: aquantia: user correct MSI irq type
2019-04-23 13:17 [PATCH v2 net-next 00/16] net: atlantic: Aquantia driver updates 2019-04 Igor Russkikh
` (7 preceding siblings ...)
2019-04-23 13:17 ` [PATCH v2 net-next 08/16] net: aquantia: use macros for better visibility Igor Russkikh
@ 2019-04-23 13:17 ` Igor Russkikh
2019-04-23 13:17 ` [PATCH v2 net-next 10/16] net: aquantia: introduce fwreq mutex Igor Russkikh
` (6 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Igor Russkikh @ 2019-04-23 13:17 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Nikita Danilov, Dmitry Bogdanov, Igor Russkikh, Nikita Danilov
Typo in msi code. No much impact though.
Signed-off-by: Nikita Danilov <ndanilov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
index 9cb8dc7656aa..961e9777e66b 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
@@ -193,7 +193,7 @@ unsigned int aq_pci_func_get_irq_type(struct aq_nic_s *self)
if (self->pdev->msix_enabled)
return AQ_HW_IRQ_MSIX;
if (self->pdev->msi_enabled)
- return AQ_HW_IRQ_MSIX;
+ return AQ_HW_IRQ_MSI;
return AQ_HW_IRQ_LEGACY;
}
--
2.17.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 net-next 10/16] net: aquantia: introduce fwreq mutex
2019-04-23 13:17 [PATCH v2 net-next 00/16] net: atlantic: Aquantia driver updates 2019-04 Igor Russkikh
` (8 preceding siblings ...)
2019-04-23 13:17 ` [PATCH v2 net-next 09/16] net: aquantia: user correct MSI irq type Igor Russkikh
@ 2019-04-23 13:17 ` Igor Russkikh
2019-04-23 13:17 ` [PATCH v2 net-next 11/16] net: aquantia: extract timer cb into work job Igor Russkikh
` (5 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Igor Russkikh @ 2019-04-23 13:17 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Nikita Danilov, Dmitry Bogdanov, Igor Russkikh, Nikita Danilov
From: Nikita Danilov <ndanilov@aquantia.com>
Some of FW operations could be invoked simultaneously,
from f.e. ethtool context and from service service activity work.
Here we introduce a fw mutex to secure and serialize access
to FW logic.
Signed-off-by: Nikita Danilov <ndanilov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 2 ++
drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c | 2 ++
2 files changed, 4 insertions(+)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
index 0409cf5ca3ab..be56ace6274b 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
@@ -105,6 +105,8 @@ struct aq_nic_s {
struct pci_dev *pdev;
unsigned int msix_entry_mask;
u32 irqvecs;
+ /* mutex to serialize FW interface access operations */
+ struct mutex fwreq_mutex;
struct aq_hw_rx_fltrs_s aq_hw_rx_fltrs;
};
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
index 961e9777e66b..a607e25dfbff 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
@@ -231,6 +231,8 @@ static int aq_pci_probe(struct pci_dev *pdev,
SET_NETDEV_DEV(ndev, &pdev->dev);
pci_set_drvdata(pdev, self);
+ mutex_init(&self->fwreq_mutex);
+
err = aq_pci_probe_get_hw_by_id(pdev, &self->aq_hw_ops,
&aq_nic_get_cfg(self)->aq_hw_caps);
if (err)
--
2.17.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 net-next 11/16] net: aquantia: extract timer cb into work job
2019-04-23 13:17 [PATCH v2 net-next 00/16] net: atlantic: Aquantia driver updates 2019-04 Igor Russkikh
` (9 preceding siblings ...)
2019-04-23 13:17 ` [PATCH v2 net-next 10/16] net: aquantia: introduce fwreq mutex Igor Russkikh
@ 2019-04-23 13:17 ` Igor Russkikh
2019-04-24 0:37 ` Jakub Kicinski
2019-04-23 13:17 ` [PATCH v2 net-next 12/16] net: aquantia: wrap fw ops by mutex Igor Russkikh
` (4 subsequent siblings)
15 siblings, 1 reply; 24+ messages in thread
From: Igor Russkikh @ 2019-04-23 13:17 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Nikita Danilov, Dmitry Bogdanov, Igor Russkikh, Nikita Danilov
Service timer callback fetches statistics from FW and that may cause
a long delay in error cases. We also now need to use fw mutex
to prevent concurrent access to FW, thus - extract that logic
from timer callback into the job in the separate work queue.
Signed-off-by: Nikita Danilov <ndanilov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
.../net/ethernet/aquantia/atlantic/aq_nic.c | 25 ++++++++++++++-----
.../net/ethernet/aquantia/atlantic/aq_nic.h | 1 +
2 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index 6de0d1c0ed79..b8f6f4129f44 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -186,25 +186,34 @@ static irqreturn_t aq_linkstate_threaded_isr(int irq, void *private)
return IRQ_HANDLED;
}
-static void aq_nic_service_timer_cb(struct timer_list *t)
+static void aq_nic_service_task(struct work_struct *work)
{
- struct aq_nic_s *self = from_timer(self, t, service_timer);
- int err = 0;
+ struct aq_nic_s *self = container_of(work, struct aq_nic_s,
+ service_task);
+ int err;
if (aq_utils_obj_test(&self->flags, AQ_NIC_FLAGS_IS_NOT_READY))
- goto err_exit;
+ return;
err = aq_nic_update_link_status(self);
if (err)
- goto err_exit;
+ return;
+ mutex_lock(&self->fwreq_mutex);
if (self->aq_fw_ops->update_stats)
self->aq_fw_ops->update_stats(self->aq_hw);
+ mutex_unlock(&self->fwreq_mutex);
aq_nic_update_ndev_stats(self);
+}
+
+static void aq_nic_service_timer_cb(struct timer_list *t)
+{
+ struct aq_nic_s *self = from_timer(self, t, service_timer);
-err_exit:
mod_timer(&self->service_timer, jiffies + AQ_CFG_SERVICE_TIMER_INTERVAL);
+
+ aq_ndev_schedule_work(&self->service_task);
}
static void aq_nic_polling_timer_cb(struct timer_list *t)
@@ -354,6 +363,9 @@ int aq_nic_start(struct aq_nic_s *self)
err = aq_nic_update_interrupt_moderation_settings(self);
if (err)
goto err_exit;
+
+ INIT_WORK(&self->service_task, aq_nic_service_task);
+
timer_setup(&self->service_timer, aq_nic_service_timer_cb, 0);
aq_nic_service_timer_cb(&self->service_timer);
@@ -904,6 +916,7 @@ int aq_nic_stop(struct aq_nic_s *self)
netif_carrier_off(self->ndev);
del_timer_sync(&self->service_timer);
+ cancel_work_sync(&self->service_task);
self->aq_hw_ops->hw_irq_disable(self->aq_hw, AQ_CFG_IRQ_MASK);
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
index be56ace6274b..c03d38ed105d 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
@@ -93,6 +93,7 @@ struct aq_nic_s {
const struct aq_fw_ops *aq_fw_ops;
struct aq_nic_cfg_s aq_nic_cfg;
struct timer_list service_timer;
+ struct work_struct service_task;
struct timer_list polling_timer;
struct aq_hw_link_status_s link_status;
struct {
--
2.17.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH v2 net-next 11/16] net: aquantia: extract timer cb into work job
2019-04-23 13:17 ` [PATCH v2 net-next 11/16] net: aquantia: extract timer cb into work job Igor Russkikh
@ 2019-04-24 0:37 ` Jakub Kicinski
2019-04-24 8:31 ` Igor Russkikh
0 siblings, 1 reply; 24+ messages in thread
From: Jakub Kicinski @ 2019-04-24 0:37 UTC (permalink / raw)
To: Igor Russkikh; +Cc: David S . Miller, netdev, Nikita Danilov, Dmitry Bogdanov
On Tue, 23 Apr 2019 13:17:55 +0000, Igor Russkikh wrote:
> Service timer callback fetches statistics from FW and that may cause
> a long delay in error cases. We also now need to use fw mutex
> to prevent concurrent access to FW, thus - extract that logic
> from timer callback into the job in the separate work queue.
>
> Signed-off-by: Nikita Danilov <ndanilov@aquantia.com>
> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
The split into patches is slightly imperfect here.
Patch 10 "introduces" a mutex, which nothing is using, yet.
Patch 11 starts some async work, which the mutex is needed for.
Patches 12 and 13 wrap other FW call sites...
Isn't it better to squash 12 and 13 into 10, this way 11 is safe
to access FW from the work queue?
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 net-next 11/16] net: aquantia: extract timer cb into work job
2019-04-24 0:37 ` Jakub Kicinski
@ 2019-04-24 8:31 ` Igor Russkikh
0 siblings, 0 replies; 24+ messages in thread
From: Igor Russkikh @ 2019-04-24 8:31 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: David S . Miller, netdev, Nikita Danilov, Dmitry Bogdanov
Hello Jakub,
> The split into patches is slightly imperfect here.
>
> Patch 10 "introduces" a mutex, which nothing is using, yet.
>
> Patch 11 starts some async work, which the mutex is needed for.
>
> Patches 12 and 13 wrap other FW call sites...
>
> Isn't it better to squash 12 and 13 into 10, this way 11 is safe
> to access FW from the work queue?
>
Thanks, you are right, will do.
Regards,
Igor
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v2 net-next 12/16] net: aquantia: wrap fw ops by mutex
2019-04-23 13:17 [PATCH v2 net-next 00/16] net: atlantic: Aquantia driver updates 2019-04 Igor Russkikh
` (10 preceding siblings ...)
2019-04-23 13:17 ` [PATCH v2 net-next 11/16] net: aquantia: extract timer cb into work job Igor Russkikh
@ 2019-04-23 13:17 ` Igor Russkikh
2019-04-23 13:17 ` [PATCH v2 net-next 13/16] net: aquantia: fetch up to date statistics on ethtool request Igor Russkikh
` (3 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Igor Russkikh @ 2019-04-23 13:17 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Nikita Danilov, Dmitry Bogdanov, Igor Russkikh, Nikita Danilov
From: Nikita Danilov <ndanilov@aquantia.com>
Since fw ops may be invoked from different threads all its invocation
must be wrapped by mutex.
Signed-off-by: Nikita Danilov <ndanilov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
.../ethernet/aquantia/atlantic/aq_ethtool.c | 22 +++++++++++++---
.../net/ethernet/aquantia/atlantic/aq_nic.c | 26 ++++++++++++++-----
2 files changed, 38 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
index a718d7a1f76c..79da48094770 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
@@ -405,8 +405,10 @@ static int aq_ethtool_get_eee(struct net_device *ndev, struct ethtool_eee *eee)
if (!aq_nic->aq_fw_ops->get_eee_rate)
return -EOPNOTSUPP;
+ mutex_lock(&aq_nic->fwreq_mutex);
err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
&supported_rates);
+ mutex_unlock(&aq_nic->fwreq_mutex);
if (err < 0)
return err;
@@ -439,8 +441,10 @@ static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_eee *eee)
!aq_nic->aq_fw_ops->set_eee_rate))
return -EOPNOTSUPP;
+ mutex_lock(&aq_nic->fwreq_mutex);
err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
&supported_rates);
+ mutex_unlock(&aq_nic->fwreq_mutex);
if (err < 0)
return err;
@@ -452,20 +456,28 @@ static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_eee *eee)
cfg->eee_speeds = 0;
}
- return aq_nic->aq_fw_ops->set_eee_rate(aq_nic->aq_hw, rate);
+ mutex_lock(&aq_nic->fwreq_mutex);
+ err = aq_nic->aq_fw_ops->set_eee_rate(aq_nic->aq_hw, rate);
+ mutex_unlock(&aq_nic->fwreq_mutex);
+
+ return err;
}
static int aq_ethtool_nway_reset(struct net_device *ndev)
{
struct aq_nic_s *aq_nic = netdev_priv(ndev);
+ int err = 0;
if (unlikely(!aq_nic->aq_fw_ops->renegotiate))
return -EOPNOTSUPP;
- if (netif_running(ndev))
- return aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw);
+ if (netif_running(ndev)) {
+ mutex_lock(&aq_nic->fwreq_mutex);
+ err = aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw);
+ mutex_unlock(&aq_nic->fwreq_mutex);
+ }
- return 0;
+ return err;
}
static void aq_ethtool_get_pauseparam(struct net_device *ndev,
@@ -503,7 +515,9 @@ static int aq_ethtool_set_pauseparam(struct net_device *ndev,
else
aq_nic->aq_hw->aq_nic_cfg->flow_control &= ~AQ_NIC_FC_TX;
+ mutex_lock(&aq_nic->fwreq_mutex);
err = aq_nic->aq_fw_ops->set_flow_control(aq_nic->aq_hw);
+ mutex_unlock(&aq_nic->fwreq_mutex);
return err;
}
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index b8f6f4129f44..454a44bb148e 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -243,8 +243,10 @@ int aq_nic_ndev_register(struct aq_nic_s *self)
if (err)
goto err_exit;
+ mutex_lock(&self->fwreq_mutex);
err = self->aq_fw_ops->get_mac_permanent(self->aq_hw,
self->ndev->dev_addr);
+ mutex_unlock(&self->fwreq_mutex);
if (err)
goto err_exit;
@@ -313,7 +315,9 @@ int aq_nic_init(struct aq_nic_s *self)
unsigned int i = 0U;
self->power_state = AQ_HW_POWER_STATE_D0;
+ mutex_lock(&self->fwreq_mutex);
err = self->aq_hw_ops->hw_reset(self->aq_hw);
+ mutex_unlock(&self->fwreq_mutex);
if (err < 0)
goto err_exit;
@@ -883,7 +887,9 @@ int aq_nic_set_link_ksettings(struct aq_nic_s *self,
self->aq_nic_cfg.is_autoneg = false;
}
+ mutex_lock(&self->fwreq_mutex);
err = self->aq_fw_ops->set_link_speed(self->aq_hw, rate);
+ mutex_unlock(&self->fwreq_mutex);
if (err < 0)
goto err_exit;
@@ -944,14 +950,22 @@ void aq_nic_deinit(struct aq_nic_s *self)
self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i])
aq_vec_deinit(aq_vec);
- self->aq_fw_ops->deinit(self->aq_hw);
+ if (likely(self->aq_fw_ops->deinit)) {
+ mutex_lock(&self->fwreq_mutex);
+ self->aq_fw_ops->deinit(self->aq_hw);
+ mutex_unlock(&self->fwreq_mutex);
+ }
if (self->power_state != AQ_HW_POWER_STATE_D0 ||
- self->aq_hw->aq_nic_cfg->wol) {
- self->aq_fw_ops->set_power(self->aq_hw,
- self->power_state,
- self->ndev->dev_addr);
- }
+ self->aq_hw->aq_nic_cfg->wol)
+ if (likely(self->aq_fw_ops->set_power)) {
+ mutex_lock(&self->fwreq_mutex);
+ self->aq_fw_ops->set_power(self->aq_hw,
+ self->power_state,
+ self->ndev->dev_addr);
+ mutex_unlock(&self->fwreq_mutex);
+ }
+
err_exit:;
}
--
2.17.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 net-next 13/16] net: aquantia: fetch up to date statistics on ethtool request
2019-04-23 13:17 [PATCH v2 net-next 00/16] net: atlantic: Aquantia driver updates 2019-04 Igor Russkikh
` (11 preceding siblings ...)
2019-04-23 13:17 ` [PATCH v2 net-next 12/16] net: aquantia: wrap fw ops by mutex Igor Russkikh
@ 2019-04-23 13:17 ` Igor Russkikh
2019-04-23 13:18 ` [PATCH v2 net-next 14/16] net: aquantia: get total counters from DMA block Igor Russkikh
` (2 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Igor Russkikh @ 2019-04-23 13:17 UTC (permalink / raw)
To: David S . Miller; +Cc: netdev, Nikita Danilov, Dmitry Bogdanov, Igor Russkikh
From: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
This improves ethtool -S usage, where stats are now actual
on each request. Before that stats only were updated at service
timer period.
Tested-by: Nikita Danilov <ndanilov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
Signed-off-by: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
---
drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index 454a44bb148e..1893ba7fcd2b 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -700,7 +700,15 @@ void aq_nic_get_stats(struct aq_nic_s *self, u64 *data)
unsigned int i = 0U;
unsigned int count = 0U;
struct aq_vec_s *aq_vec = NULL;
- struct aq_stats_s *stats = self->aq_hw_ops->hw_get_hw_stats(self->aq_hw);
+ struct aq_stats_s *stats;
+
+ if (self->aq_fw_ops->update_stats) {
+ mutex_lock(&self->fwreq_mutex);
+ self->aq_fw_ops->update_stats(self->aq_hw);
+ mutex_unlock(&self->fwreq_mutex);
+ }
+ stats = self->aq_hw_ops->hw_get_hw_stats(self->aq_hw);
+
if (!stats)
goto err_exit;
--
2.17.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 net-next 14/16] net: aquantia: get total counters from DMA block
2019-04-23 13:17 [PATCH v2 net-next 00/16] net: atlantic: Aquantia driver updates 2019-04 Igor Russkikh
` (12 preceding siblings ...)
2019-04-23 13:17 ` [PATCH v2 net-next 13/16] net: aquantia: fetch up to date statistics on ethtool request Igor Russkikh
@ 2019-04-23 13:18 ` Igor Russkikh
2019-04-23 13:18 ` [PATCH v2 net-next 15/16] net: aquantia: fixups on 64bit dma counters Igor Russkikh
2019-04-23 13:18 ` [PATCH v2 net-next 16/16] net: aquantia: remove outdated device ids Igor Russkikh
15 siblings, 0 replies; 24+ messages in thread
From: Igor Russkikh @ 2019-04-23 13:18 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Nikita Danilov, Dmitry Bogdanov, Igor Russkikh, Nikita Danilov
From: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
aq_nic_update_ndev_stats pushes statistics to ndev->stats from
system interface. This is not always good because it counts packets/bytes
before any of rx filters (including mac filter).
Its better to report the packet/bytes statistics from DMA
counters which gives actual values of data transferred over pci.
System level stats is still available via ethtool.
Signed-off-by: Nikita Danilov <ndanilov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
Signed-off-by: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
---
drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index 1893ba7fcd2b..b94c58bf1d2f 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -754,11 +754,12 @@ static void aq_nic_update_ndev_stats(struct aq_nic_s *self)
struct net_device *ndev = self->ndev;
struct aq_stats_s *stats = self->aq_hw_ops->hw_get_hw_stats(self->aq_hw);
- ndev->stats.rx_packets = stats->uprc + stats->mprc + stats->bprc;
- ndev->stats.rx_bytes = stats->ubrc + stats->mbrc + stats->bbrc;
+ ndev->stats.rx_packets = stats->dma_pkt_rc;
+ ndev->stats.rx_bytes = stats->dma_oct_rc;
ndev->stats.rx_errors = stats->erpr;
- ndev->stats.tx_packets = stats->uptc + stats->mptc + stats->bptc;
- ndev->stats.tx_bytes = stats->ubtc + stats->mbtc + stats->bbtc;
+ ndev->stats.rx_dropped = stats->dpc;
+ ndev->stats.tx_packets = stats->dma_pkt_tc;
+ ndev->stats.tx_bytes = stats->dma_oct_tc;
ndev->stats.tx_errors = stats->erpt;
ndev->stats.multicast = stats->mprc;
}
--
2.17.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 net-next 15/16] net: aquantia: fixups on 64bit dma counters
2019-04-23 13:17 [PATCH v2 net-next 00/16] net: atlantic: Aquantia driver updates 2019-04 Igor Russkikh
` (13 preceding siblings ...)
2019-04-23 13:18 ` [PATCH v2 net-next 14/16] net: aquantia: get total counters from DMA block Igor Russkikh
@ 2019-04-23 13:18 ` Igor Russkikh
2019-04-23 13:18 ` [PATCH v2 net-next 16/16] net: aquantia: remove outdated device ids Igor Russkikh
15 siblings, 0 replies; 24+ messages in thread
From: Igor Russkikh @ 2019-04-23 13:18 UTC (permalink / raw)
To: David S . Miller; +Cc: netdev, Nikita Danilov, Dmitry Bogdanov, Igor Russkikh
From: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
DMA counters are 64 bit and we can fetch that to reduce
counter overflow, espesially on byte counters.
Tested-by: Nikita Danilov <ndanilov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
Signed-off-by: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
---
.../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c | 5 -----
.../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h | 3 ---
.../aquantia/atlantic/hw_atl/hw_atl_llh_internal.h | 3 ---
.../aquantia/atlantic/hw_atl/hw_atl_utils.c | 14 +++++++++-----
4 files changed, 9 insertions(+), 16 deletions(-)
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c
index 9442deff98a8..9876122991a7 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c
@@ -49,11 +49,6 @@ u32 hw_atl_glb_soft_res_get(struct aq_hw_s *aq_hw)
HW_ATL_GLB_SOFT_RES_SHIFT);
}
-u32 hw_atl_reg_rx_dma_stat_counter7get(struct aq_hw_s *aq_hw)
-{
- return aq_hw_read_reg(aq_hw, HW_ATL_RX_DMA_STAT_COUNTER7_ADR);
-}
-
u32 hw_atl_reg_glb_mif_id_get(struct aq_hw_s *aq_hw)
{
return aq_hw_read_reg(aq_hw, HW_ATL_GLB_MIF_ID_ADR);
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h
index 4cfa4bd80ad3..3cef151633d4 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h
@@ -82,9 +82,6 @@ u32 hw_atl_reg_mac_msm_rx_bcst_octets_counter1get(struct aq_hw_s *aq_hw);
/* get msm rx unicast octets counter register 0 */
u32 hw_atl_reg_mac_msm_rx_ucst_octets_counter0get(struct aq_hw_s *aq_hw);
-/* get rx dma statistics counter 7 */
-u32 hw_atl_reg_rx_dma_stat_counter7get(struct aq_hw_s *aq_hw);
-
/* get msm tx errors counter register */
u32 hw_atl_reg_mac_msm_tx_errs_cnt_get(struct aq_hw_s *aq_hw);
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h
index 430bbd45b2f0..b64140924a02 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h
@@ -58,9 +58,6 @@
/* preprocessor definitions for msm rx unicast octets counter register 0 */
#define HW_ATL_MAC_MSM_RX_UCST_OCTETS_COUNTER0_ADR 0x000001b8u
-/* preprocessor definitions for rx dma statistics counter 7 */
-#define HW_ATL_RX_DMA_STAT_COUNTER7_ADR 0x00006818u
-
/* preprocessor definitions for msm tx unicast frames counter register */
#define HW_ATL_MAC_MSM_TX_UCST_FRM_CNT_ADR 0x00000108u
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 35df424e3af3..4063746a8859 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
@@ -545,7 +545,7 @@ void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
pmbox->stats.ubtc = pmbox->stats.uptc * mtu;
pmbox->stats.dpc = atomic_read(&self->dpc);
} else {
- pmbox->stats.dpc = hw_atl_reg_rx_dma_stat_counter7get(self);
+ pmbox->stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self);
}
err_exit:;
@@ -789,10 +789,14 @@ int hw_atl_utils_update_stats(struct aq_hw_s *self)
AQ_SDELTA(dpc);
}
#undef AQ_SDELTA
- self->curr_stats.dma_pkt_rc = hw_atl_stats_rx_dma_good_pkt_counterlsw_get(self);
- self->curr_stats.dma_pkt_tc = hw_atl_stats_tx_dma_good_pkt_counterlsw_get(self);
- self->curr_stats.dma_oct_rc = hw_atl_stats_rx_dma_good_octet_counterlsw_get(self);
- self->curr_stats.dma_oct_tc = hw_atl_stats_tx_dma_good_octet_counterlsw_get(self);
+ self->curr_stats.dma_pkt_rc = hw_atl_stats_rx_dma_good_pkt_counterlsw_get(self) +
+ ((u64)hw_atl_stats_rx_dma_good_pkt_countermsw_get(self) << 32);
+ self->curr_stats.dma_pkt_tc = hw_atl_stats_tx_dma_good_pkt_counterlsw_get(self) +
+ ((u64)hw_atl_stats_tx_dma_good_pkt_countermsw_get(self) << 32);
+ self->curr_stats.dma_oct_rc = hw_atl_stats_rx_dma_good_octet_counterlsw_get(self) +
+ ((u64)hw_atl_stats_rx_dma_good_octet_countermsw_get(self) << 32);
+ self->curr_stats.dma_oct_tc = hw_atl_stats_tx_dma_good_octet_counterlsw_get(self) +
+ ((u64)hw_atl_stats_tx_dma_good_octet_countermsw_get(self) << 32);
memcpy(&self->last_stats, &mbox.stats, sizeof(mbox.stats));
--
2.17.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 net-next 16/16] net: aquantia: remove outdated device ids
2019-04-23 13:17 [PATCH v2 net-next 00/16] net: atlantic: Aquantia driver updates 2019-04 Igor Russkikh
` (14 preceding siblings ...)
2019-04-23 13:18 ` [PATCH v2 net-next 15/16] net: aquantia: fixups on 64bit dma counters Igor Russkikh
@ 2019-04-23 13:18 ` Igor Russkikh
15 siblings, 0 replies; 24+ messages in thread
From: Igor Russkikh @ 2019-04-23 13:18 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Nikita Danilov, Dmitry Bogdanov, Igor Russkikh, Nikita Danilov
From: Nikita Danilov <ndanilov@aquantia.com>
Some device ids were never released and does not exist.
Cleanup these.
Signed-off-by: Nikita Danilov <ndanilov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
drivers/net/ethernet/aquantia/atlantic/aq_common.h | 3 ---
drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c | 6 ------
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h | 3 ---
3 files changed, 12 deletions(-)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_common.h b/drivers/net/ethernet/aquantia/atlantic/aq_common.h
index 6b6d1724676e..235bb3a72d66 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_common.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_common.h
@@ -41,9 +41,6 @@
#define AQ_DEVICE_ID_AQC111S 0x91B1
#define AQ_DEVICE_ID_AQC112S 0x92B1
-#define AQ_DEVICE_ID_AQC111E 0x51B1
-#define AQ_DEVICE_ID_AQC112E 0x52B1
-
#define HW_ATL_NIC_NAME "aQuantia AQtion 10Gbit Network Adapter"
#define AQ_HWREV_ANY 0
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
index a607e25dfbff..efd90ea575f1 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
@@ -43,9 +43,6 @@ static const struct pci_device_id aq_pci_tbl[] = {
{ PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC111S), },
{ PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC112S), },
- { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC111E), },
- { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC112E), },
-
{}
};
@@ -75,9 +72,6 @@ static const struct aq_board_revision_s hw_atl_boards[] = {
{ AQ_DEVICE_ID_AQC109S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc109s, },
{ AQ_DEVICE_ID_AQC111S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc111s, },
{ AQ_DEVICE_ID_AQC112S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc112s, },
-
- { AQ_DEVICE_ID_AQC111E, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc111e, },
- { AQ_DEVICE_ID_AQC112E, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc112e, },
};
MODULE_DEVICE_TABLE(pci, aq_pci_tbl);
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h
index 2cc8dacfdc27..b1c0b6850e60 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h
@@ -32,9 +32,6 @@ extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc109;
#define hw_atl_b0_caps_aqc111s hw_atl_b0_caps_aqc108
#define hw_atl_b0_caps_aqc112s hw_atl_b0_caps_aqc109
-#define hw_atl_b0_caps_aqc111e hw_atl_b0_caps_aqc108
-#define hw_atl_b0_caps_aqc112e hw_atl_b0_caps_aqc109
-
extern const struct aq_hw_ops hw_atl_ops_b0;
#define hw_atl_ops_b1 hw_atl_ops_b0
--
2.17.1
^ permalink raw reply related [flat|nested] 24+ messages in thread