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>
This commit is contained in:
Коммит
5be90f9938
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
// 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_phy_temp)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (attr) {
|
||||
case hwmon_temp_input:
|
||||
err = aq_nic->aq_fw_ops->get_phy_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_phy_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;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
/* 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);
|
||||
|
||||
#endif /* AQ_DRVINFO_H */
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
@ -259,6 +261,8 @@ struct aq_fw_ops {
|
|||
|
||||
int (*update_stats)(struct aq_hw_s *self);
|
||||
|
||||
int (*get_phy_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);
|
||||
|
|
|
@ -53,6 +53,18 @@ void aq_hw_write_reg(struct aq_hw_s *hw, u32 reg, u32 value)
|
|||
writel(value, hw->mmio + reg);
|
||||
}
|
||||
|
||||
/* Most of 64-bit registers are in LSW, MSW form.
|
||||
Counters are normally implemented by HW as latched pairs:
|
||||
reading LSW first locks MSW, to overcome LSW overflow
|
||||
*/
|
||||
u64 aq_hw_read_reg64(struct aq_hw_s *hw, u32 reg)
|
||||
{
|
||||
u64 value = aq_hw_read_reg(hw, reg);
|
||||
|
||||
value |= (u64)aq_hw_read_reg(hw, reg + 4) << 32;
|
||||
return value;
|
||||
}
|
||||
|
||||
int aq_hw_err_from_flags(struct aq_hw_s *hw)
|
||||
{
|
||||
int err = 0;
|
||||
|
|
|
@ -35,6 +35,7 @@ void aq_hw_write_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk,
|
|||
u32 aq_hw_read_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk, u32 shift);
|
||||
u32 aq_hw_read_reg(struct aq_hw_s *hw, u32 reg);
|
||||
void aq_hw_write_reg(struct aq_hw_s *hw, u32 reg, u32 value);
|
||||
u64 aq_hw_read_reg64(struct aq_hw_s *hw, u32 reg);
|
||||
int aq_hw_err_from_flags(struct aq_hw_s *hw);
|
||||
|
||||
#endif /* AQ_HW_UTILS_H */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
@ -161,30 +172,48 @@ static int aq_nic_update_link_status(struct aq_nic_s *self)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void aq_nic_service_timer_cb(struct timer_list *t)
|
||||
static irqreturn_t aq_linkstate_threaded_isr(int irq, void *private)
|
||||
{
|
||||
struct aq_nic_s *self = from_timer(self, t, service_timer);
|
||||
int ctimer = AQ_CFG_SERVICE_TIMER_INTERVAL;
|
||||
int err = 0;
|
||||
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_task(struct work_struct *work)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/* If no link - use faster timer rate to detect link up asap */
|
||||
if (!netif_carrier_ok(self->ndev))
|
||||
ctimer = max(ctimer / 2, 1);
|
||||
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 + ctimer);
|
||||
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)
|
||||
|
@ -214,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;
|
||||
|
||||
|
@ -284,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;
|
||||
|
||||
|
@ -334,9 +367,11 @@ 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);
|
||||
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);
|
||||
|
@ -345,13 +380,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)
|
||||
|
@ -653,7 +700,14 @@ 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;
|
||||
|
@ -699,11 +753,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;
|
||||
}
|
||||
|
@ -840,7 +895,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;
|
||||
|
||||
|
@ -873,6 +930,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);
|
||||
|
||||
|
@ -900,14 +958,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:;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -92,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 {
|
||||
|
@ -104,6 +106,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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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), },
|
||||
|
@ -42,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), },
|
||||
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -74,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);
|
||||
|
@ -139,26 +134,27 @@ err_exit:
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -166,16 +162,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);
|
||||
}
|
||||
}
|
||||
|
@ -185,7 +187,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;
|
||||
}
|
||||
|
||||
|
@ -223,6 +225,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)
|
||||
|
@ -268,6 +272,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,
|
||||
|
@ -289,6 +294,8 @@ static int aq_pci_probe(struct pci_dev *pdev,
|
|||
if (err < 0)
|
||||
goto err_register;
|
||||
|
||||
aq_drvinfo_init(ndev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_register:
|
||||
|
@ -365,4 +372,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);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,9 +24,12 @@ 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);
|
||||
|
||||
int aq_pci_func_register_driver(void);
|
||||
void aq_pci_func_unregister_driver(void);
|
||||
|
||||
#endif /* AQ_PCI_FUNC_H */
|
||||
|
|
|
@ -350,10 +350,10 @@ err_exit:
|
|||
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;
|
||||
|
|
|
@ -388,10 +388,10 @@ err_exit:
|
|||
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;
|
||||
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
@ -65,44 +60,24 @@ u32 hw_atl_rpb_rx_dma_drop_pkt_cnt_get(struct aq_hw_s *aq_hw)
|
|||
return aq_hw_read_reg(aq_hw, HW_ATL_RPB_RX_DMA_DROP_PKT_CNT_ADR);
|
||||
}
|
||||
|
||||
u32 hw_atl_stats_rx_dma_good_octet_counterlsw_get(struct aq_hw_s *aq_hw)
|
||||
u64 hw_atl_stats_rx_dma_good_octet_counter_get(struct aq_hw_s *aq_hw)
|
||||
{
|
||||
return aq_hw_read_reg(aq_hw, HW_ATL_STATS_RX_DMA_GOOD_OCTET_COUNTERLSW);
|
||||
return aq_hw_read_reg64(aq_hw, HW_ATL_STATS_RX_DMA_GOOD_OCTET_COUNTERLSW);
|
||||
}
|
||||
|
||||
u32 hw_atl_stats_rx_dma_good_pkt_counterlsw_get(struct aq_hw_s *aq_hw)
|
||||
u64 hw_atl_stats_rx_dma_good_pkt_counter_get(struct aq_hw_s *aq_hw)
|
||||
{
|
||||
return aq_hw_read_reg(aq_hw, HW_ATL_STATS_RX_DMA_GOOD_PKT_COUNTERLSW);
|
||||
return aq_hw_read_reg64(aq_hw, HW_ATL_STATS_RX_DMA_GOOD_PKT_COUNTERLSW);
|
||||
}
|
||||
|
||||
u32 hw_atl_stats_tx_dma_good_octet_counterlsw_get(struct aq_hw_s *aq_hw)
|
||||
u64 hw_atl_stats_tx_dma_good_octet_counter_get(struct aq_hw_s *aq_hw)
|
||||
{
|
||||
return aq_hw_read_reg(aq_hw, HW_ATL_STATS_TX_DMA_GOOD_OCTET_COUNTERLSW);
|
||||
return aq_hw_read_reg64(aq_hw, HW_ATL_STATS_TX_DMA_GOOD_OCTET_COUNTERLSW);
|
||||
}
|
||||
|
||||
u32 hw_atl_stats_tx_dma_good_pkt_counterlsw_get(struct aq_hw_s *aq_hw)
|
||||
u64 hw_atl_stats_tx_dma_good_pkt_counter_get(struct aq_hw_s *aq_hw)
|
||||
{
|
||||
return aq_hw_read_reg(aq_hw, HW_ATL_STATS_TX_DMA_GOOD_PKT_COUNTERLSW);
|
||||
}
|
||||
|
||||
u32 hw_atl_stats_rx_dma_good_octet_countermsw_get(struct aq_hw_s *aq_hw)
|
||||
{
|
||||
return aq_hw_read_reg(aq_hw, HW_ATL_STATS_RX_DMA_GOOD_OCTET_COUNTERMSW);
|
||||
}
|
||||
|
||||
u32 hw_atl_stats_rx_dma_good_pkt_countermsw_get(struct aq_hw_s *aq_hw)
|
||||
{
|
||||
return aq_hw_read_reg(aq_hw, HW_ATL_STATS_RX_DMA_GOOD_PKT_COUNTERMSW);
|
||||
}
|
||||
|
||||
u32 hw_atl_stats_tx_dma_good_octet_countermsw_get(struct aq_hw_s *aq_hw)
|
||||
{
|
||||
return aq_hw_read_reg(aq_hw, HW_ATL_STATS_TX_DMA_GOOD_OCTET_COUNTERMSW);
|
||||
}
|
||||
|
||||
u32 hw_atl_stats_tx_dma_good_pkt_countermsw_get(struct aq_hw_s *aq_hw)
|
||||
{
|
||||
return aq_hw_read_reg(aq_hw, HW_ATL_STATS_TX_DMA_GOOD_PKT_COUNTERMSW);
|
||||
return aq_hw_read_reg64(aq_hw, HW_ATL_STATS_TX_DMA_GOOD_PKT_COUNTERLSW);
|
||||
}
|
||||
|
||||
/* interrupt */
|
||||
|
|
|
@ -40,29 +40,17 @@ u32 hw_atl_glb_soft_res_get(struct aq_hw_s *aq_hw);
|
|||
|
||||
u32 hw_atl_rpb_rx_dma_drop_pkt_cnt_get(struct aq_hw_s *aq_hw);
|
||||
|
||||
/* get rx dma good octet counter lsw */
|
||||
u32 hw_atl_stats_rx_dma_good_octet_counterlsw_get(struct aq_hw_s *aq_hw);
|
||||
/* get rx dma good octet counter */
|
||||
u64 hw_atl_stats_rx_dma_good_octet_counter_get(struct aq_hw_s *aq_hw);
|
||||
|
||||
/* get rx dma good packet counter lsw */
|
||||
u32 hw_atl_stats_rx_dma_good_pkt_counterlsw_get(struct aq_hw_s *aq_hw);
|
||||
/* get rx dma good packet counter */
|
||||
u64 hw_atl_stats_rx_dma_good_pkt_counter_get(struct aq_hw_s *aq_hw);
|
||||
|
||||
/* get tx dma good octet counter lsw */
|
||||
u32 hw_atl_stats_tx_dma_good_octet_counterlsw_get(struct aq_hw_s *aq_hw);
|
||||
/* get tx dma good octet counter */
|
||||
u64 hw_atl_stats_tx_dma_good_octet_counter_get(struct aq_hw_s *aq_hw);
|
||||
|
||||
/* get tx dma good packet counter lsw */
|
||||
u32 hw_atl_stats_tx_dma_good_pkt_counterlsw_get(struct aq_hw_s *aq_hw);
|
||||
|
||||
/* get rx dma good octet counter msw */
|
||||
u32 hw_atl_stats_rx_dma_good_octet_countermsw_get(struct aq_hw_s *aq_hw);
|
||||
|
||||
/* get rx dma good packet counter msw */
|
||||
u32 hw_atl_stats_rx_dma_good_pkt_countermsw_get(struct aq_hw_s *aq_hw);
|
||||
|
||||
/* get tx dma good octet counter msw */
|
||||
u32 hw_atl_stats_tx_dma_good_octet_countermsw_get(struct aq_hw_s *aq_hw);
|
||||
|
||||
/* get tx dma good packet counter msw */
|
||||
u32 hw_atl_stats_tx_dma_good_pkt_countermsw_get(struct aq_hw_s *aq_hw);
|
||||
/* get tx dma good packet counter */
|
||||
u64 hw_atl_stats_tx_dma_good_pkt_counter_get(struct aq_hw_s *aq_hw);
|
||||
|
||||
/* get msm rx errors counter register */
|
||||
u32 hw_atl_reg_mac_msm_rx_errs_cnt_get(struct aq_hw_s *aq_hw);
|
||||
|
@ -82,9 +70,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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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:;
|
||||
|
@ -763,6 +763,7 @@ static int hw_atl_fw1x_deinit(struct aq_hw_s *self)
|
|||
int hw_atl_utils_update_stats(struct aq_hw_s *self)
|
||||
{
|
||||
struct hw_atl_utils_mbox mbox;
|
||||
struct aq_stats_s *cs = &self->curr_stats;
|
||||
|
||||
hw_atl_utils_mpi_read_stats(self, &mbox);
|
||||
|
||||
|
@ -789,10 +790,11 @@ 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);
|
||||
|
||||
cs->dma_pkt_rc = hw_atl_stats_rx_dma_good_pkt_counter_get(self);
|
||||
cs->dma_pkt_tc = hw_atl_stats_tx_dma_good_pkt_counter_get(self);
|
||||
cs->dma_oct_rc = hw_atl_stats_rx_dma_good_octet_counter_get(self);
|
||||
cs->dma_oct_tc = hw_atl_stats_tx_dma_good_octet_counter_get(self);
|
||||
|
||||
memcpy(&self->last_stats, &mbox.stats, sizeof(mbox.stats));
|
||||
|
||||
|
@ -960,6 +962,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_phy_temp = NULL,
|
||||
.set_power = aq_fw1x_set_power,
|
||||
.set_eee_rate = NULL,
|
||||
.get_eee_rate = NULL,
|
||||
|
|
|
@ -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_phy_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_phy_temp = aq_fw2x_get_phy_temp,
|
||||
.set_power = aq_fw2x_set_power,
|
||||
.set_eee_rate = aq_fw2x_set_eee_rate,
|
||||
.get_eee_rate = aq_fw2x_get_eee_rate,
|
||||
|
|
Загрузка…
Ссылка в новой задаче