Commit 65b342f1 authored by David S. Miller's avatar David S. Miller

Merge branch 'Aquantia-atlantic-driver-new-devices-support'

Igor Russkikh says:

====================
Aquantia atlantic driver new devices support

This patchset introduces a support for new Aquantia hardware:
AQC11x family with updated hardware (B1) and firmware (2.x and 3.x branches).

For that, a number of improvements in overall driver model were done:
 - Firmware specific ops tables. Firmware 2.x and 3.x series support
   functions are now in separate fw2x module.
 - PCI module cleanup and simplification done.
 - Verified and tested hardware reset process.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f9b6ae29 6de97c04
......@@ -39,4 +39,5 @@ atlantic-objs := aq_main.o \
hw_atl/hw_atl_a0.o \
hw_atl/hw_atl_b0.o \
hw_atl/hw_atl_utils.o \
hw_atl/hw_atl_utils_fw2x.o \
hw_atl/hw_atl_llh.o
......@@ -65,7 +65,13 @@
/*#define AQ_CFG_MAC_ADDR_PERMANENT {0x30, 0x0E, 0xE3, 0x12, 0x34, 0x56}*/
#define AQ_CFG_FC_MODE 3U
#define AQ_NIC_FC_OFF 0U
#define AQ_NIC_FC_TX 1U
#define AQ_NIC_FC_RX 2U
#define AQ_NIC_FC_FULL 3U
#define AQ_NIC_FC_AUTO 4U
#define AQ_CFG_FC_MODE AQ_NIC_FC_FULL
#define AQ_CFG_SPEED_MSK 0xFFFFU /* 0xFFFFU==auto_neg */
......
......@@ -19,4 +19,42 @@
#include "aq_cfg.h"
#include "aq_utils.h"
#define PCI_VENDOR_ID_AQUANTIA 0x1D6A
#define AQ_DEVICE_ID_0001 0x0001
#define AQ_DEVICE_ID_D100 0xD100
#define AQ_DEVICE_ID_D107 0xD107
#define AQ_DEVICE_ID_D108 0xD108
#define AQ_DEVICE_ID_D109 0xD109
#define AQ_DEVICE_ID_AQC100 0x00B1
#define AQ_DEVICE_ID_AQC107 0x07B1
#define AQ_DEVICE_ID_AQC108 0x08B1
#define AQ_DEVICE_ID_AQC109 0x09B1
#define AQ_DEVICE_ID_AQC111 0x11B1
#define AQ_DEVICE_ID_AQC112 0x12B1
#define AQ_DEVICE_ID_AQC100S 0x80B1
#define AQ_DEVICE_ID_AQC107S 0x87B1
#define AQ_DEVICE_ID_AQC108S 0x88B1
#define AQ_DEVICE_ID_AQC109S 0x89B1
#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
#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)
#endif /* AQ_COMMON_H */
......@@ -23,6 +23,7 @@ struct aq_hw_caps_s {
u64 hw_features;
u64 link_speed_msk;
unsigned int hw_priv_flags;
u32 media_type;
u32 rxds;
u32 txds;
u32 txhwb_alignment;
......@@ -30,7 +31,7 @@ struct aq_hw_caps_s {
u32 vecs;
u32 mtu;
u32 mac_regs_count;
u8 ports;
u32 hw_alive_check_addr;
u8 msix_irqs;
u8 tcs;
u8 rxd_alignment;
......@@ -41,7 +42,6 @@ struct aq_hw_caps_s {
u8 rx_rings;
bool flow_control;
bool is_64_dma;
u32 fw_ver_expected;
};
struct aq_hw_link_status_s {
......@@ -95,12 +95,15 @@ struct aq_stats_s {
#define AQ_NIC_FLAGS_IS_NOT_TX_READY (AQ_NIC_FLAGS_IS_NOT_READY | \
AQ_NIC_LINK_DOWN)
#define AQ_HW_MEDIA_TYPE_TP 1U
#define AQ_HW_MEDIA_TYPE_FIBRE 2U
struct aq_hw_s {
atomic_t flags;
u8 rbl_enabled:1;
struct aq_nic_cfg_s *aq_nic_cfg;
struct aq_pci_func_s *aq_pci_func;
const struct aq_fw_ops *aq_fw_ops;
void __iomem *mmio;
unsigned int not_ff_addr;
struct aq_hw_link_status_s aq_link_status;
struct hw_aq_atl_utils_mbox mbox;
struct hw_atl_stats_s last_stats;
......@@ -119,19 +122,9 @@ struct aq_hw_s {
struct aq_ring_s;
struct aq_ring_param_s;
struct aq_nic_cfg_s;
struct sk_buff;
struct aq_hw_ops {
struct aq_hw_s *(*create)(struct aq_pci_func_s *aq_pci_func,
unsigned int port);
void (*destroy)(struct aq_hw_s *self);
int (*get_hw_caps)(struct aq_hw_s *self,
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);
......@@ -145,15 +138,8 @@ struct aq_hw_ops {
int (*hw_ring_tx_head_update)(struct aq_hw_s *self,
struct aq_ring_s *aq_ring);
int (*hw_get_mac_permanent)(struct aq_hw_s *self,
u8 *mac);
int (*hw_set_mac_address)(struct aq_hw_s *self, u8 *mac_addr);
int (*hw_get_link_status)(struct aq_hw_s *self);
int (*hw_set_link_speed)(struct aq_hw_s *self, u32 speed);
int (*hw_reset)(struct aq_hw_s *self);
int (*hw_init)(struct aq_hw_s *self, u8 *mac_addr);
......@@ -207,8 +193,6 @@ struct aq_hw_ops {
const struct aq_hw_caps_s *aq_hw_caps,
u32 *regs_buff);
int (*hw_update_stats)(struct aq_hw_s *self);
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);
......@@ -218,4 +202,20 @@ struct aq_hw_ops {
int (*hw_set_power)(struct aq_hw_s *self, unsigned int power_state);
};
struct aq_fw_ops {
int (*init)(struct aq_hw_s *self);
int (*reset)(struct aq_hw_s *self);
int (*get_mac_permanent)(struct aq_hw_s *self, u8 *mac);
int (*set_link_speed)(struct aq_hw_s *self, u32 speed);
int (*set_state)(struct aq_hw_s *self, enum hal_atl_utils_fw_state_e state);
int (*update_link_status)(struct aq_hw_s *self);
int (*update_stats)(struct aq_hw_s *self);
};
#endif /* AQ_HW_H */
......@@ -13,6 +13,7 @@
#include "aq_hw_utils.h"
#include "aq_hw.h"
#include "aq_nic.h"
void aq_hw_write_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk,
u32 shift, u32 val)
......@@ -39,7 +40,9 @@ u32 aq_hw_read_reg(struct aq_hw_s *hw, u32 reg)
{
u32 value = readl(hw->mmio + reg);
if ((~0U) == value && (~0U) == readl(hw->mmio + hw->not_ff_addr))
if ((~0U) == value &&
(~0U) == readl(hw->mmio +
hw->aq_nic_cfg->aq_hw_caps->hw_alive_check_addr))
aq_utils_obj_set(&hw->flags, AQ_HW_FLAG_ERR_UNPLUG);
return value;
......
......@@ -35,6 +35,9 @@ do { \
} \
} while (0)
#define aq_pr_err(...) pr_err(AQ_CFG_DRV_NAME ": " __VA_ARGS__)
#define aq_pr_trace(...) pr_info(AQ_CFG_DRV_NAME ": " __VA_ARGS__)
struct aq_hw_s;
void aq_hw_write_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk,
......
......@@ -43,14 +43,9 @@ struct net_device *aq_ndev_alloc(void)
static int aq_ndev_open(struct net_device *ndev)
{
struct aq_nic_s *aq_nic = NULL;
int err = 0;
struct aq_nic_s *aq_nic = netdev_priv(ndev);
aq_nic = aq_nic_alloc_hot(ndev);
if (!aq_nic) {
err = -ENOMEM;
goto err_exit;
}
err = aq_nic_init(aq_nic);
if (err < 0)
goto err_exit;
......@@ -73,7 +68,6 @@ static int aq_ndev_close(struct net_device *ndev)
if (err < 0)
goto err_exit;
aq_nic_deinit(aq_nic);
aq_nic_free_hot_resources(aq_nic);
err_exit:
return err;
......@@ -145,15 +139,13 @@ static void aq_ndev_set_multicast_settings(struct net_device *ndev)
err = aq_nic_set_packet_filter(aq_nic, ndev->flags);
if (err < 0)
goto err_exit;
return;
if (netdev_mc_count(ndev)) {
err = aq_nic_set_multicast_list(aq_nic, ndev);
if (err < 0)
goto err_exit;
return;
}
err_exit:;
}
static const struct net_device_ops aq_ndev_ops = {
......
......@@ -17,24 +17,10 @@
#include "aq_hw.h"
struct aq_ring_s;
struct aq_pci_func_s;
struct aq_hw_ops;
struct aq_fw_s;
struct aq_vec_s;
#define AQ_NIC_FC_OFF 0U
#define AQ_NIC_FC_TX 1U
#define AQ_NIC_FC_RX 2U
#define AQ_NIC_FC_FULL 3U
#define AQ_NIC_FC_AUTO 4U
#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)
struct aq_nic_cfg_s {
const struct aq_hw_caps_s *aq_hw_caps;
u64 hw_features;
......@@ -77,13 +63,12 @@ struct aq_nic_s {
struct aq_ring_s *aq_ring_tx[AQ_CFG_VECS_MAX * AQ_CFG_TCS_MAX];
struct aq_hw_s *aq_hw;
struct net_device *ndev;
struct aq_pci_func_s *aq_pci_func;
unsigned int aq_vecs;
unsigned int packet_filter;
unsigned int power_state;
u8 port;
struct aq_hw_ops aq_hw_ops;
struct aq_hw_caps_s aq_hw_caps;
const struct aq_hw_ops *aq_hw_ops;
const struct aq_fw_ops *aq_fw_ops;
struct aq_nic_cfg_s aq_nic_cfg;
struct timer_list service_timer;
struct timer_list polling_timer;
......@@ -102,18 +87,13 @@ static inline struct device *aq_nic_get_dev(struct aq_nic_s *self)
return self->ndev->dev.parent;
}
struct aq_nic_s *aq_nic_alloc_cold(struct pci_dev *pdev,
struct aq_pci_func_s *aq_pci_func,
unsigned int port,
const struct aq_hw_ops *aq_hw_ops);
int aq_nic_ndev_init(struct aq_nic_s *self);
void aq_nic_ndev_init(struct aq_nic_s *self);
struct aq_nic_s *aq_nic_alloc_hot(struct net_device *ndev);
void aq_nic_set_tx_ring(struct aq_nic_s *self, unsigned int idx,
struct aq_ring_s *ring);
struct device *aq_nic_get_dev(struct aq_nic_s *self);
struct net_device *aq_nic_get_ndev(struct aq_nic_s *self);
int aq_nic_init(struct aq_nic_s *self);
int aq_nic_cfg_start(struct aq_nic_s *self);
void aq_nic_cfg_start(struct aq_nic_s *self);
int aq_nic_ndev_register(struct aq_nic_s *self);
void aq_nic_ndev_free(struct aq_nic_s *self);
int aq_nic_start(struct aq_nic_s *self);
......@@ -124,6 +104,7 @@ void aq_nic_get_stats(struct aq_nic_s *self, u64 *data);
int aq_nic_stop(struct aq_nic_s *self);
void aq_nic_deinit(struct aq_nic_s *self);
void aq_nic_free_hot_resources(struct aq_nic_s *self);
void aq_nic_free_vectors(struct aq_nic_s *self);
int aq_nic_set_mtu(struct aq_nic_s *self, int new_mtu);
int aq_nic_set_mac(struct aq_nic_s *self, struct net_device *ndev);
int aq_nic_set_packet_filter(struct aq_nic_s *self, unsigned int flags);
......
......@@ -15,19 +15,18 @@
#include "aq_common.h"
#include "aq_nic.h"
struct aq_pci_func_s *aq_pci_func_alloc(const struct aq_hw_ops *hw_ops,
struct pci_dev *pdev);
int aq_pci_func_init(struct aq_pci_func_s *self);
int aq_pci_func_alloc_irq(struct aq_pci_func_s *self, unsigned int i,
struct aq_board_revision_s {
unsigned short devid;
unsigned short revision;
const struct aq_hw_ops *ops;
const struct aq_hw_caps_s *caps;
};
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);
void aq_pci_func_free_irqs(struct aq_pci_func_s *self);
int aq_pci_func_start(struct aq_pci_func_s *self);
void __iomem *aq_pci_func_get_mmio(struct aq_pci_func_s *self);
unsigned int aq_pci_func_get_irq_type(struct aq_pci_func_s *self);
void aq_pci_func_deinit(struct aq_pci_func_s *self);
void aq_pci_func_free(struct aq_pci_func_s *self);
int aq_pci_func_change_pm_state(struct aq_pci_func_s *self,
pm_message_t *pm_msg);
void aq_pci_func_free_irqs(struct aq_nic_s *self);
unsigned int aq_pci_func_get_irq_type(struct aq_nic_s *self);
#endif /* AQ_PCI_FUNC_H */
......@@ -18,45 +18,67 @@
#include "hw_atl_llh.h"
#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,
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;
}
static struct aq_hw_s *hw_atl_a0_create(struct aq_pci_func_s *aq_pci_func,
unsigned int port)
{
struct aq_hw_s *self = NULL;
self = kzalloc(sizeof(*self), GFP_KERNEL);
if (!self)
goto err_exit;
self->aq_pci_func = aq_pci_func;
#define DEFAULT_A0_BOARD_BASIC_CAPABILITIES \
.is_64_dma = true, \
.msix_irqs = 4U, \
.irq_mask = ~0U, \
.vecs = HW_ATL_A0_RSS_MAX, \
.tcs = HW_ATL_A0_TC_MAX, \
.rxd_alignment = 1U, \
.rxd_size = HW_ATL_A0_RXD_SIZE, \
.rxds = 248U, \
.txd_alignment = 1U, \
.txd_size = HW_ATL_A0_TXD_SIZE, \
.txds = 8U * 1024U, \
.txhwb_alignment = 4096U, \
.tx_rings = HW_ATL_A0_TX_RINGS, \
.rx_rings = HW_ATL_A0_RX_RINGS, \
.hw_features = NETIF_F_HW_CSUM | \
NETIF_F_RXHASH | \
NETIF_F_RXCSUM | \
NETIF_F_SG | \
NETIF_F_TSO, \
.hw_priv_flags = IFF_UNICAST_FLT, \
.flow_control = true, \
.mtu = HW_ATL_A0_MTU_JUMBO, \
.mac_regs_count = 88, \
.hw_alive_check_addr = 0x10U
const struct aq_hw_caps_s hw_atl_a0_caps_aqc100 = {
DEFAULT_A0_BOARD_BASIC_CAPABILITIES,
.media_type = AQ_HW_MEDIA_TYPE_FIBRE,
.link_speed_msk = HW_ATL_A0_RATE_5G |
HW_ATL_A0_RATE_2G5 |
HW_ATL_A0_RATE_1G |
HW_ATL_A0_RATE_100M,
};
self->not_ff_addr = 0x10U;
const struct aq_hw_caps_s hw_atl_a0_caps_aqc107 = {
DEFAULT_A0_BOARD_BASIC_CAPABILITIES,
.media_type = AQ_HW_MEDIA_TYPE_TP,
.link_speed_msk = HW_ATL_A0_RATE_10G |
HW_ATL_A0_RATE_5G |
HW_ATL_A0_RATE_2G5 |
HW_ATL_A0_RATE_1G |
HW_ATL_A0_RATE_100M,
};
err_exit:
return self;
}
const struct aq_hw_caps_s hw_atl_a0_caps_aqc108 = {
DEFAULT_A0_BOARD_BASIC_CAPABILITIES,
.media_type = AQ_HW_MEDIA_TYPE_TP,
.link_speed_msk = HW_ATL_A0_RATE_5G |
HW_ATL_A0_RATE_2G5 |
HW_ATL_A0_RATE_1G |
HW_ATL_A0_RATE_100M,
};
static void hw_atl_a0_destroy(struct aq_hw_s *self)
{
kfree(self);
}
const struct aq_hw_caps_s hw_atl_a0_caps_aqc109 = {
DEFAULT_A0_BOARD_BASIC_CAPABILITIES,
.media_type = AQ_HW_MEDIA_TYPE_TP,
.link_speed_msk = HW_ATL_A0_RATE_2G5 |
HW_ATL_A0_RATE_1G |
HW_ATL_A0_RATE_100M,
};
static int hw_atl_a0_hw_reset(struct aq_hw_s *self)
{
......@@ -83,7 +105,7 @@ static int hw_atl_a0_hw_reset(struct aq_hw_s *self)
if (err < 0)
goto err_exit;
hw_atl_utils_mpi_set(self, MPI_RESET, 0x0U);
self->aq_fw_ops->set_state(self, MPI_RESET);
err = aq_hw_err_from_flags(self);
......@@ -332,7 +354,8 @@ static int hw_atl_a0_hw_init(struct aq_hw_s *self, u8 *mac_addr)
hw_atl_a0_hw_mac_addr_set(self, mac_addr);
hw_atl_utils_mpi_set(self, MPI_INIT, aq_nic_cfg->link_speed_msk);
self->aq_fw_ops->set_link_speed(self, aq_nic_cfg->link_speed_msk);
self->aq_fw_ops->set_state(self, MPI_INIT);
hw_atl_reg_tx_dma_debug_ctl_set(self, 0x800000b8U);
hw_atl_reg_tx_dma_debug_ctl_set(self, 0x000000b8U);
......@@ -343,7 +366,7 @@ static int hw_atl_a0_hw_init(struct aq_hw_s *self, u8 *mac_addr)
/* Reset link status and read out initial hardware counters */
self->aq_link_status.mbps = 0;
hw_atl_utils_update_stats(self);
self->aq_fw_ops->update_stats(self);
err = aq_hw_err_from_flags(self);
if (err < 0)
......@@ -849,27 +872,8 @@ static int hw_atl_a0_hw_ring_rx_stop(struct aq_hw_s *self,
return aq_hw_err_from_flags(self);
}
static int hw_atl_a0_hw_set_speed(struct aq_hw_s *self, u32 speed)
{
int err = 0;
err = hw_atl_utils_mpi_set_speed(self, speed, MPI_INIT);
if (err < 0)
goto err_exit;
err_exit:
return err;
}
static const struct aq_hw_ops hw_atl_ops_ = {
.create = hw_atl_a0_create,
.destroy = hw_atl_a0_destroy,
.get_hw_caps = hw_atl_a0_get_hw_caps,
.hw_get_mac_permanent = hw_atl_utils_get_mac_permanent,
const struct aq_hw_ops hw_atl_ops_a0 = {
.hw_set_mac_address = hw_atl_a0_hw_mac_addr_set,
.hw_get_link_status = hw_atl_utils_mpi_get_link_status,
.hw_set_link_speed = hw_atl_a0_hw_set_speed,
.hw_init = hw_atl_a0_hw_init,
.hw_deinit = hw_atl_utils_hw_deinit,
.hw_set_power = hw_atl_utils_hw_set_power,
......@@ -899,21 +903,6 @@ static const struct aq_hw_ops hw_atl_ops_ = {
.hw_rss_set = hw_atl_a0_hw_rss_set,
.hw_rss_hash_set = hw_atl_a0_hw_rss_hash_set,
.hw_get_regs = hw_atl_utils_hw_get_regs,
.hw_update_stats = hw_atl_utils_update_stats,
.hw_get_hw_stats = hw_atl_utils_get_hw_stats,
.hw_get_fw_version = hw_atl_utils_get_fw_version,
};
const struct aq_hw_ops *hw_atl_a0_get_ops_by_id(struct pci_dev *pdev)
{
bool is_vid_ok = (pdev->vendor == PCI_VENDOR_ID_AQUANTIA);
bool is_did_ok = ((pdev->device == HW_ATL_DEVICE_ID_0001) ||
(pdev->device == HW_ATL_DEVICE_ID_D100) ||
(pdev->device == HW_ATL_DEVICE_ID_D107) ||
(pdev->device == HW_ATL_DEVICE_ID_D108) ||
(pdev->device == HW_ATL_DEVICE_ID_D109));
bool is_rev_ok = (pdev->revision == 1U);
return (is_vid_ok && is_did_ok && is_rev_ok) ? &hw_atl_ops_ : NULL;
}
......@@ -16,19 +16,11 @@
#include "../aq_common.h"
#ifndef PCI_VENDOR_ID_AQUANTIA
extern const struct aq_hw_caps_s hw_atl_a0_caps_aqc100;
extern const struct aq_hw_caps_s hw_atl_a0_caps_aqc107;
extern const struct aq_hw_caps_s hw_atl_a0_caps_aqc108;
extern const struct aq_hw_caps_s hw_atl_a0_caps_aqc109;
#define PCI_VENDOR_ID_AQUANTIA 0x1D6A
#define HW_ATL_DEVICE_ID_0001 0x0001
#define HW_ATL_DEVICE_ID_D100 0xD100
#define HW_ATL_DEVICE_ID_D107 0xD107
#define HW_ATL_DEVICE_ID_D108 0xD108
#define HW_ATL_DEVICE_ID_D109 0xD109
#define HW_ATL_NIC_NAME "aQuantia AQtion 5Gbit Network Adapter"
#endif
const struct aq_hw_ops *hw_atl_a0_get_ops_by_id(struct pci_dev *pdev);
extern const struct aq_hw_ops hw_atl_ops_a0;
#endif /* HW_ATL_A0_H */
......@@ -88,38 +88,4 @@
#define HW_ATL_A0_FW_VER_EXPECTED 0x01050006U
/* HW layer capabilities */
static struct aq_hw_caps_s hw_atl_a0_hw_caps_ = {
.ports = 1U,
.is_64_dma = true,
.msix_irqs = 4U,
.irq_mask = ~0U,
.vecs = HW_ATL_A0_RSS_MAX,
.tcs = HW_ATL_A0_TC_MAX,
.rxd_alignment = 1U,
.rxd_size = HW_ATL_A0_RXD_SIZE,
.rxds = 248U,
.txd_alignment = 1U,
.txd_size = HW_ATL_A0_TXD_SIZE,
.txds = 8U * 1024U,
.txhwb_alignment = 4096U,
.tx_rings = HW_ATL_A0_TX_RINGS,
.rx_rings = HW_ATL_A0_RX_RINGS,
.hw_features = NETIF_F_HW_CSUM |
NETIF_F_RXCSUM |
NETIF_F_RXHASH |
NETIF_F_SG |
NETIF_F_TSO,
.hw_priv_flags = IFF_UNICAST_FLT,
.link_speed_msk = (HW_ATL_A0_RATE_10G |
HW_ATL_A0_RATE_5G |
HW_ATL_A0_RATE_2G5 |
HW_ATL_A0_RATE_1G |
HW_ATL_A0_RATE_100M),
.flow_control = true,
.mtu = HW_ATL_A0_MTU_JUMBO,
.mac_regs_count = 88,
.fw_ver_expected = HW_ATL_A0_FW_VER_EXPECTED,
};
#endif /* HW_ATL_A0_INTERNAL_H */
......@@ -19,76 +19,82 @@
#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,
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;
}
static struct aq_hw_s *hw_atl_b0_create(struct aq_pci_func_s *aq_pci_func,
unsigned int port)
{
struct aq_hw_s *self = NULL;
self = kzalloc(sizeof(*self), GFP_KERNEL);
if (!self)
goto err_exit;
self->aq_pci_func = aq_pci_func;
#define DEFAULT_B0_BOARD_BASIC_CAPABILITIES \
.is_64_dma = true, \
.msix_irqs = 4U, \
.irq_mask = ~0U, \
.vecs = HW_ATL_B0_RSS_MAX, \
.tcs = HW_ATL_B0_TC_MAX, \
.rxd_alignment = 1U, \
.rxd_size = HW_ATL_B0_RXD_SIZE, \
.rxds = 4U * 1024U, \
.txd_alignment = 1U, \
.txd_size = HW_ATL_B0_TXD_SIZE, \
.txds = 8U * 1024U, \
.txhwb_alignment = 4096U, \
.tx_rings = HW_ATL_B0_TX_RINGS, \
.rx_rings = HW_ATL_B0_RX_RINGS, \
.hw_features = NETIF_F_HW_CSUM | \
NETIF_F_RXCSUM | \
NETIF_F_RXHASH | \
NETIF_F_SG | \
NETIF_F_TSO | \
NETIF_F_LRO, \
.hw_priv_flags = IFF_UNICAST_FLT, \
.flow_control = true, \
.mtu = HW_ATL_B0_MTU_JUMBO, \
.mac_regs_count = 88, \
.hw_alive_check_addr = 0x10U
const struct aq_hw_caps_s hw_atl_b0_caps_aqc100 = {
DEFAULT_B0_BOARD_BASIC_CAPABILITIES,
.media_type = AQ_HW_MEDIA_TYPE_FIBRE,
.link_speed_msk = HW_ATL_B0_RATE_10G |
HW_ATL_B0_RATE_5G |
HW_ATL_B0_RATE_2G5 |
HW_ATL_B0_RATE_1G |
HW_ATL_B0_RATE_100M,
};
self->not_ff_addr = 0x10U;
const struct aq_hw_caps_s hw_atl_b0_caps_aqc107 = {
DEFAULT_B0_BOARD_BASIC_CAPABILITIES,
.media_type = AQ_HW_MEDIA_TYPE_TP,
.link_speed_msk = HW_ATL_B0_RATE_10G |
HW_ATL_B0_RATE_5G |
HW_ATL_B0_RATE_2G5 |
HW_ATL_B0_RATE_1G |
HW_ATL_B0_RATE_100M,
};
err_exit:
return self;
}
const struct aq_hw_caps_s hw_atl_b0_caps_aqc108 = {
DEFAULT_B0_BOARD_BASIC_CAPABILITIES,
.media_type = AQ_HW_MEDIA_TYPE_TP,
.link_speed_msk = HW_ATL_B0_RATE_5G |
HW_ATL_B0_RATE_2G5 |
HW_ATL_B0_RATE_1G |
HW_ATL_B0_RATE_100M,
};
static void hw_atl_b0_destroy(struct aq_hw_s *self)
{
kfree(self);
}
const struct aq_hw_caps_s hw_atl_b0_caps_aqc109 = {
DEFAULT_B0_BOARD_BASIC_CAPABILITIES,
.media_type = AQ_HW_MEDIA_TYPE_TP,
.link_speed_msk = HW_ATL_B0_RATE_2G5 |
HW_ATL_B0_RATE_1G |
HW_ATL_B0_RATE_100M,
};
static int hw_atl_b0_hw_reset(struct aq_hw_s *self)
{
int err = 0;
hw_atl_glb_glb_reg_res_dis_set(self, 1U);
hw_atl_pci_pci_reg_res_dis_set(self, 0U);
hw_atl_rx_rx_reg_res_dis_set(self, 0U);
hw_atl_tx_tx_reg_res_dis_set(self, 0U);
HW_ATL_FLUSH();
hw_atl_glb_soft_res_set(self, 1);
err = hw_atl_utils_soft_reset(self);
if (err)
return err;
/* check 10 times by 1ms */
AQ_HW_WAIT_FOR(hw_atl_glb_soft_res_get(self) == 0, 1000U, 10U);
if (err < 0)
goto err_exit;
hw_atl_itr_irq_reg_res_dis_set(self, 0U);
hw_atl_itr_res_irq_set(self, 1U);
/* check 10 times by 1ms */
AQ_HW_WAIT_FOR(hw_atl_itr_res_irq_get(self) == 0, 1000U, 10U);
if (err < 0)
goto err_exit;
hw_atl_utils_mpi_set(self, MPI_RESET, 0x0U);
self->aq_fw_ops->set_state(self, MPI_RESET);
err = aq_hw_err_from_flags(self);
err_exit:
return err;
}
......@@ -379,7 +385,8 @@ static int hw_atl_b0_hw_init(struct aq_hw_s *self, u8 *mac_addr)
hw_atl_b0_hw_mac_addr_set(self, mac_addr);
hw_atl_utils_mpi_set(self, MPI_INIT, aq_nic_cfg->link_speed_msk);
self->aq_fw_ops->set_link_speed(self, aq_nic_cfg->link_speed_msk);
self->aq_fw_ops->set_state(self, MPI_INIT);
hw_atl_b0_hw_qos_set(self);
hw_atl_b0_hw_rss_set(self, &aq_nic_cfg->aq_rss);
......@@ -398,7 +405,7 @@ static int hw_atl_b0_hw_init(struct aq_hw_s *self, u8 *mac_addr)
/* Reset link status and read out initial hardware counters */
self->aq_link_status.mbps = 0;
hw_atl_utils_update_stats(self);
self->aq_fw_ops->update_stats(self);
err = aq_hw_err_from_flags(self);
if (err < 0)
......@@ -923,27 +930,8 @@ static int hw_atl_b0_hw_ring_rx_stop(struct aq_hw_s *self,
return aq_hw_err_from_flags(self);
}
static int hw_atl_b0_hw_set_speed(struct aq_hw_s *self, u32 speed)
{
int err = 0;
err = hw_atl_utils_mpi_set_speed(self, speed, MPI_INIT);
if (err < 0)
goto err_exit;
err_exit:
return err;
}
static const struct aq_hw_ops hw_atl_ops_ = {
.create = hw_atl_b0_create,
.destroy = hw_atl_b0_destroy,
.get_hw_caps = hw_atl_b0_get_hw_caps,
.hw_get_mac_permanent = hw_atl_utils_get_mac_permanent,
const struct aq_hw_ops hw_atl_ops_b0 = {
.hw_set_mac_address = hw_atl_b0_hw_mac_addr_set,
.hw_get_link_status = hw_atl_utils_mpi_get_link_status,
.hw_set_link_speed = hw_atl_b0_hw_set_speed,
.hw_init = hw_atl_b0_hw_init,
.hw_deinit = hw_atl_utils_hw_deinit,
.hw_set_power = hw_atl_utils_hw_set_power,
......@@ -973,21 +961,6 @@ static const struct aq_hw_ops hw_atl_ops_ = {
.hw_rss_set = hw_atl_b0_hw_rss_set,
.hw_rss_hash_set = hw_atl_b0_hw_rss_hash_set,
.hw_get_regs = hw_atl_utils_hw_get_regs,
.hw_update_stats = hw_atl_utils_update_stats,
.hw_get_hw_stats = hw_atl_utils_get_hw_stats,
.hw_get_fw_version = hw_atl_utils_get_fw_version,
};
const struct aq_hw_ops *hw_atl_b0_get_ops_by_id(struct pci_dev *pdev)
{
bool is_vid_ok = (pdev->vendor == PCI_VENDOR_ID_AQUANTIA);
bool is_did_ok = ((pdev->device == HW_ATL_DEVICE_ID_0001) ||
(pdev->device == HW_ATL_DEVICE_ID_D100) ||
(pdev->device == HW_ATL_DEVICE_ID_D107) ||
(pdev->device == HW_ATL_DEVICE_ID_D108) ||
(pdev->device == HW_ATL_DEVICE_ID_D109));
bool is_rev_ok = (pdev->revision == 2U);
return (is_vid_ok && is_did_ok && is_rev_ok) ? &hw_atl_ops_ : NULL;
}
......@@ -16,19 +16,27 @@
#include "../aq_common.h"
#ifndef PCI_VENDOR_ID_AQUANTIA
extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc100;
extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc107;
extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc108;
extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc109;
#define PCI_VENDOR_ID_AQUANTIA 0x1D6A
#define HW_ATL_DEVICE_ID_0001 0x0001
#define HW_ATL_DEVICE_ID_D100 0xD100
#define HW_ATL_DEVICE_ID_D107 0xD107
#define HW_ATL_DEVICE_ID_D108 0xD108
#define HW_ATL_DEVICE_ID_D109 0xD109
#define hw_atl_b0_caps_aqc111 hw_atl_b0_caps_aqc108
#define hw_atl_b0_caps_aqc112 hw_atl_b0_caps_aqc109
#define HW_ATL_NIC_NAME "aQuantia AQtion 5Gbit Network Adapter"
#define hw_atl_b0_caps_aqc100s hw_atl_b0_caps_aqc100
#define hw_atl_b0_caps_aqc107s hw_atl_b0_caps_aqc107
#define hw_atl_b0_caps_aqc108s hw_atl_b0_caps_aqc108
#define hw_atl_b0_caps_aqc109s hw_atl_b0_caps_aqc109
#endif
#define hw_atl_b0_caps_aqc111s hw_atl_b0_caps_aqc108
#define hw_atl_b0_caps_aqc112s hw_atl_b0_caps_aqc109
const struct aq_hw_ops *hw_atl_b0_get_ops_by_id(struct pci_dev *pdev);
#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
#endif /* HW_ATL_B0_H */
......@@ -143,38 +143,5 @@
#define HW_ATL_INTR_MODER_MIN 0xFF
/* HW layer capabilities */
static struct aq_hw_caps_s hw_atl_b0_hw_caps_ = {
.ports = 1U,
.is_64_dma = true,
.msix_irqs = 4U,
.irq_mask = ~0U,
.vecs = HW_ATL_B0_RSS_MAX,
.tcs = HW_ATL_B0_TC_MAX,
.rxd_alignment = 1U,
.rxd_size = HW_ATL_B0_RXD_SIZE,
.rxds = 8U * 1024U,
.txd_alignment = 1U,
.txd_size = HW_ATL_B0_TXD_SIZE,
.txds = 8U * 1024U,
.txhwb_alignment = 4096U,
.tx_rings = HW_ATL_B0_TX_RINGS,
.rx_rings = HW_ATL_B0_RX_RINGS,
.hw_features = NETIF_F_HW_CSUM |
NETIF_F_RXCSUM |
NETIF_F_RXHASH |
NETIF_F_SG |
NETIF_F_TSO |
NETIF_F_LRO,
.hw_priv_flags = IFF_UNICAST_FLT,
.link_speed_msk = (HW_ATL_B0_RATE_10G |
HW_ATL_B0_RATE_5G |
HW_ATL_B0_RATE_2G5 |
HW_ATL_B0_RATE_1G |
HW_ATL_B0_RATE_100M),
.flow_control = true,
.mtu = HW_ATL_B0_MTU_JUMBO,
.mac_regs_count = 88,
.fw_ver_expected = HW_ATL_B0_FW_VER_EXPECTED,
};
#endif /* HW_ATL_B0_INTERNAL_H */
......@@ -13,25 +13,230 @@
#include "../aq_nic.h"
#include "../aq_hw_utils.h"
#include "../aq_pci_func.h"
#include "hw_atl_utils.h"
#include "hw_atl_llh.h"
#include "hw_atl_llh_internal.h"
#include <linux/random.h>
#define HW_ATL_UCP_0X370_REG 0x0370U
#define HW_ATL_FW_SM_RAM 0x2U
#define HW_ATL_MPI_FW_VERSION 0x18
#define HW_ATL_MPI_CONTROL_ADR 0x0368U
#define HW_ATL_MPI_STATE_ADR 0x036CU
#define HW_ATL_MPI_STATE_MSK 0x00FFU
#define HW_ATL_MPI_STATE_SHIFT 0U
#define HW_ATL_MPI_SPEED_MSK 0xFFFFU
#define HW_ATL_MPI_SPEED_MSK 0xFFFF0000U
#define HW_ATL_MPI_SPEED_SHIFT 16U
static int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
u32 *p, u32 cnt)
#define HW_ATL_MPI_DAISY_CHAIN_STATUS 0x704
#define HW_ATL_MPI_BOOT_EXIT_CODE 0x388
#define HW_ATL_MAC_PHY_CONTROL 0x4000
#define HW_ATL_MAC_PHY_MPI_RESET_BIT 0x1D
#define HW_ATL_FW_VER_1X 0x01050006U
#define HW_ATL_FW_VER_2X 0x02000000U
#define HW_ATL_FW_VER_3X 0x03000000U
#define FORCE_FLASHLESS 0
static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
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);
if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X,
self->fw_ver_actual) == 0) {
*fw_ops = &aq_fw_1x_ops;
} else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_2X,
self->fw_ver_actual) == 0) {
*fw_ops = &aq_fw_2x_ops;
} else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_3X,
self->fw_ver_actual) == 0) {
*fw_ops = &aq_fw_2x_ops;
} else {
aq_pr_err("Bad FW version detected: %x\n",
self->fw_ver_actual);
return -EOPNOTSUPP;
}
self->aq_fw_ops = *fw_ops;
err = self->aq_fw_ops->init(self);
return err;
}
static int hw_atl_utils_soft_reset_flb(struct aq_hw_s *self)
{
int k = 0;
u32 gsr;
aq_hw_write_reg(self, 0x404, 0x40e1);
AQ_HW_SLEEP(50);
/* Cleanup SPI */
aq_hw_write_reg(self, 0x534, 0xA0);
aq_hw_write_reg(self, 0x100, 0x9F);
aq_hw_write_reg(self, 0x100, 0x809F);
gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000);
/* Kickstart MAC */
aq_hw_write_reg(self, 0x404, 0x80e0);
aq_hw_write_reg(self, 0x32a8, 0x0);
aq_hw_write_reg(self, 0x520, 0x1);
AQ_HW_SLEEP(10);
aq_hw_write_reg(self, 0x404, 0x180e0);
for (k = 0; k < 1000; k++) {
u32 flb_status = aq_hw_read_reg(self,
HW_ATL_MPI_DAISY_CHAIN_STATUS);
flb_status = flb_status & 0x10;
if (flb_status)
break;
AQ_HW_SLEEP(10);
}
if (k == 1000) {
aq_pr_err("MAC kickstart failed\n");
return -EIO;
}
/* FW reset */
aq_hw_write_reg(self, 0x404, 0x80e0);
AQ_HW_SLEEP(50);
aq_hw_write_reg(self, 0x3a0, 0x1);
/* Kickstart PHY - skipped */
/* Global software reset*/
hw_atl_rx_rx_reg_res_dis_set(self, 0U);
hw_atl_tx_tx_reg_res_dis_set(self, 0U);
aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL,
BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000);
for (k = 0; k < 1000; k++) {
u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
if (fw_state)
break;
AQ_HW_SLEEP(10);
}
if (k == 1000) {
aq_pr_err("FW kickstart failed\n");
return -EIO;
}
return 0;
}
static int hw_atl_utils_soft_reset_rbl(struct aq_hw_s *self)
{
u32 gsr, rbl_status;
int k;
aq_hw_write_reg(self, 0x404, 0x40e1);
aq_hw_write_reg(self, 0x3a0, 0x1);
aq_hw_write_reg(self, 0x32a8, 0x0);
/* Alter RBL status */
aq_hw_write_reg(self, 0x388, 0xDEAD);
/* Global software reset*/
hw_atl_rx_rx_reg_res_dis_set(self, 0U);
hw_atl_tx_tx_reg_res_dis_set(self, 0U);
aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL,
BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR,
(gsr & 0xFFFFBFFF) | 0x8000);
if (FORCE_FLASHLESS)
aq_hw_write_reg(self, 0x534, 0x0);
aq_hw_write_reg(self, 0x404, 0x40e0);
/* Wait for RBL boot */
for (k = 0; k < 1000; k++) {
rbl_status = aq_hw_read_reg(self, 0x388) & 0xFFFF;
if (rbl_status && rbl_status != 0xDEAD)
break;
AQ_HW_SLEEP(10);
}
if (!rbl_status || rbl_status == 0xDEAD) {
aq_pr_err("RBL Restart failed");
return -EIO;
}
/* Restore NVR */
if (FORCE_FLASHLESS)
aq_hw_write_reg(self, 0x534, 0xA0);
if (rbl_status == 0xF1A7) {
aq_pr_err("No FW detected. Dynamic FW load not implemented\n");
return -ENOTSUPP;
}
for (k = 0; k < 1000; k++) {
u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
if (fw_state)
break;
AQ_HW_SLEEP(10);
}
if (k == 1000) {
aq_pr_err("FW kickstart failed\n");
return -EIO;
}
return 0;
}
int hw_atl_utils_soft_reset(struct aq_hw_s *self)
{
int k;
u32 boot_exit_code = 0;
for (k = 0; k < 1000; ++k) {
u32 flb_status = aq_hw_read_reg(self,
HW_ATL_MPI_DAISY_CHAIN_STATUS);
boot_exit_code = aq_hw_read_reg(self,
HW_ATL_MPI_BOOT_EXIT_CODE);
if (flb_status != 0x06000000 || boot_exit_code != 0)
break;
}
if (k == 1000) {
aq_pr_err("Neither RBL nor FLB firmware started\n");
return -EOPNOTSUPP;
}
self->rbl_enabled = (boot_exit_code != 0);
if (self->rbl_enabled)
return hw_atl_utils_soft_reset_rbl(self);
else
return hw_atl_utils_soft_reset_flb(self);
}
int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
u32 *p, u32 cnt)
{
int err = 0;
......@@ -137,14 +342,6 @@ static int hw_atl_utils_init_ucp(struct aq_hw_s *self,
AQ_HW_WAIT_FOR(0U != (self->mbox_addr =
aq_hw_read_reg(self, 0x360U)), 1000U, 10U);
err = hw_atl_utils_ver_match(aq_hw_caps->fw_ver_expected,
aq_hw_read_reg(self, 0x18U));
if (err < 0)
pr_err("%s: Bad FW version detected: expected=%x, actual=%x\n",
AQ_CFG_DRV_NAME,
aq_hw_caps->fw_ver_expected,
aq_hw_read_reg(self, 0x18U));
return err;
}
......@@ -286,19 +483,19 @@ void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
err_exit:;
}
int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed,
enum hal_atl_utils_fw_state_e state)
int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed)
{
u32 ucp_0x368 = 0;
u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
ucp_0x368 = (speed << HW_ATL_MPI_SPEED_SHIFT) | state;
aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, ucp_0x368);
val = (val & HW_ATL_MPI_STATE_MSK) | (speed << HW_ATL_MPI_SPEED_SHIFT);
aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
return 0;
}
void hw_atl_utils_mpi_set(struct aq_hw_s *self,
enum hal_atl_utils_fw_state_e state, u32 speed)
enum hal_atl_utils_fw_state_e state,
u32 speed)
{
int err = 0;
u32 transaction_id = 0;
......@@ -317,11 +514,22 @@ void hw_atl_utils_mpi_set(struct aq_hw_s *self,
goto err_exit;
}
err = hw_atl_utils_mpi_set_speed(self, speed, state);
aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR,
(speed << HW_ATL_MPI_SPEED_SHIFT) | state);
err_exit:;
}
static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
enum hal_atl_utils_fw_state_e state)
{
u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
val = state | (val & HW_ATL_MPI_SPEED_MSK);
aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
return 0;
}
int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
{
u32 cp0x036C = aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR);
......@@ -369,15 +577,6 @@ int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self,
u32 l = 0U;
u32 mac_addr[2];
self->mmio = aq_pci_func_get_mmio(self->aq_pci_func);
hw_atl_utils_hw_chip_features_init(self,
&self->chip_features);
err = hw_atl_utils_mpi_create(self);
if (err < 0)
goto err_exit;
if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) {
unsigned int rnd = 0;
unsigned int ucp_0x370 = 0;
......@@ -423,7 +622,6 @@ int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self,
mac[0] = (u8)(0xFFU & h);
}
err_exit:
return err;
}
......@@ -571,7 +769,7 @@ int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,
for (i = 0; i < aq_hw_caps->mac_regs_count; i++)
regs_buff[i] = aq_hw_read_reg(self,
hw_atl_utils_hw_mac_regs[i]);
hw_atl_utils_hw_mac_regs[i]);
return 0;
}
......@@ -580,3 +778,13 @@ int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version)
*fw_version = aq_hw_read_reg(self, 0x18U);
return 0;
}
const struct aq_fw_ops aq_fw_1x_ops = {
.init = hw_atl_utils_mpi_create,
.reset = NULL,
.get_mac_permanent = hw_atl_utils_get_mac_permanent,
.set_link_speed = hw_atl_utils_mpi_set_speed,
.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,
};
......@@ -163,7 +163,7 @@ struct __packed hw_aq_atl_utils_mbox {
#define HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 0x02000000U
#define IS_CHIP_FEATURE(_F_) (HAL_ATLANTIC_UTILS_CHIP_##_F_ & \
self->chip_features)
self->chip_features)
enum hal_atl_utils_fw_state_e {
MPI_DEINIT = 0,
......@@ -180,10 +180,73 @@ enum hal_atl_utils_fw_state_e {
#define HAL_ATLANTIC_RATE_100M BIT(5)
#define HAL_ATLANTIC_RATE_INVALID BIT(6)
enum hw_atl_fw2x_rate {
FW2X_RATE_100M = 0x20,
FW2X_RATE_1G = 0x100,
FW2X_RATE_2G5 = 0x200,
FW2X_RATE_5G = 0x400,
FW2X_RATE_10G = 0x800,
};
enum hw_atl_fw2x_caps_lo {
CAPS_LO_10BASET_HD = 0x00,
CAPS_LO_10BASET_FD,
CAPS_LO_100BASETX_HD,
CAPS_LO_100BASET4_HD,
CAPS_LO_100BASET2_HD,
CAPS_LO_100BASETX_FD,
CAPS_LO_100BASET2_FD,
CAPS_LO_1000BASET_HD,
CAPS_LO_1000BASET_FD,
CAPS_LO_2P5GBASET_FD,
CAPS_LO_5GBASET_FD,
CAPS_LO_10GBASET_FD,
};
enum hw_atl_fw2x_caps_hi {
CAPS_HI_RESERVED1 = 0x00,
CAPS_HI_10BASET_EEE,
CAPS_HI_RESERVED2,
CAPS_HI_PAUSE,
CAPS_HI_ASYMMETRIC_PAUSE,
CAPS_HI_100BASETX_EEE,
CAPS_HI_RESERVED3,
CAPS_HI_RESERVED4,
CAPS_HI_1000BASET_FD_EEE,
CAPS_HI_2P5GBASET_FD_EEE,
CAPS_HI_5GBASET_FD_EEE,
CAPS_HI_10GBASET_FD_EEE,
CAPS_HI_RESERVED5,
CAPS_HI_RESERVED6,
CAPS_HI_RESERVED7,
CAPS_HI_RESERVED8,
CAPS_HI_RESERVED9,
CAPS_HI_CABLE_DIAG,
CAPS_HI_TEMPERATURE,
CAPS_HI_DOWNSHIFT,
CAPS_HI_PTP_AVB_EN,
CAPS_HI_MEDIA_DETECT,
CAPS_HI_LINK_DROP,
CAPS_HI_SLEEP_PROXY,
CAPS_HI_WOL,
CAPS_HI_MAC_STOP,
CAPS_HI_EXT_LOOPBACK,
CAPS_HI_INT_LOOPBACK,
CAPS_HI_EFUSE_AGENT,
CAPS_HI_WOL_TIMER,
CAPS_HI_STATISTICS,
CAPS_HI_TRANSACTION_ID,
};
struct aq_hw_s;
struct aq_fw_ops;
struct aq_hw_caps_s;
struct aq_hw_link_status_s;
int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops);
int hw_atl_utils_soft_reset(struct aq_hw_s *self);
void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p);
int hw_atl_utils_mpi_read_mbox(struct aq_hw_s *self,
......@@ -196,9 +259,6 @@ void hw_atl_utils_mpi_set(struct aq_hw_s *self,
enum hal_atl_utils_fw_state_e state,
u32 speed);
int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed,
enum hal_atl_utils_fw_state_e state);
int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self);
int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self,
......@@ -220,5 +280,10 @@ int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version);
int hw_atl_utils_update_stats(struct aq_hw_s *self);
struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self);
int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
u32 *p, u32 cnt);
extern const struct aq_fw_ops aq_fw_1x_ops;
extern const struct aq_fw_ops aq_fw_2x_ops;
#endif /* HW_ATL_UTILS_H */
/*
* aQuantia Corporation Network Driver
* Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*/
/* File hw_atl_utils_fw2x.c: Definition of firmware 2.x functions for
* Atlantic hardware abstraction layer.
*/
#include "../aq_hw.h"
#include "../aq_hw_utils.h"
#include "../aq_pci_func.h"
#include "../aq_ring.h"
#include "../aq_vec.h"
#include "hw_atl_utils.h"
#include "hw_atl_llh.h"
#define HW_ATL_FW2X_MPI_EFUSE_ADDR 0x364
#define HW_ATL_FW2X_MPI_MBOX_ADDR 0x360
#define HW_ATL_FW2X_MPI_CONTROL_ADDR 0x368
#define HW_ATL_FW2X_MPI_CONTROL2_ADDR 0x36C
#define HW_ATL_FW2X_MPI_STATE_ADDR 0x370
#define HW_ATL_FW2X_MPI_STATE2_ADDR 0x374
static int aq_fw2x_init(struct aq_hw_s *self)
{
int err = 0;
/* check 10 times by 1ms */
AQ_HW_WAIT_FOR(0U != (self->mbox_addr =
aq_hw_read_reg(self, HW_ATL_FW2X_MPI_MBOX_ADDR)),
1000U, 10U);
return err;
}
static enum hw_atl_fw2x_rate link_speed_mask_2fw2x_ratemask(u32 speed)
{
enum hw_atl_fw2x_rate rate = 0;
if (speed & AQ_NIC_RATE_10G)
rate |= FW2X_RATE_10G;
if (speed & AQ_NIC_RATE_5G)
rate |= FW2X_RATE_5G;
if (speed & AQ_NIC_RATE_5GSR)
rate |= FW2X_RATE_5G;
if (speed & AQ_NIC_RATE_2GS)
rate |= FW2X_RATE_2G5;
if (speed & AQ_NIC_RATE_1G)
rate |= FW2X_RATE_1G;
if (speed & AQ_NIC_RATE_100M)
rate |= FW2X_RATE_100M;
return rate;
}
static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed)
{
u32 val = link_speed_mask_2fw2x_ratemask(speed);
aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, val);
return 0;
}
static int aq_fw2x_set_state(struct aq_hw_s *self,
enum hal_atl_utils_fw_state_e state)
{
/* No explicit state in 2x fw */
return 0;
}
static int aq_fw2x_update_link_status(struct aq_hw_s *self)
{
u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR);
u32 speed = mpi_state & (FW2X_RATE_100M | FW2X_RATE_1G |
FW2X_RATE_2G5 | FW2X_RATE_5G | FW2X_RATE_10G);
struct aq_hw_link_status_s *link_status = &self->aq_link_status;
if (speed) {
if (speed & FW2X_RATE_10G)
link_status->mbps = 10000;
else if (speed & FW2X_RATE_5G)
link_status->mbps = 5000;
else if (speed & FW2X_RATE_2G5)
link_status->mbps = 2500;
else if (speed & FW2X_RATE_1G)
link_status->mbps = 1000;
else if (speed & FW2X_RATE_100M)
link_status->mbps = 100;
else
link_status->mbps = 10000;
} else {
link_status->mbps = 0;
}
return 0;
}
int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
{
int err = 0;
u32 h = 0U;
u32 l = 0U;
u32 mac_addr[2] = { 0 };
u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR);
if (efuse_addr != 0) {
err = hw_atl_utils_fw_downld_dwords(self,
efuse_addr + (40U * 4U),
mac_addr,
ARRAY_SIZE(mac_addr));
if (err)
return err;
mac_addr[0] = __swab32(mac_addr[0]);
mac_addr[1] = __swab32(mac_addr[1]);
}
ether_addr_copy(mac, (u8 *)mac_addr);
if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
unsigned int rnd = 0;
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 err;
}
static int aq_fw2x_update_stats(struct aq_hw_s *self)
{
int err = 0;
u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS);
/* Toggle statistics bit for FW to update */
mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS);
aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
/* Wait FW to report back */
AQ_HW_WAIT_FOR(orig_stats_val !=
(aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) &
BIT(CAPS_HI_STATISTICS)),
1U, 10000U);
if (err)
return err;
return hw_atl_utils_update_stats(self);
}
const struct aq_fw_ops aq_fw_2x_ops = {
.init = aq_fw2x_init,
.reset = NULL,
.get_mac_permanent = aq_fw2x_get_mac_permanent,
.set_link_speed = aq_fw2x_set_link_speed,
.set_state = aq_fw2x_set_state,
.update_link_status = aq_fw2x_update_link_status,
.update_stats = aq_fw2x_update_stats,
};
......@@ -10,9 +10,9 @@
#ifndef VER_H
#define VER_H
#define NIC_MAJOR_DRIVER_VERSION 1
#define NIC_MINOR_DRIVER_VERSION 6
#define NIC_BUILD_DRIVER_VERSION 13
#define NIC_MAJOR_DRIVER_VERSION 2
#define NIC_MINOR_DRIVER_VERSION 0
#define NIC_BUILD_DRIVER_VERSION 2
#define NIC_REVISION_DRIVER_VERSION 0
#define AQ_CFG_DRV_VERSION_SUFFIX "-kern"
......
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