Skip to content

Commit

Permalink
Merge branch 'aquantia-fixes'
Browse files Browse the repository at this point in the history
Igor Russkikh says:

====================
net: aquantia: Atlantic driver 12/2017 updates

The patchset contains important hardware fix for machines with large MRRS
and couple of improvement in stats and capabilities reporting

patch v3:
 - Fixed patch #7 after Andrew's finding. NIC level stats actually
   have to be cleaned only on hw struct creation (and this is done
   in kzalloc). On each hwinit we only have to reset link state
   to make sure hw stats update will not increment nic stats during init.

patch v2:
 - split into more detailed commits

Comment from David on wrong defines case will be submitted separately later
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
davem330 committed Dec 15, 2017
2 parents 35b99df + d4c242d commit 0a06069
Show file tree
Hide file tree
Showing 12 changed files with 177 additions and 106 deletions.
5 changes: 3 additions & 2 deletions drivers/net/ethernet/aquantia/atlantic/aq_cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
#define AQ_CFG_PCI_FUNC_MSIX_IRQS 9U
#define AQ_CFG_PCI_FUNC_PORTS 2U

#define AQ_CFG_SERVICE_TIMER_INTERVAL (2 * HZ)
#define AQ_CFG_SERVICE_TIMER_INTERVAL (1 * HZ)
#define AQ_CFG_POLLING_TIMER_INTERVAL ((unsigned int)(2 * HZ))

#define AQ_CFG_SKB_FRAGS_MAX 32U
Expand Down Expand Up @@ -80,6 +80,7 @@
#define AQ_CFG_DRV_VERSION __stringify(NIC_MAJOR_DRIVER_VERSION)"."\
__stringify(NIC_MINOR_DRIVER_VERSION)"."\
__stringify(NIC_BUILD_DRIVER_VERSION)"."\
__stringify(NIC_REVISION_DRIVER_VERSION)
__stringify(NIC_REVISION_DRIVER_VERSION) \
AQ_CFG_DRV_VERSION_SUFFIX

#endif /* AQ_CFG_H */
16 changes: 8 additions & 8 deletions drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@ static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
"OutUCast",
"OutMCast",
"OutBCast",
"InUCastOctects",
"OutUCastOctects",
"InMCastOctects",
"OutMCastOctects",
"InBCastOctects",
"OutBCastOctects",
"InOctects",
"OutOctects",
"InUCastOctets",
"OutUCastOctets",
"InMCastOctets",
"OutMCastOctets",
"InBCastOctets",
"OutBCastOctets",
"InOctets",
"OutOctets",
"InPacketsDma",
"OutPacketsDma",
"InOctetsDma",
Expand Down
29 changes: 26 additions & 3 deletions drivers/net/ethernet/aquantia/atlantic/aq_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,28 @@ struct aq_hw_link_status_s {
unsigned int mbps;
};

struct aq_stats_s {
u64 uprc;
u64 mprc;
u64 bprc;
u64 erpt;
u64 uptc;
u64 mptc;
u64 bptc;
u64 erpr;
u64 mbtc;
u64 bbtc;
u64 mbrc;
u64 bbrc;
u64 ubrc;
u64 ubtc;
u64 dpc;
u64 dma_pkt_rc;
u64 dma_pkt_tc;
u64 dma_oct_rc;
u64 dma_oct_tc;
};

#define AQ_HW_IRQ_INVALID 0U
#define AQ_HW_IRQ_LEGACY 1U
#define AQ_HW_IRQ_MSI 2U
Expand Down Expand Up @@ -85,7 +107,9 @@ struct aq_hw_ops {
void (*destroy)(struct aq_hw_s *self);

int (*get_hw_caps)(struct aq_hw_s *self,
struct aq_hw_caps_s *aq_hw_caps);
struct aq_hw_caps_s *aq_hw_caps,
unsigned short device,
unsigned short subsystem_device);

int (*hw_ring_tx_xmit)(struct aq_hw_s *self, struct aq_ring_s *aq_ring,
unsigned int frags);
Expand Down Expand Up @@ -164,8 +188,7 @@ struct aq_hw_ops {

int (*hw_update_stats)(struct aq_hw_s *self);

int (*hw_get_hw_stats)(struct aq_hw_s *self, u64 *data,
unsigned int *p_count);
struct aq_stats_s *(*hw_get_hw_stats)(struct aq_hw_s *self);

int (*hw_get_fw_version)(struct aq_hw_s *self, u32 *fw_version);

Expand Down
82 changes: 55 additions & 27 deletions drivers/net/ethernet/aquantia/atlantic/aq_nic.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ static unsigned int aq_itr_rx;
module_param_named(aq_itr_rx, aq_itr_rx, uint, 0644);
MODULE_PARM_DESC(aq_itr_rx, "RX interrupt throttle rate");

static void aq_nic_update_ndev_stats(struct aq_nic_s *self);

static void aq_nic_rss_init(struct aq_nic_s *self, unsigned int num_rss_queues)
{
struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg;
Expand Down Expand Up @@ -166,11 +168,8 @@ static int aq_nic_update_link_status(struct aq_nic_s *self)
static void aq_nic_service_timer_cb(struct timer_list *t)
{
struct aq_nic_s *self = from_timer(self, t, service_timer);
struct net_device *ndev = aq_nic_get_ndev(self);
int ctimer = AQ_CFG_SERVICE_TIMER_INTERVAL;
int err = 0;
unsigned int i = 0U;
struct aq_ring_stats_rx_s stats_rx;
struct aq_ring_stats_tx_s stats_tx;

if (aq_utils_obj_test(&self->header.flags, AQ_NIC_FLAGS_IS_NOT_READY))
goto err_exit;
Expand All @@ -182,23 +181,14 @@ static void aq_nic_service_timer_cb(struct timer_list *t)
if (self->aq_hw_ops.hw_update_stats)
self->aq_hw_ops.hw_update_stats(self->aq_hw);

memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s));
memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s));
for (i = AQ_DIMOF(self->aq_vec); i--;) {
if (self->aq_vec[i])
aq_vec_add_stats(self->aq_vec[i], &stats_rx, &stats_tx);
}
aq_nic_update_ndev_stats(self);

