mirror of
https://github.com/torvalds/linux.git
synced 2024-12-31 23:31:29 +00:00
Merge branch 'aquantia-various-ethtool-ops-implementation'
Igor Russkikh says: ==================== net: aquantia: various ethtool ops implementation In this patchset Anton Mikaev and I added some useful ethtool operations: - ring size changes - link renegotioation - flow control management The patch also improves init/deinit sequence. V3 changes: - After review and analysis it is clear that rtnl lock (which is captured by default on ethtool ops) is enough to secure possible overlapping of dev open/close. Thus, just dropping internal mutex. V2 changes: - using mutex to secure simultaneous dev close/open - using state var to store/restore dev state ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
44a4c4698e
@ -11,6 +11,7 @@
|
||||
|
||||
#include "aq_ethtool.h"
|
||||
#include "aq_nic.h"
|
||||
#include "aq_vec.h"
|
||||
|
||||
static void aq_ethtool_get_regs(struct net_device *ndev,
|
||||
struct ethtool_regs *regs, void *p)
|
||||
@ -284,6 +285,117 @@ static int aq_ethtool_set_coalesce(struct net_device *ndev,
|
||||
return aq_nic_update_interrupt_moderation_settings(aq_nic);
|
||||
}
|
||||
|
||||
static int aq_ethtool_nway_reset(struct net_device *ndev)
|
||||
{
|
||||
struct aq_nic_s *aq_nic = netdev_priv(ndev);
|
||||
|
||||
if (unlikely(!aq_nic->aq_fw_ops->renegotiate))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (netif_running(ndev))
|
||||
return aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void aq_ethtool_get_pauseparam(struct net_device *ndev,
|
||||
struct ethtool_pauseparam *pause)
|
||||
{
|
||||
struct aq_nic_s *aq_nic = netdev_priv(ndev);
|
||||
|
||||
pause->autoneg = 0;
|
||||
|
||||
if (aq_nic->aq_hw->aq_nic_cfg->flow_control & AQ_NIC_FC_RX)
|
||||
pause->rx_pause = 1;
|
||||
if (aq_nic->aq_hw->aq_nic_cfg->flow_control & AQ_NIC_FC_TX)
|
||||
pause->tx_pause = 1;
|
||||
}
|
||||
|
||||
static int aq_ethtool_set_pauseparam(struct net_device *ndev,
|
||||
struct ethtool_pauseparam *pause)
|
||||
{
|
||||
struct aq_nic_s *aq_nic = netdev_priv(ndev);
|
||||
int err = 0;
|
||||
|
||||
if (!aq_nic->aq_fw_ops->set_flow_control)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (pause->autoneg == AUTONEG_ENABLE)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (pause->rx_pause)
|
||||
aq_nic->aq_hw->aq_nic_cfg->flow_control |= AQ_NIC_FC_RX;
|
||||
else
|
||||
aq_nic->aq_hw->aq_nic_cfg->flow_control &= ~AQ_NIC_FC_RX;
|
||||
|
||||
if (pause->tx_pause)
|
||||
aq_nic->aq_hw->aq_nic_cfg->flow_control |= AQ_NIC_FC_TX;
|
||||
else
|
||||
aq_nic->aq_hw->aq_nic_cfg->flow_control &= ~AQ_NIC_FC_TX;
|
||||
|
||||
err = aq_nic->aq_fw_ops->set_flow_control(aq_nic->aq_hw);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void aq_get_ringparam(struct net_device *ndev,
|
||||
struct ethtool_ringparam *ring)
|
||||
{
|
||||
struct aq_nic_s *aq_nic = netdev_priv(ndev);
|
||||
struct aq_nic_cfg_s *aq_nic_cfg = aq_nic_get_cfg(aq_nic);
|
||||
|
||||
ring->rx_pending = aq_nic_cfg->rxds;
|
||||
ring->tx_pending = aq_nic_cfg->txds;
|
||||
|
||||
ring->rx_max_pending = aq_nic_cfg->aq_hw_caps->rxds_max;
|
||||
ring->tx_max_pending = aq_nic_cfg->aq_hw_caps->txds_max;
|
||||
}
|
||||
|
||||
static int aq_set_ringparam(struct net_device *ndev,
|
||||
struct ethtool_ringparam *ring)
|
||||
{
|
||||
int err = 0;
|
||||
bool ndev_running = false;
|
||||
struct aq_nic_s *aq_nic = netdev_priv(ndev);
|
||||
struct aq_nic_cfg_s *aq_nic_cfg = aq_nic_get_cfg(aq_nic);
|
||||
const struct aq_hw_caps_s *hw_caps = aq_nic_cfg->aq_hw_caps;
|
||||
|
||||
if (ring->rx_mini_pending || ring->rx_jumbo_pending) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
if (netif_running(ndev)) {
|
||||
ndev_running = true;
|
||||
dev_close(ndev);
|
||||
}
|
||||
|
||||
aq_nic_free_vectors(aq_nic);
|
||||
|
||||
aq_nic_cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min);
|
||||
aq_nic_cfg->rxds = min(aq_nic_cfg->rxds, hw_caps->rxds_max);
|
||||
aq_nic_cfg->rxds = ALIGN(aq_nic_cfg->rxds, AQ_HW_RXD_MULTIPLE);
|
||||
|
||||
aq_nic_cfg->txds = max(ring->tx_pending, hw_caps->txds_min);
|
||||
aq_nic_cfg->txds = min(aq_nic_cfg->txds, hw_caps->txds_max);
|
||||
aq_nic_cfg->txds = ALIGN(aq_nic_cfg->txds, AQ_HW_TXD_MULTIPLE);
|
||||
|
||||
for (aq_nic->aq_vecs = 0; aq_nic->aq_vecs < aq_nic_cfg->vecs;
|
||||
aq_nic->aq_vecs++) {
|
||||
aq_nic->aq_vec[aq_nic->aq_vecs] =
|
||||
aq_vec_alloc(aq_nic, aq_nic->aq_vecs, aq_nic_cfg);
|
||||
if (unlikely(!aq_nic->aq_vec[aq_nic->aq_vecs])) {
|
||||
err = -ENOMEM;
|
||||
goto err_exit;
|
||||
}
|
||||
}
|
||||
if (ndev_running)
|
||||
err = dev_open(ndev);
|
||||
|
||||
err_exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
const struct ethtool_ops aq_ethtool_ops = {
|
||||
.get_link = aq_ethtool_get_link,
|
||||
.get_regs_len = aq_ethtool_get_regs_len,
|
||||
@ -291,6 +403,11 @@ const struct ethtool_ops aq_ethtool_ops = {
|
||||
.get_drvinfo = aq_ethtool_get_drvinfo,
|
||||
.get_strings = aq_ethtool_get_strings,
|
||||
.get_rxfh_indir_size = aq_ethtool_get_rss_indir_size,
|
||||
.nway_reset = aq_ethtool_nway_reset,
|
||||
.get_ringparam = aq_get_ringparam,
|
||||
.set_ringparam = aq_set_ringparam,
|
||||
.get_pauseparam = aq_ethtool_get_pauseparam,
|
||||
.set_pauseparam = aq_ethtool_set_pauseparam,
|
||||
.get_rxfh_key_size = aq_ethtool_get_rss_key_size,
|
||||
.get_rxfh = aq_ethtool_get_rss,
|
||||
.get_rxnfc = aq_ethtool_get_rxnfc,
|
||||
|
@ -24,8 +24,10 @@ struct aq_hw_caps_s {
|
||||
u64 link_speed_msk;
|
||||
unsigned int hw_priv_flags;
|
||||
u32 media_type;
|
||||
u32 rxds;
|
||||
u32 txds;
|
||||
u32 rxds_max;
|
||||
u32 txds_max;
|
||||
u32 rxds_min;
|
||||
u32 txds_min;
|
||||
u32 txhwb_alignment;
|
||||
u32 irq_mask;
|
||||
u32 vecs;
|
||||
@ -98,6 +100,9 @@ struct aq_stats_s {
|
||||
#define AQ_HW_MEDIA_TYPE_TP 1U
|
||||
#define AQ_HW_MEDIA_TYPE_FIBRE 2U
|
||||
|
||||
#define AQ_HW_TXD_MULTIPLE 8U
|
||||
#define AQ_HW_RXD_MULTIPLE 8U
|
||||
|
||||
struct aq_hw_s {
|
||||
atomic_t flags;
|
||||
u8 rbl_enabled:1;
|
||||
@ -197,25 +202,30 @@ struct aq_hw_ops {
|
||||
|
||||
int (*hw_get_fw_version)(struct aq_hw_s *self, u32 *fw_version);
|
||||
|
||||
int (*hw_deinit)(struct aq_hw_s *self);
|
||||
|
||||
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 (*deinit)(struct aq_hw_s *self);
|
||||
|
||||
int (*reset)(struct aq_hw_s *self);
|
||||
|
||||
int (*renegotiate)(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 (*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);
|
||||
|
||||
int (*set_flow_control)(struct aq_hw_s *self);
|
||||
};
|
||||
|
||||
#endif /* AQ_HW_H */
|
||||
|
@ -89,8 +89,8 @@ void aq_nic_cfg_start(struct aq_nic_s *self)
|
||||
aq_nic_rss_init(self, cfg->num_rss_queues);
|
||||
|
||||
/*descriptors */
|
||||
cfg->rxds = min(cfg->aq_hw_caps->rxds, AQ_CFG_RXDS_DEF);
|
||||
cfg->txds = min(cfg->aq_hw_caps->txds, AQ_CFG_TXDS_DEF);
|
||||
cfg->rxds = min(cfg->aq_hw_caps->rxds_max, AQ_CFG_RXDS_DEF);
|
||||
cfg->txds = min(cfg->aq_hw_caps->txds_max, AQ_CFG_TXDS_DEF);
|
||||
|
||||
/*rss rings */
|
||||
cfg->vecs = min(cfg->aq_hw_caps->vecs, AQ_CFG_VECS_DEF);
|
||||
@ -761,10 +761,14 @@ 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.flow_control)
|
||||
if (self->aq_nic_cfg.flow_control & AQ_NIC_FC_RX)
|
||||
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
||||
Pause);
|
||||
|
||||
if (self->aq_nic_cfg.flow_control & AQ_NIC_FC_TX)
|
||||
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
||||
Asym_Pause);
|
||||
|
||||
if (self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_FIBRE)
|
||||
ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);
|
||||
else
|
||||
@ -879,7 +883,7 @@ void aq_nic_deinit(struct aq_nic_s *self)
|
||||
aq_vec_deinit(aq_vec);
|
||||
|
||||
if (self->power_state == AQ_HW_POWER_STATE_D0) {
|
||||
(void)self->aq_hw_ops->hw_deinit(self->aq_hw);
|
||||
(void)self->aq_fw_ops->deinit(self->aq_hw);
|
||||
} else {
|
||||
(void)self->aq_hw_ops->hw_set_power(self->aq_hw,
|
||||
self->power_state);
|
||||
|
@ -19,29 +19,31 @@
|
||||
#include "hw_atl_a0_internal.h"
|
||||
|
||||
#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, \
|
||||
.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_max = HW_ATL_A0_MAX_RXD, \
|
||||
.rxds_min = HW_ATL_A0_MIN_RXD, \
|
||||
.txd_alignment = 1U, \
|
||||
.txd_size = HW_ATL_A0_TXD_SIZE, \
|
||||
.txds_max = HW_ATL_A0_MAX_TXD, \
|
||||
.txds_min = HW_ATL_A0_MIN_RXD, \
|
||||
.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, \
|
||||
.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 = {
|
||||
@ -875,7 +877,6 @@ static int hw_atl_a0_hw_ring_rx_stop(struct aq_hw_s *self,
|
||||
const struct aq_hw_ops hw_atl_ops_a0 = {
|
||||
.hw_set_mac_address = hw_atl_a0_hw_mac_addr_set,
|
||||
.hw_init = hw_atl_a0_hw_init,
|
||||
.hw_deinit = hw_atl_utils_hw_deinit,
|
||||
.hw_set_power = hw_atl_utils_hw_set_power,
|
||||
.hw_reset = hw_atl_a0_hw_reset,
|
||||
.hw_start = hw_atl_a0_hw_start,
|
||||
|
@ -88,4 +88,12 @@
|
||||
|
||||
#define HW_ATL_A0_FW_VER_EXPECTED 0x01050006U
|
||||
|
||||
#define HW_ATL_A0_MIN_RXD \
|
||||
(ALIGN(AQ_CFG_SKB_FRAGS_MAX + 1U, AQ_HW_RXD_MULTIPLE))
|
||||
#define HW_ATL_A0_MIN_TXD \
|
||||
(ALIGN(AQ_CFG_SKB_FRAGS_MAX + 1U, AQ_HW_TXD_MULTIPLE))
|
||||
|
||||
#define HW_ATL_A0_MAX_RXD 8184U
|
||||
#define HW_ATL_A0_MAX_TXD 8184U
|
||||
|
||||
#endif /* HW_ATL_A0_INTERNAL_H */
|
||||
|
@ -20,30 +20,32 @@
|
||||
#include "hw_atl_llh_internal.h"
|
||||
|
||||
#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, \
|
||||
.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_max = HW_ATL_B0_MAX_RXD, \
|
||||
.rxds_min = HW_ATL_B0_MIN_RXD, \
|
||||
.txd_alignment = 1U, \
|
||||
.txd_size = HW_ATL_B0_TXD_SIZE, \
|
||||
.txds_max = HW_ATL_B0_MAX_TXD, \
|
||||
.txds_min = HW_ATL_B0_MIN_TXD, \
|
||||
.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 = {
|
||||
@ -933,7 +935,6 @@ static int hw_atl_b0_hw_ring_rx_stop(struct aq_hw_s *self,
|
||||
const struct aq_hw_ops hw_atl_ops_b0 = {
|
||||
.hw_set_mac_address = hw_atl_b0_hw_mac_addr_set,
|
||||
.hw_init = hw_atl_b0_hw_init,
|
||||
.hw_deinit = hw_atl_utils_hw_deinit,
|
||||
.hw_set_power = hw_atl_utils_hw_set_power,
|
||||
.hw_reset = hw_atl_b0_hw_reset,
|
||||
.hw_start = hw_atl_b0_hw_start,
|
||||
|
@ -142,6 +142,14 @@
|
||||
#define HW_ATL_INTR_MODER_MAX 0x1FF
|
||||
#define HW_ATL_INTR_MODER_MIN 0xFF
|
||||
|
||||
#define HW_ATL_B0_MIN_RXD \
|
||||
(ALIGN(AQ_CFG_SKB_FRAGS_MAX + 1U, AQ_HW_RXD_MULTIPLE))
|
||||
#define HW_ATL_B0_MIN_TXD \
|
||||
(ALIGN(AQ_CFG_SKB_FRAGS_MAX + 1U, AQ_HW_TXD_MULTIPLE))
|
||||
|
||||
#define HW_ATL_B0_MAX_RXD 8184U
|
||||
#define HW_ATL_B0_MAX_TXD 8184U
|
||||
|
||||
/* HW layer capabilities */
|
||||
|
||||
#endif /* HW_ATL_B0_INTERNAL_H */
|
||||
|
@ -30,10 +30,11 @@
|
||||
#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 0xFFFF0000U
|
||||
#define HW_ATL_MPI_SPEED_SHIFT 16U
|
||||
#define HW_ATL_MPI_STATE_MSK 0x00FFU
|
||||
#define HW_ATL_MPI_STATE_SHIFT 0U
|
||||
#define HW_ATL_MPI_SPEED_MSK 0x00FF0000U
|
||||
#define HW_ATL_MPI_SPEED_SHIFT 16U
|
||||
#define HW_ATL_MPI_DIRTY_WAKE_MSK 0x02000000U
|
||||
|
||||
#define HW_ATL_MPI_DAISY_CHAIN_STATUS 0x704
|
||||
#define HW_ATL_MPI_BOOT_EXIT_CODE 0x388
|
||||
@ -521,23 +522,24 @@ void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
|
||||
err_exit:;
|
||||
}
|
||||
|
||||
static int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed)
|
||||
int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed)
|
||||
{
|
||||
u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
|
||||
|
||||
val = (val & HW_ATL_MPI_STATE_MSK) | (speed << HW_ATL_MPI_SPEED_SHIFT);
|
||||
val = val & ~HW_ATL_MPI_SPEED_MSK;
|
||||
val |= 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)
|
||||
int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
|
||||
enum hal_atl_utils_fw_state_e state)
|
||||
{
|
||||
int err = 0;
|
||||
u32 transaction_id = 0;
|
||||
struct hw_aq_atl_utils_mbox_header mbox;
|
||||
u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
|
||||
|
||||
if (state == MPI_RESET) {
|
||||
hw_atl_utils_mpi_read_mbox(self, &mbox);
|
||||
@ -551,21 +553,21 @@ void hw_atl_utils_mpi_set(struct aq_hw_s *self,
|
||||
if (err < 0)
|
||||
goto err_exit;
|
||||
}
|
||||
/* On interface DEINIT we disable DW (raise bit)
|
||||
* Otherwise enable DW (clear bit)
|
||||
*/
|
||||
if (state == MPI_DEINIT || state == MPI_POWER)
|
||||
val |= HW_ATL_MPI_DIRTY_WAKE_MSK;
|
||||
else
|
||||
val &= ~HW_ATL_MPI_DIRTY_WAKE_MSK;
|
||||
|
||||
aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR,
|
||||
(speed << HW_ATL_MPI_SPEED_SHIFT) | state);
|
||||
/* Set new state bits */
|
||||
val = val & ~HW_ATL_MPI_STATE_MSK;
|
||||
val |= state & HW_ATL_MPI_STATE_MSK;
|
||||
|
||||
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;
|
||||
err_exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
|
||||
@ -721,16 +723,18 @@ void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p)
|
||||
*p = chip_features;
|
||||
}
|
||||
|
||||
int hw_atl_utils_hw_deinit(struct aq_hw_s *self)
|
||||
static int hw_atl_fw1x_deinit(struct aq_hw_s *self)
|
||||
{
|
||||
hw_atl_utils_mpi_set(self, MPI_DEINIT, 0x0U);
|
||||
hw_atl_utils_mpi_set_speed(self, 0);
|
||||
hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hw_atl_utils_hw_set_power(struct aq_hw_s *self,
|
||||
unsigned int power_state)
|
||||
{
|
||||
hw_atl_utils_mpi_set(self, MPI_POWER, 0x0U);
|
||||
hw_atl_utils_mpi_set_speed(self, 0);
|
||||
hw_atl_utils_mpi_set_state(self, MPI_POWER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -823,10 +827,12 @@ int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version)
|
||||
|
||||
const struct aq_fw_ops aq_fw_1x_ops = {
|
||||
.init = hw_atl_utils_mpi_create,
|
||||
.deinit = hw_atl_fw1x_deinit,
|
||||
.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,
|
||||
.set_flow_control = NULL,
|
||||
};
|
||||
|
@ -239,6 +239,41 @@ enum hw_atl_fw2x_caps_hi {
|
||||
CAPS_HI_TRANSACTION_ID,
|
||||
};
|
||||
|
||||
enum hw_atl_fw2x_ctrl {
|
||||
CTRL_RESERVED1 = 0x00,
|
||||
CTRL_RESERVED2,
|
||||
CTRL_RESERVED3,
|
||||
CTRL_PAUSE,
|
||||
CTRL_ASYMMETRIC_PAUSE,
|
||||
CTRL_RESERVED4,
|
||||
CTRL_RESERVED5,
|
||||
CTRL_RESERVED6,
|
||||
CTRL_1GBASET_FD_EEE,
|
||||
CTRL_2P5GBASET_FD_EEE,
|
||||
CTRL_5GBASET_FD_EEE,
|
||||
CTRL_10GBASET_FD_EEE,
|
||||
CTRL_THERMAL_SHUTDOWN,
|
||||
CTRL_PHY_LOGS,
|
||||
CTRL_EEE_AUTO_DISABLE,
|
||||
CTRL_PFC,
|
||||
CTRL_WAKE_ON_LINK,
|
||||
CTRL_CABLE_DIAG,
|
||||
CTRL_TEMPERATURE,
|
||||
CTRL_DOWNSHIFT,
|
||||
CTRL_PTP_AVB,
|
||||
CTRL_RESERVED7,
|
||||
CTRL_LINK_DROP,
|
||||
CTRL_SLEEP_PROXY,
|
||||
CTRL_WOL,
|
||||
CTRL_MAC_STOP,
|
||||
CTRL_EXT_LOOPBACK,
|
||||
CTRL_INT_LOOPBACK,
|
||||
CTRL_RESERVED8,
|
||||
CTRL_WOL_TIMER,
|
||||
CTRL_STATISTICS,
|
||||
CTRL_FORCE_RECONNECT,
|
||||
};
|
||||
|
||||
struct aq_hw_s;
|
||||
struct aq_fw_ops;
|
||||
struct aq_hw_caps_s;
|
||||
|
@ -28,6 +28,10 @@
|
||||
#define HW_ATL_FW2X_MPI_STATE_ADDR 0x370
|
||||
#define HW_ATL_FW2X_MPI_STATE2_ADDR 0x374
|
||||
|
||||
static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed);
|
||||
static int aq_fw2x_set_state(struct aq_hw_s *self,
|
||||
enum hal_atl_utils_fw_state_e state);
|
||||
|
||||
static int aq_fw2x_init(struct aq_hw_s *self)
|
||||
{
|
||||
int err = 0;
|
||||
@ -39,6 +43,16 @@ static int aq_fw2x_init(struct aq_hw_s *self)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int aq_fw2x_deinit(struct aq_hw_s *self)
|
||||
{
|
||||
int err = aq_fw2x_set_link_speed(self, 0);
|
||||
|
||||
if (!err)
|
||||
err = aq_fw2x_set_state(self, MPI_DEINIT);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static enum hw_atl_fw2x_rate link_speed_mask_2fw2x_ratemask(u32 speed)
|
||||
{
|
||||
enum hw_atl_fw2x_rate rate = 0;
|
||||
@ -73,10 +87,38 @@ static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void aq_fw2x_set_mpi_flow_control(struct aq_hw_s *self, u32 *mpi_state)
|
||||
{
|
||||
if (self->aq_nic_cfg->flow_control & AQ_NIC_FC_RX)
|
||||
*mpi_state |= BIT(CAPS_HI_PAUSE);
|
||||
else
|
||||
*mpi_state &= ~BIT(CAPS_HI_PAUSE);
|
||||
|
||||
if (self->aq_nic_cfg->flow_control & AQ_NIC_FC_TX)
|
||||
*mpi_state |= BIT(CAPS_HI_ASYMMETRIC_PAUSE);
|
||||
else
|
||||
*mpi_state &= ~BIT(CAPS_HI_ASYMMETRIC_PAUSE);
|
||||
}
|
||||
|
||||
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 */
|
||||
u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
|
||||
|
||||
switch (state) {
|
||||
case MPI_INIT:
|
||||
mpi_state &= ~BIT(CAPS_HI_LINK_DROP);
|
||||
aq_fw2x_set_mpi_flow_control(self, &mpi_state);
|
||||
break;
|
||||
case MPI_DEINIT:
|
||||
mpi_state |= BIT(CAPS_HI_LINK_DROP);
|
||||
break;
|
||||
case MPI_RESET:
|
||||
case MPI_POWER:
|
||||
/* No actions */
|
||||
break;
|
||||
}
|
||||
aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -173,12 +215,37 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
|
||||
return hw_atl_utils_update_stats(self);
|
||||
}
|
||||
|
||||
static int aq_fw2x_renegotiate(struct aq_hw_s *self)
|
||||
{
|
||||
u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
|
||||
|
||||
mpi_opts |= BIT(CTRL_FORCE_RECONNECT);
|
||||
|
||||
aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aq_fw2x_set_flow_control(struct aq_hw_s *self)
|
||||
{
|
||||
u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
|
||||
|
||||
aq_fw2x_set_mpi_flow_control(self, &mpi_state);
|
||||
|
||||
aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct aq_fw_ops aq_fw_2x_ops = {
|
||||
.init = aq_fw2x_init,
|
||||
.deinit = aq_fw2x_deinit,
|
||||
.reset = NULL,
|
||||
.renegotiate = aq_fw2x_renegotiate,
|
||||
.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,
|
||||
.set_flow_control = aq_fw2x_set_flow_control,
|
||||
};
|
||||
|
@ -12,8 +12,8 @@
|
||||
|
||||
#define NIC_MAJOR_DRIVER_VERSION 2
|
||||
#define NIC_MINOR_DRIVER_VERSION 0
|
||||
#define NIC_BUILD_DRIVER_VERSION 2
|
||||
#define NIC_REVISION_DRIVER_VERSION 1
|
||||
#define NIC_BUILD_DRIVER_VERSION 3
|
||||
#define NIC_REVISION_DRIVER_VERSION 0
|
||||
|
||||
#define AQ_CFG_DRV_VERSION_SUFFIX "-kern"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user