Skip to content

Commit 5be90f9

Browse files
committed
Merge branch 'aquantia-next'
Igor Russkikh says: ==================== net: atlantic: Aquantia driver updates 2019-04 This patchset contains various improvements: - Work targeting link up speedups: link interrupt introduced, some other logic changes to imrove this. - FW operations securing with mutex - Counters and statistics logic improved by Dmitry - read out of chip temperature via hwmon interface implemented by Yana and Nikita. v4 changes: - remove drvinfo_exit noop - 64bit stats should be readed out sequentially (lsw, then msw) declare 64bit read ops for that v3 changes: - temp ops renamed to phy_temp ops - mutex commits squashed for better structure v2 changes: - use threaded irq for link state handling - rework hwmon via devm_hwmon_device_register_with_info Extra comments on review from Andrew: - direct device name pointer is used in hwmon registration. This causes hwmon device to derive possible interface name changes - Will consider sanity checks for firmware mutex lock separately. Right now there is no single point exsists where such check could be easily added. - There is no way now to fetch and configure min/max/crit temperatures via FW. Will investigate this separately. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 2b5bc3c + 9eec030 commit 5be90f9

22 files changed

+427
-128
lines changed

drivers/net/ethernet/aquantia/atlantic/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ atlantic-objs := aq_main.o \
3636
aq_ring.o \
3737
aq_hw_utils.o \
3838
aq_ethtool.o \
39+
aq_drvinfo.o \
3940
aq_filters.o \
4041
hw_atl/hw_atl_a0.o \
4142
hw_atl/hw_atl_b0.o \

drivers/net/ethernet/aquantia/atlantic/aq_common.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,6 @@
4141
#define AQ_DEVICE_ID_AQC111S 0x91B1
4242
#define AQ_DEVICE_ID_AQC112S 0x92B1
4343

44-
#define AQ_DEVICE_ID_AQC111E 0x51B1
45-
#define AQ_DEVICE_ID_AQC112E 0x52B1
46-
4744
#define HW_ATL_NIC_NAME "aQuantia AQtion 10Gbit Network Adapter"
4845

4946
#define AQ_HWREV_ANY 0
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
/* Copyright (C) 2014-2019 aQuantia Corporation. */
3+
4+
/* File aq_drvinfo.c: Definition of common code for firmware info in sys.*/
5+
6+
#include <linux/init.h>
7+
#include <linux/kobject.h>
8+
#include <linux/module.h>
9+
#include <linux/stat.h>
10+
#include <linux/string.h>
11+
#include <linux/hwmon.h>
12+
#include <linux/uaccess.h>
13+
14+
#include "aq_drvinfo.h"
15+
16+
static int aq_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
17+
u32 attr, int channel, long *value)
18+
{
19+
struct aq_nic_s *aq_nic = dev_get_drvdata(dev);
20+
int temp;
21+
int err;
22+
23+
if (!aq_nic)
24+
return -EIO;
25+
26+
if (type != hwmon_temp)
27+
return -EOPNOTSUPP;
28+
29+
if (!aq_nic->aq_fw_ops->get_phy_temp)
30+
return -EOPNOTSUPP;
31+
32+
switch (attr) {
33+
case hwmon_temp_input:
34+
err = aq_nic->aq_fw_ops->get_phy_temp(aq_nic->aq_hw, &temp);
35+
*value = temp;
36+
return err;
37+
default:
38+
return -EOPNOTSUPP;
39+
}
40+
}
41+
42+
static int aq_hwmon_read_string(struct device *dev,
43+
enum hwmon_sensor_types type,
44+
u32 attr, int channel, const char **str)
45+
{
46+
struct aq_nic_s *aq_nic = dev_get_drvdata(dev);
47+
48+
if (!aq_nic)
49+
return -EIO;
50+
51+
if (type != hwmon_temp)
52+
return -EOPNOTSUPP;
53+
54+
if (!aq_nic->aq_fw_ops->get_phy_temp)
55+
return -EOPNOTSUPP;
56+
57+
switch (attr) {
58+
case hwmon_temp_label:
59+
*str = "PHY Temperature";
60+
return 0;
61+
default:
62+
return -EOPNOTSUPP;
63+
}
64+
}
65+
66+
static umode_t aq_hwmon_is_visible(const void *data,
67+
enum hwmon_sensor_types type,
68+
u32 attr, int channel)
69+
{
70+
if (type != hwmon_temp)
71+
return 0;
72+
73+
switch (attr) {
74+
case hwmon_temp_input:
75+
case hwmon_temp_label:
76+
return 0444;
77+
default:
78+
return 0;
79+
}
80+
}
81+
82+
static const struct hwmon_ops aq_hwmon_ops = {
83+
.is_visible = aq_hwmon_is_visible,
84+
.read = aq_hwmon_read,
85+
.read_string = aq_hwmon_read_string,
86+
};
87+
88+
static u32 aq_hwmon_temp_config[] = {
89+
HWMON_T_INPUT | HWMON_T_LABEL,
90+
0,
91+
};
92+
93+
static const struct hwmon_channel_info aq_hwmon_temp = {
94+
.type = hwmon_temp,
95+
.config = aq_hwmon_temp_config,
96+
};
97+
98+
static const struct hwmon_channel_info *aq_hwmon_info[] = {
99+
&aq_hwmon_temp,
100+
NULL,
101+
};
102+
103+
static const struct hwmon_chip_info aq_hwmon_chip_info = {
104+
.ops = &aq_hwmon_ops,
105+
.info = aq_hwmon_info,
106+
};
107+
108+
int aq_drvinfo_init(struct net_device *ndev)
109+
{
110+
struct aq_nic_s *aq_nic = netdev_priv(ndev);
111+
struct device *dev = &aq_nic->pdev->dev;
112+
struct device *hwmon_dev;
113+
int err = 0;
114+
115+
hwmon_dev = devm_hwmon_device_register_with_info(dev,
116+
ndev->name,
117+
aq_nic,
118+
&aq_hwmon_chip_info,
119+
NULL);
120+
121+
if (IS_ERR(hwmon_dev))
122+
err = PTR_ERR(hwmon_dev);
123+
124+
return err;
125+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
/* Copyright (C) 2014-2017 aQuantia Corporation. */
3+
4+
/* File aq_drvinfo.h: Declaration of common code for firmware info in sys.*/
5+
6+
#ifndef AQ_DRVINFO_H
7+
#define AQ_DRVINFO_H
8+
9+
#include "aq_nic.h"
10+
#include "aq_hw.h"
11+
#include "hw_atl/hw_atl_utils.h"
12+
13+
int aq_drvinfo_init(struct net_device *ndev);
14+
15+
#endif /* AQ_DRVINFO_H */

drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -405,8 +405,10 @@ static int aq_ethtool_get_eee(struct net_device *ndev, struct ethtool_eee *eee)
405405
if (!aq_nic->aq_fw_ops->get_eee_rate)
406406
return -EOPNOTSUPP;
407407

408+
mutex_lock(&aq_nic->fwreq_mutex);
408409
err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
409410
&supported_rates);
411+
mutex_unlock(&aq_nic->fwreq_mutex);
410412
if (err < 0)
411413
return err;
412414