ndev->stats.rx_packets = stats_rx.packets;
ndev->stats.rx_bytes = stats_rx.bytes;
ndev->stats.rx_errors = stats_rx.errors;
ndev->stats.tx_packets = stats_tx.packets;
ndev->stats.tx_bytes = stats_tx.bytes;
ndev->stats.tx_errors = stats_tx.errors;
/* 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 + AQ_CFG_SERVICE_TIMER_INTERVAL);
mod_timer(&self->service_timer, jiffies + ctimer);
}

static void aq_nic_polling_timer_cb(struct timer_list *t)
Expand All @@ -222,7 +212,7 @@ static struct net_device *aq_nic_ndev_alloc(void)

struct aq_nic_s *aq_nic_alloc_cold(const struct net_device_ops *ndev_ops,
const struct ethtool_ops *et_ops,
struct device *dev,
struct pci_dev *pdev,
struct aq_pci_func_s *aq_pci_func,
unsigned int port,
const struct aq_hw_ops *aq_hw_ops)
Expand All @@ -242,7 +232,7 @@ struct aq_nic_s *aq_nic_alloc_cold(const struct net_device_ops *ndev_ops,
ndev->netdev_ops = ndev_ops;
ndev->ethtool_ops = et_ops;

SET_NETDEV_DEV(ndev, dev);
SET_NETDEV_DEV(ndev, &pdev->dev);

ndev->if_port = port;
self->ndev = ndev;
Expand All @@ -254,7 +244,8 @@ struct aq_nic_s *aq_nic_alloc_cold(const struct net_device_ops *ndev_ops,

self->aq_hw = self->aq_hw_ops.create(aq_pci_func, self->port,
&self->aq_hw_ops);
err = self->aq_hw_ops.get_hw_caps(self->aq_hw, &self->aq_hw_caps);
err = self->aq_hw_ops.get_hw_caps(self->aq_hw, &self->aq_hw_caps,
pdev->device, pdev->subsystem_device);
if (err < 0)
goto err_exit;

Expand Down Expand Up @@ -749,16 +740,40 @@ int aq_nic_get_regs_count(struct aq_nic_s *self)

void aq_nic_get_stats(struct aq_nic_s *self, u64 *data)
{
struct aq_vec_s *aq_vec = NULL;
unsigned int i = 0U;
unsigned int count = 0U;
int err = 0;
struct aq_vec_s *aq_vec = NULL;
struct aq_stats_s *stats = self->aq_hw_ops.hw_get_hw_stats(self->aq_hw);

err = self->aq_hw_ops.hw_get_hw_stats(self->aq_hw, data, &count);
if (err < 0)
if (!stats)
goto err_exit;

data += count;
data[i] = stats->uprc + stats->mprc + stats->bprc;
data[++i] = stats->uprc;
data[++i] = stats->mprc;
data[++i] = stats->bprc;
data[++i] = stats->erpt;
data[++i] = stats->uptc + stats->mptc + stats->bptc;
data[++i] = stats->uptc;
data[++i] = stats->mptc;
data[++i] = stats->bptc;
data[++i] = stats->ubrc;
data[++i] = stats->ubtc;
data[++i] = stats->mbrc;
data[++i] = stats->mbtc;
data[++i] = stats->bbrc;
data[++i] = stats->bbtc;
data[++i] = stats->ubrc + stats->mbrc + stats->bbrc;
data[++i] = stats->ubtc + stats->mbtc + stats->bbtc;
data[++i] = stats->dma_pkt_rc;
data[++i] = stats->dma_pkt_tc;
data[++i] = stats->dma_oct_rc;
data[++i] = stats->dma_oct_tc;
data[++i] = stats->dpc;

i++;

data += i;
count = 0U;

for (i = 0U, aq_vec = self->aq_vec[0];
Expand All @@ -768,7 +783,20 @@ void aq_nic_get_stats(struct aq_nic_s *self, u64 *data)
}

err_exit:;
(void)err;
}

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_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.tx_errors = stats->erpt;
ndev->stats.multicast = stats->mprc;
}

void aq_nic_get_link_ksettings(struct aq_nic_s *self,
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/aquantia/atlantic/aq_nic.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ struct aq_nic_cfg_s {

struct aq_nic_s *aq_nic_alloc_cold(const struct net_device_ops *ndev_ops,
const struct ethtool_ops *et_ops,
struct device *dev,
struct pci_dev *pdev,
struct aq_pci_func_s *aq_pci_func,
unsigned int port,
const struct aq_hw_ops *aq_hw_ops);
Expand Down
5 changes: 3 additions & 2 deletions drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,16 @@ struct aq_pci_func_s *aq_pci_func_alloc(struct aq_hw_ops *aq_hw_ops,
pci_set_drvdata(pdev, self);
self->pdev = pdev;

err = aq_hw_ops->get_hw_caps(NULL, &self->aq_hw_caps);
err = aq_hw_ops->get_hw_caps(NULL, &self->aq_hw_caps, pdev->device,
pdev->subsystem_device);
if (err < 0)
goto err_exit;

self->ports = self->aq_hw_caps.ports;

for (port = 0; port < self->ports; ++port) {
struct aq_nic_s *aq_nic = aq_nic_alloc_cold(ndev_ops, eth_ops,
&pdev->dev, self,
pdev, self,
port, aq_hw_ops);

if (!aq_nic) {
Expand Down
17 changes: 16 additions & 1 deletion drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,20 @@
#include "hw_atl_a0_internal.h"

static int hw_atl_a0_get_hw_caps(struct aq_hw_s *self,
struct aq_hw_caps_s *aq_hw_caps)
struct aq_hw_caps_s *aq_hw_caps,
unsigned short device,
unsigned short subsystem_device)
{
memcpy(aq_hw_caps, &hw_atl_a0_hw_caps_, sizeof(*aq_hw_caps));

if (device == HW_ATL_DEVICE_ID_D108 && subsystem_device == 0x0001)
aq_hw_caps->link_speed_msk &= ~HW_ATL_A0_RATE_10G;

if (device == HW_ATL_DEVICE_ID_D109 && subsystem_device == 0x0001) {
aq_hw_caps->link_speed_msk &= ~HW_ATL_A0_RATE_10G;
aq_hw_caps->link_speed_msk &= ~HW_ATL_A0_RATE_5G;
}

return 0;
}

Expand Down Expand Up @@ -333,6 +344,10 @@ static int hw_atl_a0_hw_init(struct aq_hw_s *self,
hw_atl_a0_hw_rss_set(self, &aq_nic_cfg->aq_rss);
hw_atl_a0_hw_rss_hash_set(self, &aq_nic_cfg->aq_rss);

/* Reset link status and read out initial hardware counters */
self->aq_link_status.mbps = 0;
hw_atl_utils_update_stats(self);

err = aq_hw_err_from_flags(self);
if (err < 0)
goto err_exit;
Expand Down
29 changes: 28 additions & 1 deletion drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,23 @@
#include "hw_atl_utils.h"
#include "hw_atl_llh.h"
#include "hw_atl_b0_internal.h"
#include "hw_atl_llh_internal.h"

static int hw_atl_b0_get_hw_caps(struct aq_hw_s *self,
struct aq_hw_caps_s *aq_hw_caps)
struct aq_hw_caps_s *aq_hw_caps,
unsigned short device,
unsigned short subsystem_device)
{
memcpy(aq_hw_caps, &hw_atl_b0_hw_caps_, sizeof(*aq_hw_caps));

if (device == HW_ATL_DEVICE_ID_D108 && subsystem_device == 0x0001)
aq_hw_caps->link_speed_msk &= ~HW_ATL_B0_RATE_10G;

if (device == HW_ATL_DEVICE_ID_D109 && subsystem_device == 0x0001) {
aq_hw_caps->link_speed_msk &= ~HW_ATL_B0_RATE_10G;
aq_hw_caps->link_speed_msk &= ~HW_ATL_B0_RATE_5G;
}

return 0;
}

Expand Down Expand Up @@ -357,6 +369,7 @@ static int hw_atl_b0_hw_init(struct aq_hw_s *self,
};

int err = 0;
u32 val;

self->aq_nic_cfg = aq_nic_cfg;

Expand All @@ -374,6 +387,20 @@ static int hw_atl_b0_hw_init(struct aq_hw_s *self,
hw_atl_b0_hw_rss_set(self, &aq_nic_cfg->aq_rss);
hw_atl_b0_hw_rss_hash_set(self, &aq_nic_cfg->aq_rss);

/* Force limit MRRS on RDM/TDM to 2K */
val = aq_hw_read_reg(self, pci_reg_control6_adr);
aq_hw_write_reg(self, pci_reg_control6_adr, (val & ~0x707) | 0x404);

/* TX DMA total request limit. B0 hardware is not capable to
* handle more than (8K-MRRS) incoming DMA data.
* Value 24 in 256byte units
*/
aq_hw_write_reg(self, tx_dma_total_req_limit_adr, 24);

/* Reset link status and read out initial hardware counters */
self->aq_link_status.mbps = 0;
hw_atl_utils_update_stats(self);

err = aq_hw_err_from_flags(self);
if (err < 0)
goto err_exit;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2343,6 +2343,9 @@
#define tx_dma_desc_base_addrmsw_adr(descriptor) \
(0x00007c04u + (descriptor) * 0x40)

/* tx dma total request limit */
#define tx_dma_total_req_limit_adr 0x00007b20u

/* tx interrupt moderation control register definitions
* Preprocessor definitions for TX Interrupt Moderation Control Register
* Base Address: 0x00008980
Expand All @@ -2369,6 +2372,9 @@
/* default value of bitfield reg_res_dsbl */
#define pci_reg_res_dsbl_default 0x1

/* PCI core control register */
#define pci_reg_control6_adr 0x1014u

/* global microprocessor scratch pad definitions */
#define glb_cpu_scratch_scp_adr(scratch_scp) (0x00000300u + (scratch_scp) * 0x4)

Expand Down
Loading

0 comments on commit 0a06069

Please sign in to comment.