Commit bf2320a6 authored by David S. Miller's avatar David S. Miller

Merge branch 'net-atlantic-A2-support'

Igor Russkikh says:

====================
net: atlantic: A2 support

This patchset adds support for the new generation of Atlantic NICs.

Chip generations are mostly compatible register-wise, but there are still
some differences. Therefore we've made some of first generation (A1) code
non-static to re-use it where possible.

Some pieces are A2 specific, in which case we redefine/extend such APIs.

v2:
 * removed #pragma pack (2 structures require the packed attribute);
 * use defines instead of magic numbers where possible;

v1: https://patchwork.ozlabs.org/cover/1276220/
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e00edb4e 43c670c8
......@@ -25,6 +25,10 @@ atlantic-objs := aq_main.o \
hw_atl/hw_atl_utils.o \
hw_atl/hw_atl_utils_fw2x.o \
hw_atl/hw_atl_llh.o \
hw_atl2/hw_atl2.o \
hw_atl2/hw_atl2_utils.o \
hw_atl2/hw_atl2_utils_fw.o \
hw_atl2/hw_atl2_llh.o \
macsec/macsec_api.o
atlantic-$(CONFIG_MACSEC) += aq_macsec.o
......
......@@ -80,8 +80,8 @@
#define AQ_CFG_LOCK_TRYS 100U
#define AQ_CFG_DRV_AUTHOR "aQuantia"
#define AQ_CFG_DRV_DESC "aQuantia Corporation(R) Network Driver"
#define AQ_CFG_DRV_AUTHOR "Marvell"
#define AQ_CFG_DRV_DESC "Marvell (Aquantia) Corporation(R) Network Driver"
#define AQ_CFG_DRV_NAME "atlantic"
#endif /* AQ_CFG_H */
......@@ -37,22 +37,31 @@
#define AQ_DEVICE_ID_AQC111S 0x91B1
#define AQ_DEVICE_ID_AQC112S 0x92B1
#define HW_ATL_NIC_NAME "aQuantia AQtion 10Gbit Network Adapter"
#define AQ_DEVICE_ID_AQC113DEV 0x00C0
#define AQ_DEVICE_ID_AQC113CS 0x94C0
#define AQ_DEVICE_ID_AQC114CS 0x93C0
#define AQ_DEVICE_ID_AQC113 0x04C0
#define AQ_DEVICE_ID_AQC113C 0x14C0
#define AQ_DEVICE_ID_AQC115C 0x12C0
#define HW_ATL_NIC_NAME "Marvell (aQuantia) AQtion 10Gbit Network Adapter"
#define AQ_HWREV_ANY 0
#define AQ_HWREV_1 1
#define AQ_HWREV_2 2
#define AQ_NIC_RATE_10G BIT(0)
#define AQ_NIC_RATE_5G BIT(1)
#define AQ_NIC_RATE_5GSR BIT(2)
#define AQ_NIC_RATE_2GS BIT(3)
#define AQ_NIC_RATE_1G BIT(4)
#define AQ_NIC_RATE_100M BIT(5)
#define AQ_NIC_RATE_EEE_10G BIT(6)
#define AQ_NIC_RATE_EEE_5G BIT(7)
#define AQ_NIC_RATE_EEE_2GS BIT(8)
#define AQ_NIC_RATE_EEE_1G BIT(9)
#define AQ_NIC_RATE_10G BIT(0)
#define AQ_NIC_RATE_5G BIT(1)
#define AQ_NIC_RATE_5GSR BIT(2)
#define AQ_NIC_RATE_2GS BIT(3)
#define AQ_NIC_RATE_1G BIT(4)
#define AQ_NIC_RATE_100M BIT(5)
#define AQ_NIC_RATE_10M BIT(6)
#define AQ_NIC_RATE_EEE_10G BIT(7)
#define AQ_NIC_RATE_EEE_5G BIT(8)
#define AQ_NIC_RATE_EEE_2GS BIT(9)
#define AQ_NIC_RATE_EEE_1G BIT(10)
#define AQ_NIC_RATE_EEE_100M BIT(11)
#endif /* AQ_COMMON_H */
......@@ -611,6 +611,9 @@ static enum hw_atl_fw2x_rate eee_mask_to_ethtool_mask(u32 speed)
if (speed & AQ_NIC_RATE_EEE_1G)
rate |= SUPPORTED_1000baseT_Full;
if (speed & AQ_NIC_RATE_EEE_100M)
rate |= SUPPORTED_100baseT_Full;
return rate;
}
......
......@@ -55,6 +55,7 @@ struct aq_hw_caps_s {
u8 rx_rings;
bool flow_control;
bool is_64_dma;
u32 priv_data_len;
};
struct aq_hw_link_status_s {
......@@ -136,6 +137,19 @@ enum aq_priv_flags {
BIT(AQ_HW_LOOPBACK_PHYINT_SYS) |\
BIT(AQ_HW_LOOPBACK_PHYEXT_SYS))
#define ATL_HW_CHIP_MIPS 0x00000001U
#define ATL_HW_CHIP_TPO2 0x00000002U
#define ATL_HW_CHIP_RPF2 0x00000004U
#define ATL_HW_CHIP_MPI_AQ 0x00000010U
#define ATL_HW_CHIP_ATLANTIC 0x00800000U
#define ATL_HW_CHIP_REVISION_A0 0x01000000U
#define ATL_HW_CHIP_REVISION_B0 0x02000000U
#define ATL_HW_CHIP_REVISION_B1 0x04000000U
#define ATL_HW_CHIP_ANTIGUA 0x08000000U
#define ATL_HW_IS_CHIP_FEATURE(_HW_, _F_) (!!(ATL_HW_CHIP_##_F_ & \
(_HW_)->chip_features))
struct aq_hw_s {
atomic_t flags;
u8 rbl_enabled:1;
......@@ -159,6 +173,7 @@ struct aq_hw_s {
struct hw_atl_utils_fw_rpc rpc;
s64 ptp_clk_offset;
u16 phy_id;
void *priv;
};
struct aq_ring_s;
......@@ -182,6 +197,11 @@ struct aq_hw_ops {
int (*hw_set_mac_address)(struct aq_hw_s *self, u8 *mac_addr);
int (*hw_soft_reset)(struct aq_hw_s *self);
int (*hw_prepare)(struct aq_hw_s *self,
const struct aq_fw_ops **fw_ops);
int (*hw_reset)(struct aq_hw_s *self);
int (*hw_init)(struct aq_hw_s *self, u8 *mac_addr);
......@@ -254,7 +274,7 @@ struct aq_hw_ops {
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);
u32 (*hw_get_fw_version)(struct aq_hw_s *self);
int (*hw_set_offload)(struct aq_hw_s *self,
struct aq_nic_cfg_s *aq_nic_cfg);
......
......@@ -257,6 +257,20 @@ static void aq_nic_polling_timer_cb(struct timer_list *t)
AQ_CFG_POLLING_TIMER_INTERVAL);
}
static int aq_nic_hw_prepare(struct aq_nic_s *self)
{
int err = 0;
err = self->aq_hw_ops->hw_soft_reset(self->aq_hw);
if (err)
goto exit;
err = self->aq_hw_ops->hw_prepare(self->aq_hw, &self->aq_fw_ops);
exit:
return err;
}
int aq_nic_ndev_register(struct aq_nic_s *self)
{
int err = 0;
......@@ -266,7 +280,7 @@ int aq_nic_ndev_register(struct aq_nic_s *self)
goto err_exit;
}
err = hw_atl_utils_initfw(self->aq_hw, &self->aq_fw_ops);
err = aq_nic_hw_prepare(self);
if (err)
goto err_exit;
......@@ -364,7 +378,8 @@ int aq_nic_init(struct aq_nic_s *self)
if (err < 0)
goto err_exit;
if (self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_TP) {
if (ATL_HW_IS_CHIP_FEATURE(self->aq_hw, ATLANTIC) &&
self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_TP) {
self->aq_hw->phy_id = HW_ATL_PHY_ID_MAX;
err = aq_phy_init(self->aq_hw);
}
......@@ -764,6 +779,9 @@ int aq_nic_get_regs(struct aq_nic_s *self, struct ethtool_regs *regs, void *p)
u32 *regs_buff = p;
int err = 0;
if (unlikely(!self->aq_hw_ops->hw_get_regs))
return -EOPNOTSUPP;
regs->version = 1;
err = self->aq_hw_ops->hw_get_regs(self->aq_hw,
......@@ -778,6 +796,9 @@ int aq_nic_get_regs(struct aq_nic_s *self, struct ethtool_regs *regs, void *p)
int aq_nic_get_regs_count(struct aq_nic_s *self)
{
if (unlikely(!self->aq_hw_ops->hw_get_regs))
return 0;
return self->aq_nic_cfg.aq_hw_caps->mac_regs_count;
}
......@@ -885,6 +906,10 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self,
ethtool_link_ksettings_add_link_mode(cmd, supported,
100baseT_Full);
if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_10M)
ethtool_link_ksettings_add_link_mode(cmd, supported,
10baseT_Full);
if (self->aq_nic_cfg.aq_hw_caps->flow_control) {
ethtool_link_ksettings_add_link_mode(cmd, supported,
Pause);
......@@ -924,6 +949,10 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self,
ethtool_link_ksettings_add_link_mode(cmd, advertising,
100baseT_Full);
if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_10M)
ethtool_link_ksettings_add_link_mode(cmd, advertising,
10baseT_Full);
if (self->aq_nic_cfg.fc.cur & AQ_NIC_FC_RX)
ethtool_link_ksettings_add_link_mode(cmd, advertising,
Pause);
......@@ -954,6 +983,10 @@ int aq_nic_set_link_ksettings(struct aq_nic_s *self,
speed = cmd->base.speed;
switch (speed) {
case SPEED_10:
rate = AQ_NIC_RATE_10M;
break;
case SPEED_100:
rate = AQ_NIC_RATE_100M;
break;
......@@ -1006,11 +1039,7 @@ struct aq_nic_cfg_s *aq_nic_get_cfg(struct aq_nic_s *self)
u32 aq_nic_get_fw_version(struct aq_nic_s *self)
{
u32 fw_version = 0U;
self->aq_hw_ops->hw_get_fw_version(self->aq_hw, &fw_version);
return fw_version;
return self->aq_hw_ops->hw_get_fw_version(self->aq_hw);
}
int aq_nic_set_loopback(struct aq_nic_s *self)
......
......@@ -16,6 +16,7 @@
#include "aq_pci_func.h"
#include "hw_atl/hw_atl_a0.h"
#include "hw_atl/hw_atl_b0.h"
#include "hw_atl2/hw_atl2.h"
#include "aq_filters.h"
#include "aq_drvinfo.h"
#include "aq_macsec.h"
......@@ -41,6 +42,13 @@ 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_AQC113DEV), },
{ PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113CS), },
{ PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC114CS), },
{ PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113), },
{ PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113C), },
{ PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC115C), },
{}
};
......@@ -70,6 +78,13 @@ 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_AQC113DEV, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, },
{ AQ_DEVICE_ID_AQC113, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, },
{ AQ_DEVICE_ID_AQC113CS, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, },
{ AQ_DEVICE_ID_AQC114CS, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, },
{ AQ_DEVICE_ID_AQC113C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, },
{ AQ_DEVICE_ID_AQC115C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, },
};
MODULE_DEVICE_TABLE(pci, aq_pci_tbl);
......@@ -104,10 +119,8 @@ int aq_pci_func_init(struct pci_dev *pdev)
int err;
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
if (!err) {
if (!err)
err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
}
if (err) {
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (!err)
......@@ -237,6 +250,15 @@ static int aq_pci_probe(struct pci_dev *pdev,
goto err_ioremap;
}
self->aq_hw->aq_nic_cfg = aq_nic_get_cfg(self);
if (self->aq_hw->aq_nic_cfg->aq_hw_caps->priv_data_len) {
int len = self->aq_hw->aq_nic_cfg->aq_hw_caps->priv_data_len;
self->aq_hw->priv = kzalloc(len, GFP_KERNEL);
if (!self->aq_hw->priv) {
err = -ENOMEM;
goto err_free_aq_hw;
}
}
for (bar = 0; bar < 4; ++bar) {
if (IORESOURCE_MEM & pci_resource_flags(pdev, bar)) {
......@@ -245,19 +267,19 @@ static int aq_pci_probe(struct pci_dev *pdev,
mmio_pa = pci_resource_start(pdev, bar);
if (mmio_pa == 0U) {
err = -EIO;
goto err_free_aq_hw;
goto err_free_aq_hw_priv;
}
reg_sz = pci_resource_len(pdev, bar);
if ((reg_sz <= 24 /*ATL_REGS_SIZE*/)) {
err = -EIO;
goto err_free_aq_hw;
goto err_free_aq_hw_priv;
}
self->aq_hw->mmio = ioremap(mmio_pa, reg_sz);
if (!self->aq_hw->mmio) {
err = -EIO;
goto err_free_aq_hw;
goto err_free_aq_hw_priv;
}
break;
}
......@@ -265,7 +287,7 @@ static int aq_pci_probe(struct pci_dev *pdev,
if (bar == 4) {
err = -EIO;
goto err_free_aq_hw;
goto err_free_aq_hw_priv;
}
numvecs = min((u8)AQ_CFG_VECS_DEF,
......@@ -305,6 +327,8 @@ static int aq_pci_probe(struct pci_dev *pdev,
aq_pci_free_irq_vectors(self);
err_hwinit:
iounmap(self->aq_hw->mmio);
err_free_aq_hw_priv:
kfree(self->aq_hw->priv);
err_free_aq_hw:
kfree(self->aq_hw);
err_ioremap:
......@@ -332,6 +356,7 @@ static void aq_pci_remove(struct pci_dev *pdev)
aq_nic_free_vectors(self);
aq_pci_free_irq_vectors(self);
iounmap(self->aq_hw->mmio);
kfree(self->aq_hw->priv);
kfree(self->aq_hw);
pci_release_regions(pdev);
free_netdev(self->ndev);
......
......@@ -267,7 +267,7 @@ static int hw_atl_a0_hw_init_tx_path(struct aq_hw_s *self)
hw_atl_tdm_tx_desc_wr_wb_irq_en_set(self, 1U);
/* misc */
aq_hw_write_reg(self, 0x00007040U, IS_CHIP_FEATURE(TPO2) ?
aq_hw_write_reg(self, 0x00007040U, ATL_HW_IS_CHIP_FEATURE(self, TPO2) ?
0x00010000U : 0x00000000U);
hw_atl_tdm_tx_dca_en_set(self, 0U);
hw_atl_tdm_tx_dca_mode_set(self, 0U);
......@@ -886,6 +886,8 @@ static int hw_atl_a0_hw_ring_rx_stop(struct aq_hw_s *self,
}
const struct aq_hw_ops hw_atl_ops_a0 = {
.hw_soft_reset = hw_atl_utils_soft_reset,
.hw_prepare = hw_atl_utils_initfw,
.hw_set_mac_address = hw_atl_a0_hw_mac_addr_set,
.hw_init = hw_atl_a0_hw_init,
.hw_reset = hw_atl_a0_hw_reset,
......
......@@ -187,8 +187,8 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self)
return aq_hw_err_from_flags(self);
}
static int hw_atl_b0_hw_rss_hash_set(struct aq_hw_s *self,
struct aq_rss_parameters *rss_params)
int hw_atl_b0_hw_rss_hash_set(struct aq_hw_s *self,
struct aq_rss_parameters *rss_params)
{
struct aq_nic_cfg_s *cfg = self->aq_nic_cfg;
unsigned int addr = 0U;
......@@ -215,8 +215,8 @@ static int hw_atl_b0_hw_rss_hash_set(struct aq_hw_s *self,
return err;
}
static int hw_atl_b0_hw_rss_set(struct aq_hw_s *self,
struct aq_rss_parameters *rss_params)
int hw_atl_b0_hw_rss_set(struct aq_hw_s *self,
struct aq_rss_parameters *rss_params)
{
u32 num_rss_queues = max(1U, self->aq_nic_cfg->num_rss_queues);
u8 *indirection_table = rss_params->indirection_table;
......@@ -251,9 +251,10 @@ static int hw_atl_b0_hw_rss_set(struct aq_hw_s *self,
return err;
}
static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self,
struct aq_nic_cfg_s *aq_nic_cfg)
int hw_atl_b0_hw_offload_set(struct aq_hw_s *self,
struct aq_nic_cfg_s *aq_nic_cfg)
{
u64 rxcsum = !!(aq_nic_cfg->features & NETIF_F_RXCSUM);
unsigned int i;
/* TX checksums offloads*/
......@@ -261,10 +262,8 @@ static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self,
hw_atl_tpo_tcp_udp_crc_offload_en_set(self, 1);
/* RX checksums offloads*/
hw_atl_rpo_ipv4header_crc_offload_en_set(self, !!(aq_nic_cfg->features &
NETIF_F_RXCSUM));
hw_atl_rpo_tcp_udp_crc_offload_en_set(self, !!(aq_nic_cfg->features &
NETIF_F_RXCSUM));
hw_atl_rpo_ipv4header_crc_offload_en_set(self, rxcsum);
hw_atl_rpo_tcp_udp_crc_offload_en_set(self, rxcsum);
/* LSO offloads*/
hw_atl_tdm_large_send_offload_en_set(self, 0xFFFFFFFFU);
......@@ -272,7 +271,7 @@ static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self,
/* Outer VLAN tag offload */
hw_atl_rpo_outer_vlan_tag_mode_set(self, 1U);
/* LRO offloads */
/* LRO offloads */
{
unsigned int val = (8U < HW_ATL_B0_LRO_RXD_MAX) ? 0x3U :
((4U < HW_ATL_B0_LRO_RXD_MAX) ? 0x2U :
......@@ -314,7 +313,7 @@ static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self,
static int hw_atl_b0_hw_init_tx_path(struct aq_hw_s *self)
{
/* Tx TC/Queue number config */
hw_atl_rpb_tps_tx_tc_mode_set(self, 1U);
hw_atl_tpb_tps_tx_tc_mode_set(self, 1U);
hw_atl_thm_lso_tcp_flag_of_first_pkt_set(self, 0x0FF6U);
hw_atl_thm_lso_tcp_flag_of_middle_pkt_set(self, 0x0FF6U);
......@@ -324,7 +323,7 @@ static int hw_atl_b0_hw_init_tx_path(struct aq_hw_s *self)
hw_atl_tdm_tx_desc_wr_wb_irq_en_set(self, 1U);
/* misc */
aq_hw_write_reg(self, 0x00007040U, IS_CHIP_FEATURE(TPO2) ?
aq_hw_write_reg(self, 0x00007040U, ATL_HW_IS_CHIP_FEATURE(self, TPO2) ?
0x00010000U : 0x00000000U);
hw_atl_tdm_tx_dca_en_set(self, 0U);
hw_atl_tdm_tx_dca_mode_set(self, 0U);
......@@ -372,8 +371,8 @@ static int hw_atl_b0_hw_init_rx_path(struct aq_hw_s *self)
hw_atl_rdm_rx_desc_wr_wb_irq_en_set(self, 1U);
/* misc */
aq_hw_write_reg(self, 0x00005040U,
IS_CHIP_FEATURE(RPF2) ? 0x000F0000U : 0x00000000U);
aq_hw_write_reg(self, 0x00005040U, ATL_HW_IS_CHIP_FEATURE(self, RPF2) ?
0x000F0000U : 0x00000000U);
hw_atl_rpfl2broadcast_flr_act_set(self, 1U);
hw_atl_rpfl2broadcast_count_threshold_set(self, 0xFFFFU & (~0U / 256U));
......@@ -384,7 +383,7 @@ static int hw_atl_b0_hw_init_rx_path(struct aq_hw_s *self)
return aq_hw_err_from_flags(self);
}
static int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr)
int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr)
{
unsigned int h = 0U;
unsigned int l = 0U;
......@@ -479,23 +478,21 @@ static int hw_atl_b0_hw_init(struct aq_hw_s *self, u8 *mac_addr)
return err;
}
static int hw_atl_b0_hw_ring_tx_start(struct aq_hw_s *self,
struct aq_ring_s *ring)
int hw_atl_b0_hw_ring_tx_start(struct aq_hw_s *self, struct aq_ring_s *ring)
{
hw_atl_tdm_tx_desc_en_set(self, 1, ring->idx);
return aq_hw_err_from_flags(self);
}
static int hw_atl_b0_hw_ring_rx_start(struct aq_hw_s *self,
struct aq_ring_s *ring)
int hw_atl_b0_hw_ring_rx_start(struct aq_hw_s *self, struct aq_ring_s *ring)
{
hw_atl_rdm_rx_desc_en_set(self, 1, ring->idx);
return aq_hw_err_from_flags(self);
}
static int hw_atl_b0_hw_start(struct aq_hw_s *self)
int hw_atl_b0_hw_start(struct aq_hw_s *self)
{
hw_atl_tpb_tx_buff_en_set(self, 1);
hw_atl_rpb_rx_buff_en_set(self, 1);
......@@ -511,9 +508,8 @@ static int hw_atl_b0_hw_tx_ring_tail_update(struct aq_hw_s *self,
return 0;
}
static int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self,
struct aq_ring_s *ring,
unsigned int frags)
int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self, struct aq_ring_s *ring,
unsigned int frags)
{
struct aq_ring_buff_s *buff = NULL;
struct hw_atl_txd_s *txd = NULL;
......@@ -600,9 +596,8 @@ static int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self,
return aq_hw_err_from_flags(self);
}
static int hw_atl_b0_hw_ring_rx_init(struct aq_hw_s *self,
struct aq_ring_s *aq_ring,
struct aq_ring_param_s *aq_ring_param)
int hw_atl_b0_hw_ring_rx_init(struct aq_hw_s *self, struct aq_ring_s *aq_ring,
struct aq_ring_param_s *aq_ring_param)
{
u32 dma_desc_addr_msw = (u32)(((u64)aq_ring->dx_ring_pa) >> 32);
u32 vlan_rx_stripping = self->aq_nic_cfg->is_vlan_rx_strip;
......@@ -643,9 +638,8 @@ static int hw_atl_b0_hw_ring_rx_init(struct aq_hw_s *self,
return aq_hw_err_from_flags(self);
}
static int hw_atl_b0_hw_ring_tx_init(struct aq_hw_s *self,
struct aq_ring_s *aq_ring,
struct aq_ring_param_s *aq_ring_param)
int hw_atl_b0_hw_ring_tx_init(struct aq_hw_s *self, struct aq_ring_s *aq_ring,
struct aq_ring_param_s *aq_ring_param)
{
u32 dma_desc_msw_addr = (u32)(((u64)aq_ring->dx_ring_pa) >> 32);
u32 dma_desc_lsw_addr = (u32)aq_ring->dx_ring_pa;
......@@ -673,9 +667,8 @@ static int hw_atl_b0_hw_ring_tx_init(struct aq_hw_s *self,
return aq_hw_err_from_flags(self);
}
static int hw_atl_b0_hw_ring_rx_fill(struct aq_hw_s *self,
struct aq_ring_s *ring,
unsigned int sw_tail_old)
int hw_atl_b0_hw_ring_rx_fill(struct aq_hw_s *self, struct aq_ring_s *ring,
unsigned int sw_tail_old)
{
for (; sw_tail_old != ring->sw_tail;
sw_tail_old = aq_ring_next_dx(ring, sw_tail_old)) {
......@@ -734,8 +727,8 @@ static int hw_atl_b0_hw_ring_hwts_rx_receive(struct aq_hw_s *self,
return aq_hw_err_from_flags(self);
}
static int hw_atl_b0_hw_ring_tx_head_update(struct aq_hw_s *self,
struct aq_ring_s *ring)
int hw_atl_b0_hw_ring_tx_head_update(struct aq_hw_s *self,
struct aq_ring_s *ring)
{
unsigned int hw_head_;
int err = 0;
......@@ -753,8 +746,7 @@ static int hw_atl_b0_hw_ring_tx_head_update(struct aq_hw_s *self,
return err;
}
static int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self,
struct aq_ring_s *ring)
int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self, struct aq_ring_s *ring)
{
for (; ring->hw_head != ring->sw_tail;
ring->hw_head = aq_ring_next_dx(ring, ring->hw_head)) {
......@@ -854,14 +846,14 @@ static int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self,
return aq_hw_err_from_flags(self);
}
static int hw_atl_b0_hw_irq_enable(struct aq_hw_s *self, u64 mask)
int hw_atl_b0_hw_irq_enable(struct aq_hw_s *self, u64 mask)
{
hw_atl_itr_irq_msk_setlsw_set(self, LODWORD(mask));
return aq_hw_err_from_flags(self);
}
static int hw_atl_b0_hw_irq_disable(struct aq_hw_s *self, u64 mask)
int hw_atl_b0_hw_irq_disable(struct aq_hw_s *self, u64 mask)
{
hw_atl_itr_irq_msk_clearlsw_set(self, LODWORD(mask));
hw_atl_itr_irq_status_clearlsw_set(self, LODWORD(mask));
......@@ -871,7 +863,7 @@ static int hw_atl_b0_hw_irq_disable(struct aq_hw_s *self, u64 mask)
return aq_hw_err_from_flags(self);
}
static int hw_atl_b0_hw_irq_read(struct aq_hw_s *self, u64 *mask)
int hw_atl_b0_hw_irq_read(struct aq_hw_s *self, u64 *mask)
{
*mask = hw_atl_itr_irq_statuslsw_get(self);
......@@ -880,8 +872,8 @@ static int hw_atl_b0_hw_irq_read(struct aq_hw_s *self, u64 *mask)
#define IS_FILTER_ENABLED(_F_) ((packet_filter & (_F_)) ? 1U : 0U)
static int hw_atl_b0_hw_packet_filter_set(struct aq_hw_s *self,
unsigned int packet_filter)
int hw_atl_b0_hw_packet_filter_set(struct aq_hw_s *self,
unsigned int packet_filter)
{
struct aq_nic_cfg_s *cfg = self->aq_nic_cfg;
unsigned int i = 0U;
......@@ -1071,16 +1063,14 @@ static int hw_atl_b0_hw_stop(struct aq_hw_s *self)
return err;
}
static int hw_atl_b0_hw_ring_tx_stop(struct aq_hw_s *self,
struct aq_ring_s *ring)
int hw_atl_b0_hw_ring_tx_stop(struct aq_hw_s *self, struct aq_ring_s *ring)
{
hw_atl_tdm_tx_desc_en_set(self, 0U, ring->idx);
return aq_hw_err_from_flags(self);
}
static int hw_atl_b0_hw_ring_rx_stop(struct aq_hw_s *self,
struct aq_ring_s *ring)
int hw_atl_b0_hw_ring_rx_stop(struct aq_hw_s *self, struct aq_ring_s *ring)
{
hw_atl_rdm_rx_desc_en_set(self, 0U, ring->idx);
......@@ -1089,7 +1079,7 @@ static int hw_atl_b0_hw_ring_rx_stop(struct aq_hw_s *self,
static int hw_atl_b0_tx_tc_mode_get(struct aq_hw_s *self, u32 *tc_mode)
{
*tc_mode = hw_atl_rpb_tps_tx_tc_mode_get(self);
*tc_mode = hw_atl_tpb_tps_tx_tc_mode_get(self);
return aq_hw_err_from_flags(self);
}
......@@ -1478,6 +1468,8 @@ static int hw_atl_b0_set_loopback(struct aq_hw_s *self, u32 mode, bool enable)
}
const struct aq_hw_ops hw_atl_ops_b0 = {
.hw_soft_reset = hw_atl_utils_soft_reset,
.hw_prepare = hw_atl_utils_initfw,
.hw_set_mac_address = hw_atl_b0_hw_mac_addr_set,
.hw_init = hw_atl_b0_hw_init,
.hw_reset = hw_atl_b0_hw_reset,
......
......@@ -33,4 +33,41 @@ extern const struct aq_hw_ops hw_atl_ops_b0;
#define hw_atl_ops_b1 hw_atl_ops_b0
int hw_atl_b0_hw_rss_hash_set(struct aq_hw_s *self,
struct aq_rss_parameters *rss_params);
int hw_atl_b0_hw_rss_set(struct aq_hw_s *self,
struct aq_rss_parameters *rss_params);
int hw_atl_b0_hw_offload_set(struct aq_hw_s *self,
struct aq_nic_cfg_s *aq_nic_cfg);
int hw_atl_b0_hw_ring_tx_start(struct aq_hw_s *self, struct aq_ring_s *ring);
int hw_atl_b0_hw_ring_rx_start(struct aq_hw_s *self, struct aq_ring_s *ring);
int hw_atl_b0_hw_ring_rx_init(struct aq_hw_s *self, struct aq_ring_s *aq_ring,
struct aq_ring_param_s *aq_ring_param);
int hw_atl_b0_hw_ring_rx_fill(struct aq_hw_s *self, struct aq_ring_s *ring,
unsigned int sw_tail_old);
int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self, struct aq_ring_s *ring);
int hw_atl_b0_hw_ring_tx_init(struct aq_hw_s *self, struct aq_ring_s *aq_ring,
struct aq_ring_param_s *aq_ring_param);
int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self, struct aq_ring_s *ring,
unsigned int frags);
int hw_atl_b0_hw_ring_tx_head_update(struct aq_hw_s *self,
struct aq_ring_s *ring);
int hw_atl_b0_hw_ring_tx_stop(struct aq_hw_s *self, struct aq_ring_s *ring);
int hw_atl_b0_hw_ring_rx_stop(struct aq_hw_s *self, struct aq_ring_s *ring);
int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr);
int hw_atl_b0_hw_start(struct aq_hw_s *self);
int hw_atl_b0_hw_irq_enable(struct aq_hw_s *self, u64 mask);
int hw_atl_b0_hw_irq_disable(struct aq_hw_s *self, u64 mask);
int hw_atl_b0_hw_irq_read(struct aq_hw_s *self, u64 *mask);
int hw_atl_b0_hw_packet_filter_set(struct aq_hw_s *self,
unsigned int packet_filter);
#endif /* HW_ATL_B0_H */
......@@ -693,6 +693,13 @@ void hw_atl_rpfl2multicast_flr_en_set(struct aq_hw_s *aq_hw,
HW_ATL_RPFL2MC_ENF_SHIFT, l2multicast_flr_en);
}
u32 hw_atl_rpfl2promiscuous_mode_en_get(struct aq_hw_s *aq_hw)
{
return aq_hw_read_reg_bit(aq_hw, HW_ATL_RPFL2PROMIS_MODE_ADR,
HW_ATL_RPFL2PROMIS_MODE_MSK,
HW_ATL_RPFL2PROMIS_MODE_SHIFT);
}
void hw_atl_rpfl2promiscuous_mode_en_set(struct aq_hw_s *aq_hw,
u32 l2promiscuous_mode_en)
{
......@@ -867,6 +874,13 @@ void hw_atl_rpf_vlan_prom_mode_en_set(struct aq_hw_s *aq_hw,
vlan_prom_mode_en);
}
u32 hw_atl_rpf_vlan_prom_mode_en_get(struct aq_hw_s *aq_hw)
{
return aq_hw_read_reg_bit(aq_hw, HW_ATL_RPF_VL_PROMIS_MODE_ADR,
HW_ATL_RPF_VL_PROMIS_MODE_MSK,
HW_ATL_RPF_VL_PROMIS_MODE_SHIFT);
}
void hw_atl_rpf_vlan_accept_untagged_packets_set(struct aq_hw_s *aq_hw,
u32 vlan_acc_untagged_packets)
{
......@@ -1304,14 +1318,14 @@ void hw_atl_tpb_tx_buff_en_set(struct aq_hw_s *aq_hw, u32 tx_buff_en)
HW_ATL_TPB_TX_BUF_EN_SHIFT, tx_buff_en);
}
u32 hw_atl_rpb_tps_tx_tc_mode_get(struct aq_hw_s *aq_hw)
u32 hw_atl_tpb_tps_tx_tc_mode_get(struct aq_hw_s *aq_hw)
{
return aq_hw_read_reg_bit(aq_hw, HW_ATL_TPB_TX_TC_MODE_ADDR,
HW_ATL_TPB_TX_TC_MODE_MSK,
HW_ATL_TPB_TX_TC_MODE_SHIFT);
}
void hw_atl_rpb_tps_tx_tc_mode_set(struct aq_hw_s *aq_hw,
void hw_atl_tpb_tps_tx_tc_mode_set(struct aq_hw_s *aq_hw,
u32 tx_traf_class_mode)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL_TPB_TX_TC_MODE_ADDR,
......
......@@ -349,6 +349,9 @@ void hw_atl_rpfl2multicast_flr_en_set(struct aq_hw_s *aq_hw,
u32 l2multicast_flr_en,
u32 filter);
/* get l2 promiscuous mode enable */
u32 hw_atl_rpfl2promiscuous_mode_en_get(struct aq_hw_s *aq_hw);
/* set l2 promiscuous mode enable */
void hw_atl_rpfl2promiscuous_mode_en_set(struct aq_hw_s *aq_hw,
u32 l2promiscuous_mode_en);
......@@ -420,6 +423,9 @@ void hw_atl_rpf_vlan_outer_etht_set(struct aq_hw_s *aq_hw, u32 vlan_outer_etht);
void hw_atl_rpf_vlan_prom_mode_en_set(struct aq_hw_s *aq_hw,
u32 vlan_prom_mode_en);
/* Get VLAN promiscuous mode enable */
u32 hw_atl_rpf_vlan_prom_mode_en_get(struct aq_hw_s *aq_hw);
/* Set VLAN untagged action */
void hw_atl_rpf_vlan_untagged_act_set(struct aq_hw_s *aq_hw,
u32 vlan_untagged_act);
......@@ -610,11 +616,11 @@ void hw_atl_thm_lso_tcp_flag_of_middle_pkt_set(struct aq_hw_s *aq_hw,
/* tpb */
/* set TX Traffic Class Mode */
void hw_atl_rpb_tps_tx_tc_mode_set(struct aq_hw_s *aq_hw,
void hw_atl_tpb_tps_tx_tc_mode_set(struct aq_hw_s *aq_hw,
u32 tx_traf_class_mode);
/* get TX Traffic Class Mode */
u32 hw_atl_rpb_tps_tx_tc_mode_get(struct aq_hw_s *aq_hw);
u32 hw_atl_tpb_tps_tx_tc_mode_get(struct aq_hw_s *aq_hw);
/* set tx buffer enable */
void hw_atl_tpb_tx_buff_en_set(struct aq_hw_s *aq_hw, u32 tx_buff_en);
......
......@@ -53,7 +53,6 @@ enum mcp_area {
MCP_AREA_SETTINGS = 0x20000000,
};
static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
enum hal_atl_utils_fw_state_e state);
static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self);
......@@ -67,14 +66,10 @@ int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops)
{
int err = 0;
err = hw_atl_utils_soft_reset(self);
if (err)
return err;
hw_atl_utils_hw_chip_features_init(self,
&self->chip_features);
hw_atl_utils_get_fw_version(self, &self->fw_ver_actual);
self->fw_ver_actual = hw_atl_utils_get_fw_version(self);
if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X,
self->fw_ver_actual) == 0) {
......@@ -313,7 +308,7 @@ int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
for (++cnt; --cnt && !err;) {
aq_hw_write_reg(self, HW_ATL_MIF_CMD, 0x00008000U);
if (IS_CHIP_FEATURE(REVISION_B1))
if (ATL_HW_IS_CHIP_FEATURE(self, REVISION_B1))
err = readx_poll_timeout_atomic(hw_atl_utils_mif_addr_get,
self, val, val != a,
1U, 1000U);
......@@ -409,7 +404,7 @@ static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 addr, u32 *p,
if (err < 0)
goto err_exit;
if (IS_CHIP_FEATURE(REVISION_B1))
if (ATL_HW_IS_CHIP_FEATURE(self, REVISION_B1))
err = hw_atl_utils_write_b1_mbox(self, addr, p, cnt, area);
else
err = hw_atl_utils_write_b0_mbox(self, addr, p, cnt);
......@@ -438,7 +433,7 @@ int hw_atl_write_fwsettings_dwords(struct aq_hw_s *self, u32 offset, u32 *p,
p, cnt, MCP_AREA_SETTINGS);
}
static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
{
const u32 dw_major_mask = 0xff000000U;
const u32 dw_minor_mask = 0x00ffffffU;
......@@ -501,7 +496,7 @@ int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size)
struct aq_hw_atl_utils_fw_rpc_tid_s sw;
int err = 0;
if (!IS_CHIP_FEATURE(MIPS)) {
if (!ATL_HW_IS_CHIP_FEATURE(self, MIPS)) {
err = -1;
goto err_exit;
}
......@@ -607,7 +602,7 @@ void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
if (err < 0)
goto err_exit;
if (IS_CHIP_FEATURE(REVISION_A0)) {
if (ATL_HW_IS_CHIP_FEATURE(self, REVISION_A0)) {
unsigned int mtu = self->aq_nic_cfg ?
self->aq_nic_cfg->mtu : 1514U;
pmbox->stats.ubrc = pmbox->stats.uprc * mtu;
......@@ -806,22 +801,24 @@ void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p)
u32 mif_rev = val & 0xFFU;
u32 chip_features = 0U;
chip_features |= ATL_HW_CHIP_ATLANTIC;
if ((0xFU & mif_rev) == 1U) {
chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 |
HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
HAL_ATLANTIC_UTILS_CHIP_MIPS;
chip_features |= ATL_HW_CHIP_REVISION_A0 |
ATL_HW_CHIP_MPI_AQ |
ATL_HW_CHIP_MIPS;
} else if ((0xFU & mif_rev) == 2U) {
chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 |
HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
HAL_ATLANTIC_UTILS_CHIP_MIPS |
HAL_ATLANTIC_UTILS_CHIP_TPO2 |
HAL_ATLANTIC_UTILS_CHIP_RPF2;
chip_features |= ATL_HW_CHIP_REVISION_B0 |
ATL_HW_CHIP_MPI_AQ |
ATL_HW_CHIP_MIPS |
ATL_HW_CHIP_TPO2 |
ATL_HW_CHIP_RPF2;
} else if ((0xFU & mif_rev) == 0xAU) {
chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B1 |
HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
HAL_ATLANTIC_UTILS_CHIP_MIPS |
HAL_ATLANTIC_UTILS_CHIP_TPO2 |
HAL_ATLANTIC_UTILS_CHIP_RPF2;
chip_features |= ATL_HW_CHIP_REVISION_B1 |
ATL_HW_CHIP_MPI_AQ |
ATL_HW_CHIP_MIPS |
ATL_HW_CHIP_TPO2 |
ATL_HW_CHIP_RPF2;
}
*p = chip_features;
......@@ -919,11 +916,9 @@ int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,
return 0;
}
int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version)
u32 hw_atl_utils_get_fw_version(struct aq_hw_s *self)
{
*fw_version = aq_hw_read_reg(self, 0x18U);
return 0;
return aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
}
static int aq_fw1x_set_wake_magic(struct aq_hw_s *self, bool wol_enabled,
......
......@@ -360,6 +360,8 @@ struct aq_rx_filter_vlan {
u8 queue;
};
#define HW_ATL_VLAN_MAX_FILTERS 16U
struct aq_rx_filter_l2 {
s8 queue;
u8 location;
......@@ -406,17 +408,6 @@ enum hw_atl_rx_ctrl_registers_l3l4 {
#define HW_ATL_GET_REG_LOCATION_FL3L4(location) \
((location) - AQ_RX_FIRST_LOC_FL3L4)
#define HAL_ATLANTIC_UTILS_CHIP_MIPS 0x00000001U
#define HAL_ATLANTIC_UTILS_CHIP_TPO2 0x00000002U
#define HAL_ATLANTIC_UTILS_CHIP_RPF2 0x00000004U
#define HAL_ATLANTIC_UTILS_CHIP_MPI_AQ 0x00000010U
#define HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 0x01000000U
#define HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 0x02000000U
#define HAL_ATLANTIC_UTILS_CHIP_REVISION_B1 0x04000000U
#define IS_CHIP_FEATURE(_F_) (HAL_ATLANTIC_UTILS_CHIP_##_F_ & \
self->chip_features)
enum hal_atl_utils_fw_state_e {
MPI_DEINIT = 0,
MPI_RESET = 1,
......@@ -622,7 +613,7 @@ int hw_atl_utils_hw_set_power(struct aq_hw_s *self,
int hw_atl_utils_hw_deinit(struct aq_hw_s *self);
int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version);
u32 hw_atl_utils_get_fw_version(struct aq_hw_s *self);
int hw_atl_utils_update_stats(struct aq_hw_s *self);
......@@ -643,6 +634,8 @@ int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size);
int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
struct hw_atl_utils_fw_rpc **rpc);
int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
extern const struct aq_fw_ops aq_fw_1x_ops;
extern const struct aq_fw_ops aq_fw_2x_ops;
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-only */
/* Atlantic Network Driver
* Copyright (C) 2020 Marvell International Ltd.
*/
#ifndef HW_ATL2_H
#define HW_ATL2_H
#include "aq_common.h"
extern const struct aq_hw_caps_s hw_atl2_caps_aqc113;
extern const struct aq_hw_ops hw_atl2_ops;
#endif /* HW_ATL2_H */
/* SPDX-License-Identifier: GPL-2.0-only */
/* Atlantic Network Driver
* Copyright (C) 2020 Marvell International Ltd.
*/
#ifndef HW_ATL2_INTERNAL_H
#define HW_ATL2_INTERNAL_H
#include "hw_atl2_utils.h"
#define HW_ATL2_MTU_JUMBO 16352U
#define HW_ATL2_MTU 1514U
#define HW_ATL2_TX_RINGS 4U
#define HW_ATL2_RX_RINGS 4U
#define HW_ATL2_RINGS_MAX 32U
#define HW_ATL2_TXD_SIZE (16U)
#define HW_ATL2_RXD_SIZE (16U)
#define HW_ATL2_MAC_UC 0U
#define HW_ATL2_MAC_MIN 1U
#define HW_ATL2_MAC_MAX 38U
/* interrupts */
#define HW_ATL2_ERR_INT 8U
#define HW_ATL2_INT_MASK (0xFFFFFFFFU)
#define HW_ATL2_TXBUF_MAX 128U
#define HW_ATL2_RXBUF_MAX 192U
#define HW_ATL2_RSS_REDIRECTION_MAX 64U
#define HW_ATL2_TC_MAX 1U
#define HW_ATL2_RSS_MAX 8U
#define HW_ATL2_INTR_MODER_MAX 0x1FF
#define HW_ATL2_INTR_MODER_MIN 0xFF
#define HW_ATL2_MIN_RXD \
(ALIGN(AQ_CFG_SKB_FRAGS_MAX + 1U, AQ_HW_RXD_MULTIPLE))
#define HW_ATL2_MIN_TXD \
(ALIGN(AQ_CFG_SKB_FRAGS_MAX + 1U, AQ_HW_TXD_MULTIPLE))
#define HW_ATL2_MAX_RXD 8184U
#define HW_ATL2_MAX_TXD 8184U
#define HW_ATL2_FW_SM_ACT_RSLVR 0x3U
#define HW_ATL2_RPF_TAG_UC_OFFSET 0x0
#define HW_ATL2_RPF_TAG_ALLMC_OFFSET 0x6
#define HW_ATL2_RPF_TAG_ET_OFFSET 0x7
#define HW_ATL2_RPF_TAG_VLAN_OFFSET 0xA
#define HW_ATL2_RPF_TAG_UNTAG_OFFSET 0xE
#define HW_ATL2_RPF_TAG_L3_V4_OFFSET 0xF
#define HW_ATL2_RPF_TAG_L3_V6_OFFSET 0x12
#define HW_ATL2_RPF_TAG_L4_OFFSET 0x15
#define HW_ATL2_RPF_TAG_L4_FLEX_OFFSET 0x18
#define HW_ATL2_RPF_TAG_FLEX_OFFSET 0x1B
#define HW_ATL2_RPF_TAG_PCP_OFFSET 0x1D
#define HW_ATL2_RPF_TAG_UC_MASK (0x0000003F << HW_ATL2_RPF_TAG_UC_OFFSET)
#define HW_ATL2_RPF_TAG_ALLMC_MASK (0x00000001 << HW_ATL2_RPF_TAG_ALLMC_OFFSET)
#define HW_ATL2_RPF_TAG_UNTAG_MASK (0x00000001 << HW_ATL2_RPF_TAG_UNTAG_OFFSET)
#define HW_ATL2_RPF_TAG_VLAN_MASK (0x0000000F << HW_ATL2_RPF_TAG_VLAN_OFFSET)
#define HW_ATL2_RPF_TAG_ET_MASK (0x00000007 << HW_ATL2_RPF_TAG_ET_OFFSET)
#define HW_ATL2_RPF_TAG_L3_V4_MASK (0x00000007 << HW_ATL2_RPF_TAG_L3_V4_OFFSET)
#define HW_ATL2_RPF_TAG_L3_V6_MASK (0x00000007 << HW_ATL2_RPF_TAG_L3_V6_OFFSET)
#define HW_ATL2_RPF_TAG_L4_MASK (0x00000007 << HW_ATL2_RPF_TAG_L4_OFFSET)
#define HW_ATL2_RPF_TAG_PCP_MASK (0x00000007 << HW_ATL2_RPF_TAG_PCP_OFFSET)
#define HW_ATL2_RPF_TAG_BASE_UC BIT(HW_ATL2_RPF_TAG_UC_OFFSET)
#define HW_ATL2_RPF_TAG_BASE_ALLMC BIT(HW_ATL2_RPF_TAG_ALLMC_OFFSET)
#define HW_ATL2_RPF_TAG_BASE_UNTAG BIT(HW_ATL2_RPF_TAG_UNTAG_OFFSET)
#define HW_ATL2_RPF_TAG_BASE_VLAN BIT(HW_ATL2_RPF_TAG_VLAN_OFFSET)
enum HW_ATL2_RPF_ART_INDEX {
HW_ATL2_RPF_L2_PROMISC_OFF_INDEX,
HW_ATL2_RPF_VLAN_PROMISC_OFF_INDEX,
HW_ATL2_RPF_L3L4_USER_INDEX = 8,
HW_ATL2_RPF_ET_PCP_USER_INDEX = HW_ATL2_RPF_L3L4_USER_INDEX + 16,
HW_ATL2_RPF_VLAN_USER_INDEX = HW_ATL2_RPF_ET_PCP_USER_INDEX + 16,
HW_ATL2_RPF_PCP_TO_TC_INDEX = HW_ATL2_RPF_VLAN_USER_INDEX +
HW_ATL_VLAN_MAX_FILTERS,
HW_ATL2_RPF_VLAN_INDEX = HW_ATL2_RPF_PCP_TO_TC_INDEX +
AQ_CFG_TCS_MAX,
HW_ATL2_RPF_MAC_INDEX,
HW_ATL2_RPF_ALLMC_INDEX,
HW_ATL2_RPF_UNTAG_INDEX,
HW_ATL2_RPF_VLAN_PROMISC_ON_INDEX,
HW_ATL2_RPF_L2_PROMISC_ON_INDEX,
};
#define HW_ATL2_ACTION(ACTION, RSS, INDEX, VALID) \
((((ACTION) & 0x3U) << 8) | \
(((RSS) & 0x1U) << 7) | \
(((INDEX) & 0x3FU) << 2) | \
(((VALID) & 0x1U) << 0))
#define HW_ATL2_ACTION_DROP HW_ATL2_ACTION(0, 0, 0, 1)
#define HW_ATL2_ACTION_DISABLE HW_ATL2_ACTION(0, 0, 0, 0)
#define HW_ATL2_ACTION_ASSIGN_QUEUE(QUEUE) HW_ATL2_ACTION(1, 0, (QUEUE), 1)
#define HW_ATL2_ACTION_ASSIGN_TC(TC) HW_ATL2_ACTION(1, 1, (TC), 1)
enum HW_ATL2_RPF_RSS_HASH_TYPE {
HW_ATL2_RPF_RSS_HASH_TYPE_NONE = 0,
HW_ATL2_RPF_RSS_HASH_TYPE_IPV4 = BIT(0),
HW_ATL2_RPF_RSS_HASH_TYPE_IPV4_TCP = BIT(1),
HW_ATL2_RPF_RSS_HASH_TYPE_IPV4_UDP = BIT(2),
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6 = BIT(3),
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_TCP = BIT(4),
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_UDP = BIT(5),
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_EX = BIT(6),
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_EX_TCP = BIT(7),
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_EX_UDP = BIT(8),
HW_ATL2_RPF_RSS_HASH_TYPE_ALL = HW_ATL2_RPF_RSS_HASH_TYPE_IPV4 |
HW_ATL2_RPF_RSS_HASH_TYPE_IPV4_TCP |
HW_ATL2_RPF_RSS_HASH_TYPE_IPV4_UDP |
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6 |
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_TCP |
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_UDP |
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_EX |
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_EX_TCP |
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_EX_UDP,
};
#define HW_ATL_RSS_DISABLED 0x00000000U
#define HW_ATL_RSS_ENABLED_3INDEX_BITS 0xB3333333U
#define HW_ATL_MCAST_FLT_ANY_TO_HOST 0x00010FFFU
struct hw_atl2_priv {
struct statistics_s last_stats;
unsigned int art_base_index;
};
#endif /* HW_ATL2_INTERNAL_H */
// SPDX-License-Identifier: GPL-2.0-only
/* Atlantic Network Driver
* Copyright (C) 2020 Marvell International Ltd.
*/
#include "hw_atl2_llh.h"
#include "hw_atl2_llh_internal.h"
#include "aq_hw_utils.h"
void hw_atl2_rpf_rss_hash_type_set(struct aq_hw_s *aq_hw, u32 rss_hash_type)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_ADR,
HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_MSK,
HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_SHIFT,
rss_hash_type);
}
/* rpf */
void hw_atl2_rpf_new_enable_set(struct aq_hw_s *aq_hw, u32 enable)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_NEW_EN_ADR,
HW_ATL2_RPF_NEW_EN_MSK,
HW_ATL2_RPF_NEW_EN_SHIFT,
enable);
}
void hw_atl2_rpfl2_uc_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPFL2UC_TAG_ADR(filter),
HW_ATL2_RPFL2UC_TAG_MSK,
HW_ATL2_RPFL2UC_TAG_SHIFT,
tag);
}
void hw_atl2_rpfl2_bc_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_L2_BC_TAG_ADR,
HW_ATL2_RPF_L2_BC_TAG_MSK,
HW_ATL2_RPF_L2_BC_TAG_SHIFT,
tag);
}
void hw_atl2_new_rpf_rss_redir_set(struct aq_hw_s *aq_hw, u32 tc, u32 index,
u32 queue)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_RSS_REDIR_ADR(tc, index),
HW_ATL2_RPF_RSS_REDIR_MSK(tc),
HW_ATL2_RPF_RSS_REDIR_SHIFT(tc),
queue);
}
void hw_atl2_rpf_vlan_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_VL_TAG_ADR(filter),
HW_ATL2_RPF_VL_TAG_MSK,
HW_ATL2_RPF_VL_TAG_SHIFT,
tag);
}
/* TX */
void hw_atl2_tpb_tx_buf_clk_gate_en_set(struct aq_hw_s *aq_hw, u32 clk_gate_en)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_ADR,
HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_MSK,
HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_SHIFT,
clk_gate_en);
}
void hw_atl2_reg_tx_intr_moder_ctrl_set(struct aq_hw_s *aq_hw,
u32 tx_intr_moderation_ctl,
u32 queue)
{
aq_hw_write_reg(aq_hw, HW_ATL2_TX_INTR_MODERATION_CTL_ADR(queue),
tx_intr_moderation_ctl);
}
void hw_atl2_tps_tx_pkt_shed_tc_data_max_credit_set(struct aq_hw_s *aq_hw,
u32 max_credit,
u32 tc)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TPS_DATA_TCTCREDIT_MAX_ADR(tc),
HW_ATL2_TPS_DATA_TCTCREDIT_MAX_MSK,
HW_ATL2_TPS_DATA_TCTCREDIT_MAX_SHIFT,
max_credit);
}
void hw_atl2_tps_tx_pkt_shed_tc_data_weight_set(struct aq_hw_s *aq_hw,
u32 tx_pkt_shed_tc_data_weight,
u32 tc)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TPS_DATA_TCTWEIGHT_ADR(tc),
HW_ATL2_TPS_DATA_TCTWEIGHT_MSK,
HW_ATL2_TPS_DATA_TCTWEIGHT_SHIFT,
tx_pkt_shed_tc_data_weight);
}
u32 hw_atl2_get_hw_version(struct aq_hw_s *aq_hw)
{
return aq_hw_read_reg(aq_hw, HW_ATL2_FPGA_VER_ADR);
}
void hw_atl2_init_launchtime(struct aq_hw_s *aq_hw)
{
u32 hw_ver = hw_atl2_get_hw_version(aq_hw);
aq_hw_write_reg_bit(aq_hw, HW_ATL2_LT_CTRL_ADR,
HW_ATL2_LT_CTRL_CLK_RATIO_MSK,
HW_ATL2_LT_CTRL_CLK_RATIO_SHIFT,
hw_ver < HW_ATL2_FPGA_VER_U32(1, 0, 0, 0) ?
HW_ATL2_LT_CTRL_CLK_RATIO_FULL_SPEED :
hw_ver >= HW_ATL2_FPGA_VER_U32(1, 0, 85, 2) ?
HW_ATL2_LT_CTRL_CLK_RATIO_HALF_SPEED :
HW_ATL2_LT_CTRL_CLK_RATIO_QUATER_SPEED);
}
/* set action resolver record */
void hw_atl2_rpf_act_rslvr_record_set(struct aq_hw_s *aq_hw, u8 location,
u32 tag, u32 mask, u32 action)
{
aq_hw_write_reg(aq_hw,
HW_ATL2_RPF_ACT_RSLVR_REQ_TAG_ADR(location),
tag);
aq_hw_write_reg(aq_hw,
HW_ATL2_RPF_ACT_RSLVR_TAG_MASK_ADR(location),
mask);
aq_hw_write_reg(aq_hw,
HW_ATL2_RPF_ACT_RSLVR_ACTN_ADR(location),
action);
}
void hw_atl2_rpf_act_rslvr_section_en_set(struct aq_hw_s *aq_hw, u32 sections)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_REC_TAB_EN_ADR,
HW_ATL2_RPF_REC_TAB_EN_MSK,
HW_ATL2_RPF_REC_TAB_EN_SHIFT,
sections);
}
void hw_atl2_mif_shared_buf_get(struct aq_hw_s *aq_hw, int offset, u32 *data,
int len)
{
int j = 0;
int i;
for (i = offset; i < offset + len; i++, j++)
data[j] = aq_hw_read_reg(aq_hw,
HW_ATL2_MIF_SHARED_BUFFER_IN_ADR(i));
}
void hw_atl2_mif_shared_buf_write(struct aq_hw_s *aq_hw, int offset, u32 *data,
int len)
{
int j = 0;
int i;
for (i = offset; i < offset + len; i++, j++)
aq_hw_write_reg(aq_hw, HW_ATL2_MIF_SHARED_BUFFER_IN_ADR(i),
data[j]);
}
void hw_atl2_mif_shared_buf_read(struct aq_hw_s *aq_hw, int offset, u32 *data,
int len)
{
int j = 0;
int i;
for (i = offset; i < offset + len; i++, j++)
data[j] = aq_hw_read_reg(aq_hw,
HW_ATL2_MIF_SHARED_BUFFER_OUT_ADR(i));
}
void hw_atl2_mif_host_finished_write_set(struct aq_hw_s *aq_hw, u32 finish)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_MIF_HOST_FINISHED_WRITE_ADR,
HW_ATL2_MIF_HOST_FINISHED_WRITE_MSK,
HW_ATL2_MIF_HOST_FINISHED_WRITE_SHIFT,
finish);
}
u32 hw_atl2_mif_mcp_finished_read_get(struct aq_hw_s *aq_hw)
{
return aq_hw_read_reg_bit(aq_hw, HW_ATL2_MIF_MCP_FINISHED_READ_ADR,
HW_ATL2_MIF_MCP_FINISHED_READ_MSK,
HW_ATL2_MIF_MCP_FINISHED_READ_SHIFT);
}
u32 hw_atl2_mif_mcp_boot_reg_get(struct aq_hw_s *aq_hw)
{
return aq_hw_read_reg(aq_hw, HW_ATL2_MIF_BOOT_REG_ADR);
}
void hw_atl2_mif_mcp_boot_reg_set(struct aq_hw_s *aq_hw, u32 val)
{
return aq_hw_write_reg(aq_hw, HW_ATL2_MIF_BOOT_REG_ADR, val);
}
u32 hw_atl2_mif_host_req_int_get(struct aq_hw_s *aq_hw)
{
return aq_hw_read_reg(aq_hw, HW_ATL2_MCP_HOST_REQ_INT_ADR);
}
void hw_atl2_mif_host_req_int_clr(struct aq_hw_s *aq_hw, u32 val)
{
return aq_hw_write_reg(aq_hw, HW_ATL2_MCP_HOST_REQ_INT_CLR_ADR,
val);
}
/* SPDX-License-Identifier: GPL-2.0-only */
/* Atlantic Network Driver
* Copyright (C) 2020 Marvell International Ltd.
*/
#ifndef HW_ATL2_LLH_H
#define HW_ATL2_LLH_H
#include <linux/types.h>
struct aq_hw_s;
/* Set TX Interrupt Moderation Control Register */
void hw_atl2_reg_tx_intr_moder_ctrl_set(struct aq_hw_s *aq_hw,
u32 tx_intr_moderation_ctl,
u32 queue);
/** Set RSS HASH type */
void hw_atl2_rpf_rss_hash_type_set(struct aq_hw_s *aq_hw, u32 rss_hash_type);
/* set new RPF enable */
void hw_atl2_rpf_new_enable_set(struct aq_hw_s *aq_hw, u32 enable);
/* set l2 unicast filter tag */
void hw_atl2_rpfl2_uc_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter);
/* set l2 broadcast filter tag */
void hw_atl2_rpfl2_bc_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag);
/* set new rss redirection table */
void hw_atl2_new_rpf_rss_redir_set(struct aq_hw_s *aq_hw, u32 tc, u32 index,
u32 queue);
/* Set VLAN filter tag */
void hw_atl2_rpf_vlan_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter);
/* set tx buffer clock gate enable */
void hw_atl2_tpb_tx_buf_clk_gate_en_set(struct aq_hw_s *aq_hw, u32 clk_gate_en);
/* set tx packet scheduler tc data max credit */
void hw_atl2_tps_tx_pkt_shed_tc_data_max_credit_set(struct aq_hw_s *aq_hw,
u32 max_credit,
u32 tc);
/* set tx packet scheduler tc data weight */
void hw_atl2_tps_tx_pkt_shed_tc_data_weight_set(struct aq_hw_s *aq_hw,
u32 tx_pkt_shed_tc_data_weight,
u32 tc);
u32 hw_atl2_get_hw_version(struct aq_hw_s *aq_hw);
void hw_atl2_init_launchtime(struct aq_hw_s *aq_hw);
/* set action resolver record */
void hw_atl2_rpf_act_rslvr_record_set(struct aq_hw_s *aq_hw, u8 location,
u32 tag, u32 mask, u32 action);
/* set enable action resolver section */
void hw_atl2_rpf_act_rslvr_section_en_set(struct aq_hw_s *aq_hw, u32 sections);
/* get data from firmware shared input buffer */
void hw_atl2_mif_shared_buf_get(struct aq_hw_s *aq_hw, int offset, u32 *data,
int len);
/* set data into firmware shared input buffer */
void hw_atl2_mif_shared_buf_write(struct aq_hw_s *aq_hw, int offset, u32 *data,
int len);
/* get data from firmware shared output buffer */
void hw_atl2_mif_shared_buf_read(struct aq_hw_s *aq_hw, int offset, u32 *data,
int len);
/* set host finished write shared buffer indication */
void hw_atl2_mif_host_finished_write_set(struct aq_hw_s *aq_hw, u32 finish);
/* get mcp finished read shared buffer indication */
u32 hw_atl2_mif_mcp_finished_read_get(struct aq_hw_s *aq_hw);
/* get mcp boot register */
u32 hw_atl2_mif_mcp_boot_reg_get(struct aq_hw_s *aq_hw);
/* set mcp boot register */
void hw_atl2_mif_mcp_boot_reg_set(struct aq_hw_s *aq_hw, u32 val);
/* get host interrupt request */
u32 hw_atl2_mif_host_req_int_get(struct aq_hw_s *aq_hw);
/* clear host interrupt request */
void hw_atl2_mif_host_req_int_clr(struct aq_hw_s *aq_hw, u32 val);
#endif /* HW_ATL2_LLH_H */
// SPDX-License-Identifier: GPL-2.0-only
/* Atlantic Network Driver
* Copyright (C) 2020 Marvell International Ltd.
*/
#include <linux/iopoll.h>
#include "aq_hw_utils.h"
#include "hw_atl/hw_atl_utils.h"
#include "hw_atl2_utils.h"
#include "hw_atl2_llh.h"
#include "hw_atl2_llh_internal.h"
#define HW_ATL2_FW_VER_1X 0x01000000U
#define AQ_A2_BOOT_STARTED BIT(0x18)
#define AQ_A2_CRASH_INIT BIT(0x1B)
#define AQ_A2_BOOT_CODE_FAILED BIT(0x1C)
#define AQ_A2_FW_INIT_FAILED BIT(0x1D)
#define AQ_A2_FW_INIT_COMP_SUCCESS BIT(0x1F)
#define AQ_A2_FW_BOOT_FAILED_MASK (AQ_A2_CRASH_INIT | \
AQ_A2_BOOT_CODE_FAILED | \
AQ_A2_FW_INIT_FAILED)
#define AQ_A2_FW_BOOT_COMPLETE_MASK (AQ_A2_FW_BOOT_FAILED_MASK | \
AQ_A2_FW_INIT_COMP_SUCCESS)
#define AQ_A2_FW_BOOT_REQ_REBOOT BIT(0x0)
#define AQ_A2_FW_BOOT_REQ_HOST_BOOT BIT(0x8)
#define AQ_A2_FW_BOOT_REQ_MAC_FAST_BOOT BIT(0xA)
#define AQ_A2_FW_BOOT_REQ_PHY_FAST_BOOT BIT(0xB)
int hw_atl2_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops)
{
int err;
self->fw_ver_actual = hw_atl2_utils_get_fw_version(self);
if (hw_atl_utils_ver_match(HW_ATL2_FW_VER_1X,
self->fw_ver_actual) == 0) {
*fw_ops = &aq_a2_fw_ops;
} else {
aq_pr_err("Bad FW version detected: %x, but continue\n",
self->fw_ver_actual);
*fw_ops = &aq_a2_fw_ops;
}
aq_pr_trace("Detect ATL2FW %x\n", self->fw_ver_actual);
self->aq_fw_ops = *fw_ops;
err = self->aq_fw_ops->init(self);
self->chip_features |= ATL_HW_CHIP_ANTIGUA;
return err;
}
static bool hw_atl2_mcp_boot_complete(struct aq_hw_s *self)
{
u32 rbl_status;
rbl_status = hw_atl2_mif_mcp_boot_reg_get(self);
if (rbl_status & AQ_A2_FW_BOOT_COMPLETE_MASK)
return true;
/* Host boot requested */
if (hw_atl2_mif_host_req_int_get(self) & HW_ATL2_MCP_HOST_REQ_INT_READY)
return true;
return false;
}
int hw_atl2_utils_soft_reset(struct aq_hw_s *self)
{
bool rbl_complete = false;
u32 rbl_status = 0;
u32 rbl_request;
int err;
err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_boot_reg_get, self,
rbl_status,
((rbl_status & AQ_A2_BOOT_STARTED) &&
(rbl_status != 0xFFFFFFFFu)),
10, 500000);
if (err)
aq_pr_trace("Boot code probably hanged, reboot anyway");
hw_atl2_mif_host_req_int_clr(self, 0x01);
rbl_request = AQ_A2_FW_BOOT_REQ_REBOOT;
#ifdef AQ_CFG_FAST_START
rbl_request |= AQ_A2_FW_BOOT_REQ_MAC_FAST_BOOT;
#endif
hw_atl2_mif_mcp_boot_reg_set(self, rbl_request);
/* Wait for RBL boot */
err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_boot_reg_get, self,
rbl_status,
((rbl_status & AQ_A2_BOOT_STARTED) &&
(rbl_status != 0xFFFFFFFFu)),
10, 200000);
if (err) {
aq_pr_err("Boot code hanged");
goto err_exit;
}
err = readx_poll_timeout_atomic(hw_atl2_mcp_boot_complete, self,
rbl_complete,
rbl_complete,
10, 2000000);
if (err) {
aq_pr_err("FW Restart timed out");
goto err_exit;
}
rbl_status = hw_atl2_mif_mcp_boot_reg_get(self);
if (rbl_status & AQ_A2_FW_BOOT_FAILED_MASK) {
err = -EIO;
aq_pr_err("FW Restart failed");
goto err_exit;
}
if (hw_atl2_mif_host_req_int_get(self) &
HW_ATL2_MCP_HOST_REQ_INT_READY) {
err = -EIO;
aq_pr_err("No FW detected. Dynamic FW load not implemented");
goto err_exit;
}
if (self->aq_fw_ops) {
err = self->aq_fw_ops->init(self);
if (err) {
aq_pr_err("FW Init failed");
goto err_exit;
}
}
err_exit:
return err;
}
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0-only
/* Atlantic Network Driver
* Copyright (C) 2020 Marvell International Ltd.
*/
#include <linux/iopoll.h>
#include "aq_hw.h"
#include "hw_atl/hw_atl_llh.h"
#include "hw_atl2_utils.h"
#include "hw_atl2_llh.h"
#include "hw_atl2_internal.h"
#define AQ_A2_FW_READ_TRY_MAX 1000
#define hw_atl2_shared_buffer_write(HW, ITEM, VARIABLE) \
hw_atl2_mif_shared_buf_write(HW,\
(offsetof(struct fw_interface_in, ITEM) / sizeof(u32)),\
(u32 *)&(VARIABLE), sizeof(VARIABLE) / sizeof(u32))
#define hw_atl2_shared_buffer_get(HW, ITEM, VARIABLE) \
hw_atl2_mif_shared_buf_get(HW, \
(offsetof(struct fw_interface_in, ITEM) / sizeof(u32)),\
(u32 *)&(VARIABLE), \
sizeof(VARIABLE) / sizeof(u32))
/* This should never be used on non atomic fields,
* treat any > u32 read as non atomic.
*/
#define hw_atl2_shared_buffer_read(HW, ITEM, VARIABLE) \
{\
BUILD_BUG_ON_MSG((offsetof(struct fw_interface_out, ITEM) % \
sizeof(u32)) != 0,\
"Non aligned read " # ITEM);\
BUILD_BUG_ON_MSG(sizeof(VARIABLE) > sizeof(u32),\
"Non atomic read " # ITEM);\
hw_atl2_mif_shared_buf_read(HW, \
(offsetof(struct fw_interface_out, ITEM) / sizeof(u32)),\
(u32 *)&(VARIABLE), sizeof(VARIABLE) / sizeof(u32));\
}
#define hw_atl2_shared_buffer_read_safe(HW, ITEM, DATA) \
hw_atl2_shared_buffer_read_block((HW), \
(offsetof(struct fw_interface_out, ITEM) / sizeof(u32)),\
sizeof(((struct fw_interface_out *)0)->ITEM) / sizeof(u32),\
(DATA))
static int hw_atl2_shared_buffer_read_block(struct aq_hw_s *self,
u32 offset, u32 dwords, void *data)
{
struct transaction_counter_s tid1, tid2;
int cnt = 0;
do {
do {
hw_atl2_shared_buffer_read(self, transaction_id, tid1);
cnt++;
if (cnt > AQ_A2_FW_READ_TRY_MAX)
return -ETIME;
if (tid1.transaction_cnt_a != tid1.transaction_cnt_b)
udelay(1);
} while (tid1.transaction_cnt_a != tid1.transaction_cnt_b);
hw_atl2_mif_shared_buf_read(self, offset, (u32 *)data, dwords);
hw_atl2_shared_buffer_read(self, transaction_id, tid2);
cnt++;
if (cnt > AQ_A2_FW_READ_TRY_MAX)
return -ETIME;
} while (tid2.transaction_cnt_a != tid2.transaction_cnt_b ||
tid1.transaction_cnt_a != tid2.transaction_cnt_a);
return 0;
}
static inline int hw_atl2_shared_buffer_finish_ack(struct aq_hw_s *self)
{
u32 val;
int err;
hw_atl2_mif_host_finished_write_set(self, 1U);
err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_finished_read_get,
self, val, val == 0U,
100, 100000U);
WARN(err, "hw_atl2_shared_buffer_finish_ack");
return err;
}
static int aq_a2_fw_init(struct aq_hw_s *self)
{
struct link_control_s link_control;
u32 mtu;
u32 val;
int err;
hw_atl2_shared_buffer_get(self, link_control, link_control);
link_control.mode = AQ_HOST_MODE_ACTIVE;
hw_atl2_shared_buffer_write(self, link_control, link_control);
hw_atl2_shared_buffer_get(self, mtu, mtu);
mtu = HW_ATL2_MTU_JUMBO;
hw_atl2_shared_buffer_write(self, mtu, mtu);
hw_atl2_mif_host_finished_write_set(self, 1U);
err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_finished_read_get,
self, val, val == 0U,
100, 5000000U);
WARN(err, "hw_atl2_shared_buffer_finish_ack");
return err;
}
static int aq_a2_fw_deinit(struct aq_hw_s *self)
{
struct link_control_s link_control;
hw_atl2_shared_buffer_get(self, link_control, link_control);
link_control.mode = AQ_HOST_MODE_SHUTDOWN;
hw_atl2_shared_buffer_write(self, link_control, link_control);
return hw_atl2_shared_buffer_finish_ack(self);
}
static void a2_link_speed_mask2fw(u32 speed,
struct link_options_s *link_options)
{
link_options->rate_10G = !!(speed & AQ_NIC_RATE_10G);
link_options->rate_5G = !!(speed & AQ_NIC_RATE_5G);
link_options->rate_N5G = !!(speed & AQ_NIC_RATE_5GSR);
link_options->rate_2P5G = !!(speed & AQ_NIC_RATE_2GS);
link_options->rate_N2P5G = link_options->rate_2P5G;
link_options->rate_1G = !!(speed & AQ_NIC_RATE_1G);
link_options->rate_100M = !!(speed & AQ_NIC_RATE_100M);
link_options->rate_10M = !!(speed & AQ_NIC_RATE_10M);
}
static int aq_a2_fw_set_link_speed(struct aq_hw_s *self, u32 speed)
{
struct link_options_s link_options;
hw_atl2_shared_buffer_get(self, link_options, link_options);
link_options.link_up = 1U;
a2_link_speed_mask2fw(speed, &link_options);
hw_atl2_shared_buffer_write(self, link_options, link_options);
return hw_atl2_shared_buffer_finish_ack(self);
}
static int aq_a2_fw_set_state(struct aq_hw_s *self,
enum hal_atl_utils_fw_state_e state)
{
struct link_options_s link_options;
hw_atl2_shared_buffer_get(self, link_options, link_options);
switch (state) {
case MPI_INIT:
link_options.link_up = 1U;
break;
case MPI_DEINIT:
link_options.link_up = 0U;
break;
case MPI_RESET:
case MPI_POWER:
/* No actions */
break;
}
hw_atl2_shared_buffer_write(self, link_options, link_options);
return hw_atl2_shared_buffer_finish_ack(self);
}
static int aq_a2_fw_update_link_status(struct aq_hw_s *self)
{
struct link_status_s link_status;
hw_atl2_shared_buffer_read(self, link_status, link_status);
switch (link_status.link_rate) {
case AQ_A2_FW_LINK_RATE_10G:
self->aq_link_status.mbps = 10000;
break;
case AQ_A2_FW_LINK_RATE_5G:
self->aq_link_status.mbps = 5000;
break;
case AQ_A2_FW_LINK_RATE_2G5:
self->aq_link_status.mbps = 2500;
break;
case AQ_A2_FW_LINK_RATE_1G:
self->aq_link_status.mbps = 1000;
break;
case AQ_A2_FW_LINK_RATE_100M:
self->aq_link_status.mbps = 100;
break;
case AQ_A2_FW_LINK_RATE_10M:
self->aq_link_status.mbps = 10;
break;
default:
self->aq_link_status.mbps = 0;
}
return 0;
}
static int aq_a2_fw_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
{
struct mac_address_aligned_s mac_address;
hw_atl2_shared_buffer_get(self, mac_address, mac_address);
ether_addr_copy(mac, (u8 *)mac_address.aligned.mac_address);
if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
unsigned int rnd = 0;
u32 h;
u32 l;
get_random_bytes(&rnd, sizeof(unsigned int));
l = 0xE3000000U | (0xFFFFU & rnd) | (0x00 << 16);
h = 0x8001300EU;
mac[5] = (u8)(0xFFU & l);
l >>= 8;
mac[4] = (u8)(0xFFU & l);
l >>= 8;
mac[3] = (u8)(0xFFU & l);
l >>= 8;
mac[2] = (u8)(0xFFU & l);
mac[1] = (u8)(0xFFU & h);
h >>= 8;
mac[0] = (u8)(0xFFU & h);
}
return 0;
}
static int aq_a2_fw_update_stats(struct aq_hw_s *self)
{
struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv;
struct statistics_s stats;
hw_atl2_shared_buffer_read_safe(self, stats, &stats);
#define AQ_SDELTA(_N_, _F_) (self->curr_stats._N_ += \
stats.msm._F_ - priv->last_stats.msm._F_)
if (self->aq_link_status.mbps) {
AQ_SDELTA(uprc, rx_unicast_frames);
AQ_SDELTA(mprc, rx_multicast_frames);
AQ_SDELTA(bprc, rx_broadcast_frames);
AQ_SDELTA(erpr, rx_error_frames);
AQ_SDELTA(uptc, tx_unicast_frames);
AQ_SDELTA(mptc, tx_multicast_frames);
AQ_SDELTA(bptc, tx_broadcast_frames);
AQ_SDELTA(erpt, tx_errors);
AQ_SDELTA(ubrc, rx_unicast_octets);
AQ_SDELTA(ubtc, tx_unicast_octets);
AQ_SDELTA(mbrc, rx_multicast_octets);
AQ_SDELTA(mbtc, tx_multicast_octets);
AQ_SDELTA(bbrc, rx_broadcast_octets);
AQ_SDELTA(bbtc, tx_broadcast_octets);
}
#undef AQ_SDELTA
self->curr_stats.dma_pkt_rc =
hw_atl_stats_rx_dma_good_pkt_counter_get(self);
self->curr_stats.dma_pkt_tc =
hw_atl_stats_tx_dma_good_pkt_counter_get(self);
self->curr_stats.dma_oct_rc =
hw_atl_stats_rx_dma_good_octet_counter_get(self);
self->curr_stats.dma_oct_tc =
hw_atl_stats_tx_dma_good_octet_counter_get(self);
self->curr_stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self);
memcpy(&priv->last_stats, &stats, sizeof(stats));
return 0;
}
static int aq_a2_fw_renegotiate(struct aq_hw_s *self)
{
struct link_options_s link_options;
int err;
hw_atl2_shared_buffer_get(self, link_options, link_options);
link_options.link_renegotiate = 1U;
hw_atl2_shared_buffer_write(self, link_options, link_options);
err = hw_atl2_shared_buffer_finish_ack(self);
/* We should put renegotiate status back to zero
* after command completes
*/
link_options.link_renegotiate = 0U;
hw_atl2_shared_buffer_write(self, link_options, link_options);
return err;
}
u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self)
{
struct version_s version;
hw_atl2_shared_buffer_read_safe(self, version, &version);
/* A2 FW version is stored in reverse order */
return version.mac.major << 24 |
version.mac.minor << 16 |
version.mac.build;
}
int hw_atl2_utils_get_action_resolve_table_caps(struct aq_hw_s *self,
u8 *base_index, u8 *count)
{
struct filter_caps_s filter_caps;
int err;
err = hw_atl2_shared_buffer_read_safe(self, filter_caps, &filter_caps);
if (err)
return err;
*base_index = filter_caps.rslv_tbl_base_index;
*count = filter_caps.rslv_tbl_count;
return 0;
}
const struct aq_fw_ops aq_a2_fw_ops = {
.init = aq_a2_fw_init,
.deinit = aq_a2_fw_deinit,
.reset = NULL,
.renegotiate = aq_a2_fw_renegotiate,
.get_mac_permanent = aq_a2_fw_get_mac_permanent,
.set_link_speed = aq_a2_fw_set_link_speed,
.set_state = aq_a2_fw_set_state,
.update_link_status = aq_a2_fw_update_link_status,
.update_stats = aq_a2_fw_update_stats,
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment