mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 22:40:54 -04:00
Merge "atlantic forwarding driver v1.1.15"
This commit is contained in:
commit
695b140e10
16 changed files with 365 additions and 68 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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, ®, hwsem_put);
|
||||
stats->tx_pause = reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_TX_PKTS_GOOD, ®, hwsem_put);
|
||||
stats->tx_ether_pkts = reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_TX_OCTETS_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_TX_OCTETS_HI, ®2, hwsem_put);
|
||||
stats->tx_ether_octets = ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_PAUSE, ®, hwsem_put);
|
||||
stats->rx_pause = reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_OCTETS_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_OCTETS_HI, ®2, hwsem_put);
|
||||
stats->rx_ether_octets = ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_PKTS_GOOD, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_ERRS, ®2, hwsem_put);
|
||||
stats->rx_ether_pkts = reg + reg2;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_BROADCAST, ®, hwsem_put);
|
||||
stats->rx_ether_broacasts = reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_MULTICAST, ®, hwsem_put);
|
||||
stats->rx_ether_multicasts = reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_FCS_ERRS, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_ALIGN_ERRS, ®2, 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, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_PAUSE_HI, ®2, hwsem_put);
|
||||
stats->tx_pause = ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_PKTS_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_PKTS_HI, ®2, hwsem_put);
|
||||
stats->tx_ether_pkts = ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_OCTETS_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_OCTETS_HI, ®2, hwsem_put);
|
||||
stats->tx_ether_octets = ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_PAUSE_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_PAUSE_HI, ®2, hwsem_put);
|
||||
stats->rx_pause = ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_OCTETS_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_OCTETS_HI, ®2, hwsem_put);
|
||||
stats->rx_ether_octets = ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_PKTS_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_PKTS_HI, ®2, hwsem_put);
|
||||
stats->rx_ether_pkts = ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_BROADCAST_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_BROADCAST_HI, ®2, hwsem_put);
|
||||
stats->rx_ether_broacasts = ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_MULTICAST_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_MULTICAST_HI, ®2, hwsem_put);
|
||||
stats->rx_ether_multicasts = ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_FCS_ERRS_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_FCS_ERRS_LO, ®, 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, ®2, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_ALIGN_ERRS_HI, ®2, 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, ®, hwsem_put);
|
||||
stats.tx_pause = reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_PAUSE, ®, hwsem_put);
|
||||
stats.rx_pause = reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_OCTETS_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_OCTETS_HI, ®2, hwsem_put);
|
||||
stats.rx_ether_octets = ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_PKTS_GOOD, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_ERRS, ®2, hwsem_put);
|
||||
stats.rx_ether_pkts = reg + reg2;;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_BROADCAST, ®, hwsem_put);
|
||||
stats.rx_ether_broacasts = reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_MULTICAST, ®, hwsem_put);
|
||||
stats.rx_ether_multicasts = reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_FCS_ERRS, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_ALIGN_ERRS, ®2, 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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue