Merge "atlantic forwarding driver v1.1.15"

This commit is contained in:
qctecmdr 2021-02-26 06:40:49 -08:00 • committed by Gerrit - the friendly Code Review server
commit 695b140e10
16 changed files with 365 additions and 68 deletions

View file

@ -214,7 +214,7 @@ static int __atl2_fw_wait_init(struct atl_hw *hw)
"pauseQuanta invalid size");
BUILD_BUG_ON_MSG(sizeof(struct cable_diag_control_s) != 0x4,
"cableDiagControl invalid size");
BUILD_BUG_ON_MSG(sizeof(struct statistics_s) != 0x70,
BUILD_BUG_ON_MSG(sizeof(struct statistics_s) != 0x74,
"statistics_s invalid size");
@ -901,19 +901,34 @@ static int atl2_fw_set_mediadetect(struct atl_hw *hw, bool on)
return atl2_shared_buffer_finish_ack(hw);
}
static int atl2_fw_set_downshift(struct atl_hw *hw, bool on)
{
struct link_options_s link_options;
atl2_shared_buffer_get(hw, link_options, link_options);
link_options.downshift = on;
atl2_shared_buffer_write(hw, link_options, link_options);
return atl2_shared_buffer_finish_ack(hw);
}
static int atl2_fw_unsupported(struct atl_hw *hw)
{
return -EOPNOTSUPP;
}
int atl2_get_fw_version(struct atl_hw *hw, u32 *fw_version)
int atl2_get_fw_version(struct atl_hw *hw)
{
struct mac_version_t mac_version;
struct atl_mcp *mcp = &hw->mcp;
struct version_s version;
atl2_shared_buffer_read(hw, version.mac, mac_version);
*fw_version = mac_version.major << 24 | mac_version.minor << 16 |
mac_version.build;
atl2_shared_buffer_read_safe(hw, version, &version);
mcp->fw_rev = version.bundle.major << 24 | version.bundle.minor << 16 |
version.bundle.build;
mcp->interface_ver = version.drv_iface_ver;
return 0;
}
@ -927,6 +942,7 @@ static struct atl_fw_ops atl2_fw_ops = {
.set_default_link = atl2_fw_set_default_link,
.get_phy_temperature = atl2_fw_get_phy_temperature,
.set_mediadetect = atl2_fw_set_mediadetect,
.set_downshift = atl2_fw_set_downshift,
.send_macsec_req = (void *)atl2_fw_unsupported,
.set_pad_stripping = atl2_fw_set_pad_stripping,
.get_mac_addr = atl2_fw_get_mac_addr,
@ -943,7 +959,7 @@ int atl2_fw_init(struct atl_hw *hw)
struct atl_mcp *mcp = &hw->mcp;
int ret;
atl2_get_fw_version(hw, &mcp->fw_rev);
atl2_get_fw_version(hw);
mcp->ops = &atl2_fw_ops;
atl_dev_dbg("Detect ATL2FW %x\n", mcp->fw_rev);

View file

@ -239,7 +239,8 @@ struct version_s {
uint32_t minor:8;
uint32_t build:16;
} phy;
uint32_t rsvd:32;
uint32_t drv_iface_ver:4;
uint32_t rsvd:28;
};
struct link_status_s {
@ -444,7 +445,7 @@ struct phy_fw_load_status_s {
uint32_t rsvd2:2;
};
struct statistics_s {
struct statistics_a0_s {
struct {
uint32_t link_up;
uint32_t link_down;
@ -477,6 +478,33 @@ struct statistics_s {
uint32_t reserve_fw_gap;
};
struct statistics_b0_s {
uint64_t rx_good_octets;
uint64_t rx_pause_frames;
uint64_t rx_good_frames;
uint64_t rx_errors;
uint64_t rx_unicast_frames;
uint64_t rx_multicast_frames;
uint64_t rx_broadcast_frames;
uint64_t tx_good_octets;
uint64_t tx_pause_frames;
uint64_t tx_good_frames;
uint64_t tx_errors;
uint64_t tx_unicast_frames;
uint64_t tx_multicast_frames;
uint64_t tx_broadcast_frames;
uint32_t main_loop_cycles;
};
struct statistics_s {
union {
struct statistics_a0_s a0;
struct statistics_b0_s b0;
};
};
struct filter_caps_s {
uint8_t l2_filters_base_index:6;
uint8_t flexible_filter_mask:2;
@ -590,7 +618,6 @@ struct fw_interface_out {
struct core_dump_s core_dump;
uint32_t rsvd11:32;
struct statistics_s stats;
uint32_t rsvd12:32;
struct filter_caps_s filter_caps;
struct device_caps_s device_caps;
uint32_t rsvd13:32;
@ -627,6 +654,9 @@ struct fw_iti_hdr {
#define ATL2_HOST_MODE_LOW_POWER 3
#define ATL2_HOST_MODE_SHUTDOWN 4
#define ATL2_FW_INTERFACE_A0 0
#define ATL2_FW_INTERFACE_B0 1
#define ATL2_FW_CABLE_STATUS_OPEN_CIRCUIT 7
#define ATL2_FW_CABLE_STATUS_HIGH_MISMATCH 6
#define ATL2_FW_CABLE_STATUS_LOW_MISMATCH 5
@ -683,7 +713,6 @@ enum ATL2_WAKE_REASON {
};
int atl2_fw_init(struct atl_hw *hw);
int atl2_get_fw_version(struct atl_hw *hw, u32 *fw_version);
int atl2_fw_set_filter_policy(struct atl_hw *hw, bool promisc, bool allmulti);

View file

@ -20,7 +20,7 @@
#include <linux/netdevice.h>
#include <linux/moduleparam.h>
#define ATL_VERSION "1.1.11"
#define ATL_VERSION "1.1.15"
struct atl_nic;
@ -315,6 +315,7 @@ enum atl_priv_flags {
ATL_PF_STATS_RESET,
ATL_PF_STRIP_PAD,
ATL_PF_MEDIA_DETECT,
ATL_PF_DOWNSHIFT,
};
enum atl_priv_flag_bits {
@ -339,9 +340,11 @@ enum atl_priv_flag_bits {
ATL_DEF_PF_BIT(STRIP_PAD),
ATL_DEF_PF_BIT(MEDIA_DETECT),
ATL_DEF_PF_BIT(DOWNSHIFT),
ATL_PF_RW_MASK = ATL_PF_LPB_MASK | ATL_PF_BIT(STATS_RESET) |
ATL_PF_BIT(STRIP_PAD) | ATL_PF_BIT(MEDIA_DETECT),
ATL_PF_BIT(STRIP_PAD) | ATL_PF_BIT(MEDIA_DETECT) |
ATL_PF_BIT(DOWNSHIFT),
ATL_PF_RO_MASK = ATL_PF_LPI_MASK,
};
@ -397,6 +400,7 @@ void atl_clear_tdm_cache(struct atl_nic *nic);
int atl_alloc_rings(struct atl_nic *nic);
void atl_free_rings(struct atl_nic *nic);
irqreturn_t atl_ring_irq(int irq, void *priv);
irqreturn_t atl_ptp_irq(int irq, void *private);
void atl_ring_work(struct work_struct *work);
void atl_start_hw_global(struct atl_nic *nic);
int atl_intr_init(struct atl_nic *nic);

View file

@ -47,6 +47,21 @@
/* introduced in commit 72bb68721f80a1441e871b6afc9ab0b3793d5031 */
#define ATL_HAVE_IPV6_NTUPLE
#if RHEL_RELEASE_CODE == RHEL_RELEASE_VERSION(7, 3)
static inline void ethtool_convert_legacy_u32_to_link_mode(unsigned long *dst,
u32 legacy_u32)
{
bitmap_zero(dst, __ETHTOOL_LINK_MODE_MASK_NBITS);
dst[0] = legacy_u32;
}
#endif
#else
#define __ETHTOOL_DECLARE_LINK_MODE_MASK(VAR) unsigned long VAR[1]
static inline void ethtool_convert_legacy_u32_to_link_mode(unsigned long *dst,
u32 legacy_u32)
{
dst[0] = legacy_u32;
}
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) || RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,3)

View file

@ -181,6 +181,7 @@ static int atl_set_fixed_speed(struct atl_hw *hw, unsigned int speed,
{
unsigned int dplx = (duplex == DUPLEX_HALF) ? DUPLEX_HALF : DUPLEX_FULL;
struct atl_link_state *lstate = &hw->link_state;
__ETHTOOL_DECLARE_LINK_MODE_MASK(link_modes);
struct atl_link_type *type;
unsigned long tmp;
int i;
@ -197,9 +198,9 @@ static int atl_set_fixed_speed(struct atl_hw *hw, unsigned int speed,
if (lstate->eee_enabled) {
atl_link_to_kernel(lstate->supported >> ATL_EEE_BIT_OFFT,
&tmp, false);
link_modes, false);
/* advertize the supported links */
tmp = atl_kernel_to_link(&tmp, false);
tmp = atl_kernel_to_link(link_modes, false);
lstate->advertized |= tmp << ATL_EEE_BIT_OFFT;
}
@ -479,6 +480,7 @@ static int atl_set_eee(struct net_device *ndev, struct ethtool_eee *eee)
struct atl_nic *nic = netdev_priv(ndev);
struct atl_hw *hw = &nic->hw;
struct atl_link_state *lstate = &hw->link_state;
__ETHTOOL_DECLARE_LINK_MODE_MASK(link_modes);
unsigned long tmp = 0;
if ((hw->chip_id == ATL_ATLANTIC) && (atl_fw_major(hw) < 2))
@ -491,14 +493,15 @@ static int atl_set_eee(struct net_device *ndev, struct ethtool_eee *eee)
if (lstate->eee_enabled) {
atl_link_to_kernel(lstate->supported >> ATL_EEE_BIT_OFFT,
&tmp, false);
if (eee->advertised & ~tmp)
link_modes, false);
if (eee->advertised & ~link_modes[0])
return -EINVAL;
/* advertize the requested link or all supported */
if (eee->advertised)
tmp = eee->advertised;
tmp = atl_kernel_to_link(&tmp, false);
ethtool_convert_legacy_u32_to_link_mode(link_modes,
eee->advertised);
tmp = atl_kernel_to_link(link_modes, false);
}
lstate->advertized &= ~ATL_EEE_MASK;
@ -628,6 +631,8 @@ static const struct atl_stat_desc rx_fwd_stat_descs[] = {
static const struct atl_stat_desc eth_stat_descs[] = {
ATL_ETH_STAT(tx_pause, tx_pause),
ATL_ETH_STAT(tx_ether_pkts, tx_ether_pkts),
ATL_ETH_STAT(tx_ether_octets, tx_ether_octets),
ATL_ETH_STAT(rx_pause, rx_pause),
ATL_ETH_STAT(rx_ether_drops, rx_ether_drops),
ATL_ETH_STAT(rx_ether_octets, rx_ether_octets),
@ -655,6 +660,7 @@ static const char atl_priv_flags[][ETH_GSTRING_LEN] = {
ATL_PRIV_FLAG(ResetStatistics, STATS_RESET),
ATL_PRIV_FLAG(StripEtherPadding, STRIP_PAD),
ATL_PRIV_FLAG(MediaDetect, MEDIA_DETECT),
ATL_PRIV_FLAG(Downshift, DOWNSHIFT),
};
#if IS_ENABLED(CONFIG_MACSEC) && defined(NETIF_F_HW_MACSEC)
@ -1089,6 +1095,16 @@ int atl_set_media_detect(struct atl_nic *nic, bool on)
return ret;
}
int atl_set_downshift(struct atl_nic *nic, bool on)
{
struct atl_hw *hw = &nic->hw;
int ret;
ret = hw->mcp.ops->set_downshift(hw, on);
return ret;
}
static uint32_t atl_get_priv_flags(struct net_device *ndev)
{
struct atl_nic *nic = netdev_priv(ndev);
@ -1129,6 +1145,13 @@ static int atl_set_priv_flags(struct net_device *ndev, uint32_t flags)
return ret;
}
if (diff & ATL_PF_BIT(DOWNSHIFT)) {
ret = atl_set_downshift(nic,
!!(flags & ATL_PF_BIT(DOWNSHIFT)));
if (ret)
return ret;
}
if (hweight32(lpb) > 1) {
atl_nic_err("Can't enable more than one loopback simultaneously\n");
return -EINVAL;

View file

@ -655,6 +655,33 @@ unlock:
return ret;
}
static int atl_fw2_set_downshift(struct atl_hw *hw, bool on)
{
uint32_t req;
int res = 0;
int ret = 0;
atl_lock_fw(hw);
if (on)
hw->mcp.req_high |= atl_fw2_downshift;
else
hw->mcp.req_high &= ~atl_fw2_downshift;
req = hw->mcp.req_high;
atl_write(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_HIGH), req);
busy_wait(10000, udelay(10), res,
atl_read(hw, ATL_MCP_SCRATCH(FW2_LINK_RES_HIGH)),
((res ^ req) & atl_fw2_downshift) != 0);
if (((res ^ req) & atl_fw2_downshift) != 0) {
atl_dev_err("Timeout waiting for statistics\n");
ret = -EIO;
}
atl_unlock_fw(hw);
return ret;
}
static int __atl_fw2x_apply_msm_settings(struct atl_hw *hw)
{
@ -982,7 +1009,8 @@ static struct atl_fw_ops atl_fw_ops[2] = {
.dump_cfg = atl_fw1_unsupported,
.restore_cfg = atl_fw1_unsupported,
.set_phy_loopback = (void *)atl_fw1_unsupported,
.set_mediadetect = (void *)atl_fw1_unsupported,
.set_mediadetect = (void *)atl_fw1_unsupported,
.set_downshift = (void *)atl_fw1_unsupported,
.send_macsec_req = (void *)atl_fw1_unsupported,
.set_pad_stripping = (void *)atl_fw1_unsupported,
.__get_hbeat = (void *)atl_fw1_unsupported,
@ -1003,6 +1031,7 @@ static struct atl_fw_ops atl_fw_ops[2] = {
.restore_cfg = atl_fw2_restore_cfg,
.set_phy_loopback = atl_fw2_set_phy_loopback,
.set_mediadetect = atl_fw2_set_mediadetect,
.set_downshift = atl_fw2_set_downshift,
.send_macsec_req = atl_fw2_send_macsec_request,
.set_pad_stripping = atl_fw2_set_pad_stripping,
.__get_hbeat = __atl_fw2_get_hbeat,

View file

@ -31,6 +31,7 @@ struct atl_mcp {
uint32_t caps_low;
uint32_t caps_high;
uint32_t caps_ex;
uint32_t interface_ver;
struct mutex lock;
unsigned long next_wdog;
bool wdog_disabled;
@ -86,6 +87,7 @@ enum atl_fw2_opts {
atl_define_bit(atl_fw2_wake_on_link, 16)
atl_define_bit(atl_fw2_wake_on_link_force, 17)
atl_define_bit(atl_fw2_phy_temp, 18)
atl_define_bit(atl_fw2_downshift, 19)
atl_define_bit(atl_fw2_set_thermal, 21)
atl_define_bit(atl_fw2_link_drop, 22)
atl_define_bit(atl_fw2_nic_proxy, 0x17)
@ -287,6 +289,7 @@ struct atl_fw_ops {
int (*restore_cfg)(struct atl_hw *hw);
int (*set_phy_loopback)(struct atl_nic *nic, u32 mode);
int (*set_mediadetect)(struct atl_hw *hw, bool on);
int (*set_downshift)(struct atl_hw *hw, bool on);
int (*set_pad_stripping)(struct atl_hw *hw, bool on);
int (*send_macsec_req)(struct atl_hw *hw,
struct macsec_msg_fw_request *msg,

View file

@ -1178,7 +1178,7 @@ static int request_ring(struct net_device *ndev, struct genl_info *info)
goto err_relring;
}
result = atl_init_rx_ring(ring_desc);
result = atl_init_rx_ring(ring_desc, ATL_QUEUE_REGULAR);
}
if (result)
goto err_relring;

View file

@ -575,8 +575,10 @@ static irqreturn_t atl_legacy_irq(int irq, void *priv)
}
}
if (unlikely(stat & hw->non_ring_intr_mask))
if (unlikely(stat & BIT(ATL_IRQ_LINK)))
atl_link_irq(irq, nic);
if (unlikely(stat & BIT(ATL_IRQ_PTP)))
atl_ptp_irq(irq, nic->ptp);
return IRQ_HANDLED;
}
@ -898,6 +900,9 @@ void atl_set_rx_mode(struct net_device *ndev)
else if (uc_count + mc_count > nic->rxf_mac.available - 1)
all_multi_needed = true;
if (nic->priv_flags & ATL_PF_BIT(LPB_NET_DMA))
promisc_needed = true;
/* Enable promisc VLAN mode if IFF_PROMISC explicitly
* requested or too many VIDs registered
*/
@ -1242,6 +1247,106 @@ void atl_adjust_eth_stats(struct atl_ether_stats *stats,
_stats[i] += add ? _base[i] : - _base[i];
}
static int __atl_fetch_msm1_stats(struct atl_hw *hw,
struct atl_ether_stats *stats)
{
u32 reg, reg2;
int ret;
ret = atl_hwsem_get(hw, ATL_MCP_SEM_MSM);
if (ret)
return ret;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_TX_PAUSE, &reg, hwsem_put);
stats->tx_pause = reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_TX_PKTS_GOOD, &reg, hwsem_put);
stats->tx_ether_pkts = reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_TX_OCTETS_LO, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_TX_OCTETS_HI, &reg2, hwsem_put);
stats->tx_ether_octets = ((uint64_t)reg2 << 32) | reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_PAUSE, &reg, hwsem_put);
stats->rx_pause = reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_OCTETS_LO, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_OCTETS_HI, &reg2, hwsem_put);
stats->rx_ether_octets = ((uint64_t)reg2 << 32) | reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_PKTS_GOOD, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_ERRS, &reg2, hwsem_put);
stats->rx_ether_pkts = reg + reg2;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_BROADCAST, &reg, hwsem_put);
stats->rx_ether_broacasts = reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_MULTICAST, &reg, hwsem_put);
stats->rx_ether_multicasts = reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_FCS_ERRS, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_ALIGN_ERRS, &reg2, hwsem_put);
stats->rx_ether_crc_align_errs = reg + reg2;
hwsem_put:
atl_hwsem_put(hw, ATL_MCP_SEM_MSM);
return ret;
}
static int __atl_fetch_msm2_stats(struct atl_hw *hw,
struct atl_ether_stats *stats)
{
u32 reg, reg2;
int ret;
ret = atl_hwsem_get(hw, ATL_MCP_SEM_MSM);
if (ret)
return ret;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_PAUSE_LO, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_PAUSE_HI, &reg2, hwsem_put);
stats->tx_pause = ((uint64_t)reg2 << 32) | reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_PKTS_LO, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_PKTS_HI, &reg2, hwsem_put);
stats->tx_ether_pkts = ((uint64_t)reg2 << 32) | reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_OCTETS_LO, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_OCTETS_HI, &reg2, hwsem_put);
stats->tx_ether_octets = ((uint64_t)reg2 << 32) | reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_PAUSE_LO, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_PAUSE_HI, &reg2, hwsem_put);
stats->rx_pause = ((uint64_t)reg2 << 32) | reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_OCTETS_LO, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_OCTETS_HI, &reg2, hwsem_put);
stats->rx_ether_octets = ((uint64_t)reg2 << 32) | reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_PKTS_LO, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_PKTS_HI, &reg2, hwsem_put);
stats->rx_ether_pkts = ((uint64_t)reg2 << 32) | reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_BROADCAST_LO, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_BROADCAST_HI, &reg2, hwsem_put);
stats->rx_ether_broacasts = ((uint64_t)reg2 << 32) | reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_MULTICAST_LO, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_MULTICAST_HI, &reg2, hwsem_put);
stats->rx_ether_multicasts = ((uint64_t)reg2 << 32) | reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_FCS_ERRS_LO, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_FCS_ERRS_LO, &reg, hwsem_put);
stats->rx_ether_crc_align_errs = ((uint64_t)reg2 << 32) | reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_ALIGN_ERRS_LO, &reg2, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_ALIGN_ERRS_HI, &reg2, hwsem_put);
stats->rx_ether_crc_align_errs += ((uint64_t)reg2 << 32) | reg;
hwsem_put:
atl_hwsem_put(hw, ATL_MCP_SEM_MSM);
return ret;
}
int atl_update_eth_stats(struct atl_nic *nic)
{
struct atl_hw *hw = &nic->hw;
@ -1257,34 +1362,13 @@ int atl_update_eth_stats(struct atl_nic *nic)
atl_lock_fw(hw);
ret = atl_hwsem_get(hw, ATL_MCP_SEM_MSM);
if (hw->mcp.interface_ver != ATL2_FW_INTERFACE_B0)
ret = __atl_fetch_msm1_stats(hw, &stats);
else
ret = __atl_fetch_msm2_stats(hw, &stats);
if (ret)
goto unlock_fw;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_TX_PAUSE, &reg, hwsem_put);
stats.tx_pause = reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_PAUSE, &reg, hwsem_put);
stats.rx_pause = reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_OCTETS_LO, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_OCTETS_HI, &reg2, hwsem_put);
stats.rx_ether_octets = ((uint64_t)reg2 << 32) | reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_PKTS_GOOD, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_ERRS, &reg2, hwsem_put);
stats.rx_ether_pkts = reg + reg2;;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_BROADCAST, &reg, hwsem_put);
stats.rx_ether_broacasts = reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_MULTICAST, &reg, hwsem_put);
stats.rx_ether_multicasts = reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_FCS_ERRS, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_ALIGN_ERRS, &reg2, hwsem_put);
stats.rx_ether_crc_align_errs = reg + reg2;
stats.rx_ether_drops = atl_read(hw, ATL_RX_DMA_STATS_CNT7);
/* capture debug counters*/
@ -1307,8 +1391,6 @@ int atl_update_eth_stats(struct atl_nic *nic)
ret = 0;
hwsem_put:
atl_hwsem_put(hw, ATL_MCP_SEM_MSM);
unlock_fw:
atl_unlock_fw(hw);
return ret;

View file

@ -443,6 +443,10 @@ int atl_fw_configure(struct atl_hw *hw)
!!(nic->priv_flags & ATL_PF_BIT(MEDIA_DETECT)));
if (ret && ret != -EOPNOTSUPP)
return ret;
ret = hw->mcp.ops->set_downshift(hw,
!!(nic->priv_flags & ATL_PF_BIT(DOWNSHIFT)));
if (ret && ret != -EOPNOTSUPP)
return ret;
ret = hw->mcp.ops->set_pad_stripping(hw,
!!(nic->priv_flags & ATL_PF_BIT(STRIP_PAD)));
if (ret && ret != -EOPNOTSUPP)
@ -598,6 +602,7 @@ static int atl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_ioremap;
}
nic->priv_flags = ATL_PF_BIT(DOWNSHIFT);
ret = atl_hwinit(hw, id->driver_data);
if (ret)
goto err_hwinit;

View file

@ -34,6 +34,12 @@
#define PTP_4TC_RING_IDX 16
#define PTP_HWTS_RING_IDX 31
enum ptp_perout_action {
ptp_perout_disabled = 0,
ptp_perout_enabled,
ptp_perout_pps,
};
enum ptp_speed_offsets {
ptp_offset_idx_10 = 0,
ptp_offset_idx_100,
@ -105,6 +111,8 @@ struct ptp_tm_offset {
static struct ptp_tm_offset ptp_offset[6];
static int atl_ptp_pps_reconfigure(struct atl_ptp *ptp);
static int __atl_ptp_skb_put(struct ptp_skb_ring *ring, struct sk_buff *skb)
{
unsigned int next_head = (ring->head + 1) % ring->size;
@ -309,6 +317,8 @@ static int atl_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
hw_atl_adj_sys_clock(&nic->hw, delta);
spin_unlock_irqrestore(&ptp->ptp_lock, flags);
atl_ptp_pps_reconfigure(ptp);
return 0;
}
@ -354,9 +364,10 @@ static int atl_ptp_settime(struct ptp_clock_info *ptp_info,
spin_lock_irqsave(&ptp->ptp_lock, flags);
hw_atl_get_ptp_ts(&nic->hw, &now);
hw_atl_adj_sys_clock(&nic->hw, (s64)ns - (s64)now);
spin_unlock_irqrestore(&ptp->ptp_lock, flags);
atl_ptp_pps_reconfigure(ptp);
return 0;
}
@ -418,6 +429,8 @@ static int atl_ptp_perout_pin_configure(struct ptp_clock_info *ptp_clock,
start = on ? s->sec * NSEC_PER_SEC + s->nsec : 0;
atl_ptp_hw_pin_conf(nic, pin_index, start, period);
ptp->ptp_info.pin_config[pin_index].rsv[2] = on ? ptp_perout_enabled :
ptp_perout_disabled;
return 0;
}
@ -442,10 +455,35 @@ static int atl_ptp_pps_pin_configure(struct ptp_clock_info *ptp_clock,
(rest > 990000000LL ? 2 : 1) : 0;
atl_ptp_hw_pin_conf(nic, pin_index, start, period);
ptp->ptp_info.pin_config[pin_index].rsv[2] = on ? ptp_perout_pps :
ptp_perout_disabled;
return 0;
}
static int atl_ptp_pps_reconfigure(struct atl_ptp *ptp)
{
struct atl_nic *nic = ptp->nic;
u64 start, period;
u32 rest = 0;
int i;
for (i = 0; i < ptp->ptp_info.n_pins; i++)
if ((ptp->ptp_info.pin_config[i].func == PTP_PF_PEROUT) &&
(ptp->ptp_info.pin_config[i].rsv[2] == ptp_perout_pps)) {
hw_atl_get_ptp_ts(&nic->hw, &start);
div_u64_rem(start, NSEC_PER_SEC, &rest);
period = NSEC_PER_SEC;
start = start - rest + NSEC_PER_SEC * (rest > 990000000LL ? 2 : 1);
atl_ptp_hw_pin_conf(nic, i, start, period);
}
return 0;
}
static void atl_ptp_extts_pin_ctrl(struct atl_ptp *ptp)
{
struct atl_nic *nic = ptp->nic;
@ -575,21 +613,6 @@ static int atl_ptp_poll(struct napi_struct *napi, int budget)
return work_done;
}
static irqreturn_t atl_ptp_irq(int irq, void *private)
{
struct atl_ptp *ptp = private;
int err = 0;
if (!ptp) {
err = -EINVAL;
goto err_exit;
}
napi_schedule_irqoff(ptp->napi);
err_exit:
return err >= 0 ? IRQ_HANDLED : IRQ_NONE;
}
static struct ptp_clock_info atl_ptp_clock = {
.owner = THIS_MODULE,
.name = "atlantic ptp",
@ -808,6 +831,25 @@ static void atl_ptp_poll_sync_work_cb(struct work_struct *w)
#endif /* IS_REACHABLE(CONFIG_PTP_1588_CLOCK) */
irqreturn_t atl_ptp_irq(int irq, void *private)
{
#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
struct atl_ptp *ptp = private;
int err = 0;
if (!ptp) {
err = -EINVAL;
goto err_exit;
}
napi_schedule_irqoff(ptp->napi);
err_exit:
return err >= 0 ? IRQ_HANDLED : IRQ_NONE;
#else
return IRQ_NONE;
#endif
}
void atl_ptp_tm_offset_set(struct atl_nic *nic, unsigned int mbps)
{
#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
@ -1030,7 +1072,7 @@ int atl_ptp_irq_alloc(struct atl_nic *nic)
atl_ptp_irq, 0, nic->ndev->name, ptp);
}
return -EINVAL;
return 0;
#else
return 0;
#endif
@ -1046,7 +1088,8 @@ void atl_ptp_irq_free(struct atl_nic *nic)
return;
atl_intr_disable(hw, BIT(ptp->idx_vector));
free_irq(pci_irq_vector(hw->pdev, ptp->idx_vector), ptp);
if (nic->flags & ATL_FL_MULTIPLE_VECTORS)
free_irq(pci_irq_vector(hw->pdev, ptp->idx_vector), ptp);
#endif
}

View file

@ -209,11 +209,14 @@ enum mcp_scratchpad {
#define ATL_MSM_GEN_CTRL 0x8
#define ATL_MSM_GEN_STS 0x40
#define ATL_MSM_TX_LPI_DELAY 0x78
#define ATL_MSM_CTR_TX_PKTS_GOOD 0x80
#define ATL_MSM_CTR_RX_PKTS_GOOD 0x88
#define ATL_MSM_CTR_RX_FCS_ERRS 0x90
#define ATL_MSM_CTR_RX_ALIGN_ERRS 0x98
#define ATL_MSM_CTR_TX_PAUSE 0xa0
#define ATL_MSM_CTR_RX_PAUSE 0xa8
#define ATL_MSM_CTR_TX_OCTETS_LO 0xd0
#define ATL_MSM_CTR_TX_OCTETS_HI 0xd4
#define ATL_MSM_CTR_RX_OCTETS_LO 0xd8
#define ATL_MSM_CTR_RX_OCTETS_HI 0xdc
#define ATL_MSM_CTR_RX_MULTICAST 0xE8
@ -221,4 +224,26 @@ enum mcp_scratchpad {
#define ATL_MSM_CTR_RX_ERRS 0x120
#define ATL_MSM2_CTR_RX_OCTETS_LO 0x100
#define ATL_MSM2_CTR_RX_OCTETS_HI 0x104
#define ATL_MSM2_CTR_RX_ALIGN_ERRS_LO 0x110
#define ATL_MSM2_CTR_RX_ALIGN_ERRS_HI 0x114
#define ATL_MSM2_CTR_RX_PAUSE_LO 0x118
#define ATL_MSM2_CTR_RX_PAUSE_HI 0x11c
#define ATL_MSM2_CTR_RX_FCS_ERRS_LO 0x128
#define ATL_MSM2_CTR_RX_FCS_ERRS_HI 0x12c
#define ATL_MSM2_CTR_RX_MULTICAST_LO 0x148
#define ATL_MSM2_CTR_RX_MULTICAST_HI 0x14c
#define ATL_MSM2_CTR_RX_BROADCAST_LO 0x150
#define ATL_MSM2_CTR_RX_BROADCAST_HI 0x154
#define ATL_MSM2_CTR_RX_PKTS_LO 0x160
#define ATL_MSM2_CTR_RX_PKTS_HI 0x164
#define ATL_MSM2_CTR_TX_OCTETS_LO 0x200
#define ATL_MSM2_CTR_TX_OCTETS_HI 0x204
#define ATL_MSM2_CTR_TX_PAUSE_LO 0x218
#define ATL_MSM2_CTR_TX_PAUSE_HI 0x21c
#define ATL_MSM2_CTR_TX_PKTS_LO 0x220
#define ATL_MSM2_CTR_TX_PKTS_HI 0x224
#endif

View file

@ -1825,7 +1825,7 @@ void atl_set_intr_mod(struct atl_nic *nic)
atl_set_intr_mod_qvec(qvec);
}
int atl_init_rx_ring(struct atl_desc_ring *rx)
int atl_init_rx_ring(struct atl_desc_ring *rx, enum atl_queue_type type)
{
struct atl_hw *hw = &rx->nic->hw;
struct atl_rxbuf *rxbuf;
@ -1835,7 +1835,7 @@ int atl_init_rx_ring(struct atl_desc_ring *rx)
if (rx->head > 0x1FFF)
return -EIO;
switch (rx->qvec->type) {
switch (type) {
case ATL_QUEUE_HWTS:
ret = atl_fill_hwts_rx(rx, ring_space(rx), false);
break;
@ -1851,7 +1851,7 @@ int atl_init_rx_ring(struct atl_desc_ring *rx)
if (ret)
return ret;
if (likely(rx->qvec->type != ATL_QUEUE_HWTS)) {
if (likely(type != ATL_QUEUE_HWTS)) {
rx->next_to_recycle = rx->tail;
/* rxbuf at ->next_to_recycle is always kept empty so that
* atl_maybe_recycle_rxbuf() always have a spot to recycle into
@ -1962,7 +1962,7 @@ int atl_start_qvec(struct atl_queue_vec *qvec)
int intr = atl_qvec_intr(qvec);
int ret;
ret = atl_init_rx_ring(rx);
ret = atl_init_rx_ring(rx, qvec->type);
if (ret)
return ret;
if (likely(qvec->type != ATL_QUEUE_HWTS)) {

View file

@ -186,7 +186,7 @@ do { \
u64_stats_update_end(&_ring->syncp); \
} while (0)
int atl_init_rx_ring(struct atl_desc_ring *rx);
int atl_init_rx_ring(struct atl_desc_ring *rx, enum atl_queue_type type);
int atl_init_tx_ring(struct atl_desc_ring *tx);
netdev_tx_t atl_map_skb(struct sk_buff *skb, struct atl_desc_ring *ring);

View file

@ -52,8 +52,10 @@ struct atl_ring_stats {
};
struct atl_ether_stats {
uint64_t rx_pause;
uint64_t tx_pause;
uint64_t tx_ether_pkts;
uint64_t tx_ether_octets;
uint64_t rx_pause;
uint64_t rx_ether_drops;
uint64_t rx_ether_octets;
uint64_t rx_ether_pkts;

View file

@ -1,3 +1,24 @@
Version 1.1.15
==============
[ATLDRV-1613] - Atlantic_fwd driver hitting NULL pointer dereference at 0000000000000678 while requesting rx rings
Version 1.1.14
==============
[ATLDRV-1609] - Facing failure for the DMA Network Loopback Test
[ATLDRV-1605] - AQC107 GPIO_0 PPS alignment
[ATLDRV-1614] - probe of 0000:02:00.0 failed with error -22 after loading driver with "msi=N max_queues_non_msi=4"
Version 1.1.13
==============
[ATLDRV-1581] - AQ091: AQC DMA stats in Ethtool
A2: report FW bundle ver instead of mac FW ver
Version 1.1.12
==============
[ATLDRV-1573] - Crash on enable EEE
[ATLDRV-1576] - FWD: Add support of Antigua B0 statistics
[ATLDRV-1577] - Add Downshift feature
Version 1.1.11
==============
[ATLDRV-1567] - forwarding driver issue with adj_freq