@@ -439,8 +441,10 @@ static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_eee *eee)
439441
!aq_nic->aq_fw_ops->set_eee_rate))
440442
return -EOPNOTSUPP;
441443

444+
mutex_lock(&aq_nic->fwreq_mutex);
442445
err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
443446
&supported_rates);
447+
mutex_unlock(&aq_nic->fwreq_mutex);
444448
if (err < 0)
445449
return err;
446450

@@ -452,20 +456,28 @@ static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_eee *eee)
452456
cfg->eee_speeds = 0;
453457
}
454458

455-
return aq_nic->aq_fw_ops->set_eee_rate(aq_nic->aq_hw, rate);
459+
mutex_lock(&aq_nic->fwreq_mutex);
460+
err = aq_nic->aq_fw_ops->set_eee_rate(aq_nic->aq_hw, rate);
461+
mutex_unlock(&aq_nic->fwreq_mutex);
462+
463+
return err;
456464
}
457465

458466
static int aq_ethtool_nway_reset(struct net_device *ndev)
459467
{
460468
struct aq_nic_s *aq_nic = netdev_priv(ndev);
469+
int err = 0;
461470

462471
if (unlikely(!aq_nic->aq_fw_ops->renegotiate))
463472
return -EOPNOTSUPP;
464473

465-
if (netif_running(ndev))
466-
return aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw);
474+
if (netif_running(ndev)) {
475+
mutex_lock(&aq_nic->fwreq_mutex);
476+
err = aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw);
477+
mutex_unlock(&aq_nic->fwreq_mutex);
478+
}
467479

468-
return 0;
480+
return err;
469481
}
470482

471483
static void aq_ethtool_get_pauseparam(struct net_device *ndev,
@@ -503,7 +515,9 @@ static int aq_ethtool_set_pauseparam(struct net_device *ndev,
503515
else
504516
aq_nic->aq_hw->aq_nic_cfg->flow_control &= ~AQ_NIC_FC_TX;
505517

518+
mutex_lock(&aq_nic->fwreq_mutex);
506519
err = aq_nic->aq_fw_ops->set_flow_control(aq_nic->aq_hw);
520+
mutex_unlock(&aq_nic->fwreq_mutex);
507521

508522
return err;
509523
}

drivers/net/ethernet/aquantia/atlantic/aq_hw.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ struct aq_stats_s {
8888
#define AQ_HW_IRQ_MSI 2U
8989
#define AQ_HW_IRQ_MSIX 3U
9090

91+
#define AQ_HW_SERVICE_IRQS 1U
92+
9193
#define AQ_HW_POWER_STATE_D0 0U
9294
#define AQ_HW_POWER_STATE_D3 3U
9395

@@ -259,6 +261,8 @@ struct aq_fw_ops {
259261

260262
int (*update_stats)(struct aq_hw_s *self);
261263

264+
int (*get_phy_temp)(struct aq_hw_s *self, int *temp);
265+
262266
u32 (*get_flow_control)(struct aq_hw_s *self, u32 *fcmode);
263267

264268
int (*set_flow_control)(struct aq_hw_s *self);

drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,18 @@ void aq_hw_write_reg(struct aq_hw_s *hw, u32 reg, u32 value)
5353
writel(value, hw->mmio + reg);
5454
}
5555

56+
/* Most of 64-bit registers are in LSW, MSW form.
57+
Counters are normally implemented by HW as latched pairs:
58+
reading LSW first locks MSW, to overcome LSW overflow
59+
*/
60+
u64 aq_hw_read_reg64(struct aq_hw_s *hw, u32 reg)
61+
{
62+
u64 value = aq_hw_read_reg(hw, reg);
63+
64+
value |= (u64)aq_hw_read_reg(hw, reg + 4) << 32;
65+
return value;
66+
}
67+
5668
int aq_hw_err_from_flags(struct aq_hw_s *hw)
5769
{
5870
int err = 0;

drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ void aq_hw_write_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk,
3535
u32 aq_hw_read_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk, u32 shift);
3636
u32 aq_hw_read_reg(struct aq_hw_s *hw, u32 reg);
3737
void aq_hw_write_reg(struct aq_hw_s *hw, u32 reg, u32 value);
38+
u64 aq_hw_read_reg64(struct aq_hw_s *hw, u32 reg);
3839
int aq_hw_err_from_flags(struct aq_hw_s *hw);
3940

4041
#endif /* AQ_HW_UTILS_H */

drivers/net/ethernet/aquantia/atlantic/aq_main.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,17 @@ MODULE_VERSION(AQ_CFG_DRV_VERSION);
2323
MODULE_AUTHOR(AQ_CFG_DRV_AUTHOR);
2424
MODULE_DESCRIPTION(AQ_CFG_DRV_DESC);
2525

26+
const char aq_ndev_driver_name[] = AQ_CFG_DRV_NAME;
27+
2628
static const struct net_device_ops aq_ndev_ops;
2729

30+
static struct workqueue_struct *aq_ndev_wq;
31+
32+
void aq_ndev_schedule_work(struct work_struct *work)
33+
{
34+
queue_work(aq_ndev_wq, work);
35+
}
36+
2837
struct net_device *aq_ndev_alloc(void)
2938
{
3039
struct net_device *ndev = NULL;
@@ -209,3 +218,35 @@ static const struct net_device_ops aq_ndev_ops = {
209218
.ndo_vlan_rx_add_vid = aq_ndo_vlan_rx_add_vid,
210219
.ndo_vlan_rx_kill_vid = aq_ndo_vlan_rx_kill_vid,
211220
};
221+
222+
static int __init aq_ndev_init_module(void)
223+
{
224+
int ret;
225+
226+
aq_ndev_wq = create_singlethread_workqueue(aq_ndev_driver_name);
227+
if (!aq_ndev_wq) {
228+
pr_err("Failed to create workqueue\n");
229+
return -ENOMEM;
230+
}
231+
232+
ret = aq_pci_func_register_driver();
233+
if (ret) {
234+
destroy_workqueue(aq_ndev_wq);
235+
return ret;
236+
}
237+
238+
return 0;
239+
}
240+
241+
static void __exit aq_ndev_exit_module(void)
242+
{
243+
aq_pci_func_unregister_driver();
244+
245+
if (aq_ndev_wq) {
246+
destroy_workqueue(aq_ndev_wq);
247+
aq_ndev_wq = NULL;
248+
}
249+
}
250+
251+
module_init(aq_ndev_init_module);
252+
module_exit(aq_ndev_exit_module);

drivers/net/ethernet/aquantia/atlantic/aq_main.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
#define AQ_MAIN_H
1414

1515
#include "aq_common.h"
16+
#include "aq_nic.h"
1617

18+
void aq_ndev_schedule_work(struct work_struct *work);
1719
struct net_device *aq_ndev_alloc(void);
1820

1921
#endif /* AQ_MAIN_H */

0 commit comments

Comments
 (0)