[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Wed, 8 Aug 2018 13:57:14 +0300
From: Igor Russkikh <igor.russkikh@...antia.com>
To: "David S . Miller" <davem@...emloft.net>
Cc: netdev@...r.kernel.org, Igor Russkikh <igor.russkikh@...antia.com>,
Yana Esina <yana.esina@...antia.com>,
Nikita Danilov <nikita.danilov@...antia.com>
Subject: [PATCH net-next 4/5] net: aquantia: implement EEE support
From: Yana Esina <yana.esina@...antia.com>
Support of Energy-Efficient Ethernet to aQuantia NIC's via ethtool
(according to the IEEE 802.3az specifications)
We do replace some duplicate speed bits definitions here (HW_ATL_B0_RATE_)
with driver generic constants (AQ_NIC_RATE_)
Signed-off-by: Yana Esina <yana.esina@...antia.com>
Signed-off-by: Nikita Danilov <nikita.danilov@...antia.com>
Tested-by: Nikita Danilov <nikita.danilov@...antia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@...antia.com>
---
drivers/net/ethernet/aquantia/atlantic/aq_common.h | 5 +
.../net/ethernet/aquantia/atlantic/aq_ethtool.c | 76 +++++++++++
drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 4 +
drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 1 +
.../ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 32 ++---
.../aquantia/atlantic/hw_atl/hw_atl_a0_internal.h | 6 -
.../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 34 ++---
.../aquantia/atlantic/hw_atl/hw_atl_b0_internal.h | 6 -
.../aquantia/atlantic/hw_atl/hw_atl_utils.c | 2 +
.../aquantia/atlantic/hw_atl/hw_atl_utils.h | 13 ++
.../aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 141 +++++++++++++++++----
11 files changed, 250 insertions(+), 70 deletions(-)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_common.h b/drivers/net/ethernet/aquantia/atlantic/aq_common.h
index d52b088..becb578 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_common.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_common.h
@@ -57,4 +57,9 @@
#define AQ_NIC_RATE_1G BIT(4)
#define AQ_NIC_RATE_100M BIT(5)
+#define AQ_NIC_RATE_EEE_10G BIT(6)
+#define AQ_NIC_RATE_EEE_5G BIT(7)
+#define AQ_NIC_RATE_EEE_2GS BIT(8)
+#define AQ_NIC_RATE_EEE_1G BIT(9)
+
#endif /* AQ_COMMON_H */
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
index f9fe49b..ec12edf 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
@@ -315,6 +315,80 @@ static int aq_ethtool_set_wol(struct net_device *ndev,
return err;
}
+static enum hw_atl_fw2x_rate eee_mask_to_ethtool_mask(u32 speed)
+{
+ u32 rate = 0;
+
+ if (speed & AQ_NIC_RATE_EEE_10G)
+ rate |= SUPPORTED_10000baseT_Full;
+
+ if (speed & AQ_NIC_RATE_EEE_2GS)
+ rate |= SUPPORTED_2500baseX_Full;
+
+ if (speed & AQ_NIC_RATE_EEE_1G)
+ rate |= SUPPORTED_1000baseT_Full;
+
+ return rate;
+}
+
+static int aq_ethtool_get_eee(struct net_device *ndev, struct ethtool_eee *eee)
+{
+ struct aq_nic_s *aq_nic = netdev_priv(ndev);
+ int err = 0;
+
+ u32 rate, supported_rates;
+
+ if (!aq_nic->aq_fw_ops->get_eee_rate)
+ return -EOPNOTSUPP;
+
+ err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
+ &supported_rates);
+ if (err < 0)
+ return err;
+
+ eee->supported = eee_mask_to_ethtool_mask(supported_rates);
+
+ if (aq_nic->aq_nic_cfg.eee_speeds)
+ eee->advertised = eee->supported;
+
+ eee->lp_advertised = eee_mask_to_ethtool_mask(rate);
+
+ eee->eee_enabled = !!eee->advertised;
+
+ eee->tx_lpi_enabled = eee->eee_enabled;
+ if (eee->advertised & eee->lp_advertised)
+ eee->eee_active = true;
+
+ return 0;
+}
+
+static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_eee *eee)
+{
+ struct aq_nic_s *aq_nic = netdev_priv(ndev);
+ struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
+ u32 rate, supported_rates;
+ int err = 0;
+
+ if (unlikely(!aq_nic->aq_fw_ops->get_eee_rate ||
+ !aq_nic->aq_fw_ops->set_eee_rate))
+ return -EOPNOTSUPP;
+
+ err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
+ &supported_rates);
+ if (err < 0)
+ return err;
+
+ if (eee->eee_enabled) {
+ rate = supported_rates;
+ cfg->eee_speeds = rate;
+ } else {
+ rate = 0;
+ cfg->eee_speeds = 0;
+ }
+
+ return aq_nic->aq_fw_ops->set_eee_rate(aq_nic->aq_hw, rate);
+}
+
static int aq_ethtool_nway_reset(struct net_device *ndev)
{
struct aq_nic_s *aq_nic = netdev_priv(ndev);
@@ -438,6 +512,8 @@ const struct ethtool_ops aq_ethtool_ops = {
.nway_reset = aq_ethtool_nway_reset,
.get_ringparam = aq_get_ringparam,
.set_ringparam = aq_set_ringparam,
+ .get_eee = aq_ethtool_get_eee,
+ .set_eee = aq_ethtool_set_eee,
.get_pauseparam = aq_ethtool_get_pauseparam,
.set_pauseparam = aq_ethtool_set_pauseparam,
.get_rxfh_key_size = aq_ethtool_get_rss_key_size,
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
index 403d86ea..e868924 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
@@ -231,6 +231,10 @@ struct aq_fw_ops {
int (*set_power)(struct aq_hw_s *self, unsigned int power_state,
u8 *mac);
+ int (*set_eee_rate)(struct aq_hw_s *self, u32 speed);
+
+ int (*get_eee_rate)(struct aq_hw_s *self, u32 *rate,
+ u32 *supported_rates);
};
#endif /* AQ_HW_H */
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
index 2069cbb..c1582f4 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
@@ -45,6 +45,7 @@ struct aq_nic_cfg_s {
bool is_lro;
u8 tcs;
struct aq_rss_parameters aq_rss;
+ u32 eee_speeds;
};
#define AQ_NIC_FLAG_STARTED 0x00000004U
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
index 1dd0ef4..f9d88c7 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
@@ -49,37 +49,37 @@
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,
+ .link_speed_msk = AQ_NIC_RATE_5G |
+ AQ_NIC_RATE_2GS |
+ AQ_NIC_RATE_1G |
+ AQ_NIC_RATE_100M,
};
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,
+ .link_speed_msk = AQ_NIC_RATE_10G |
+ AQ_NIC_RATE_5G |
+ AQ_NIC_RATE_2GS |
+ AQ_NIC_RATE_1G |
+ AQ_NIC_RATE_100M,
};
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,
+ .link_speed_msk = AQ_NIC_RATE_5G |
+ AQ_NIC_RATE_2GS |
+ AQ_NIC_RATE_1G |
+ AQ_NIC_RATE_100M,
};
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,
+ .link_speed_msk = AQ_NIC_RATE_2GS |
+ AQ_NIC_RATE_1G |
+ AQ_NIC_RATE_100M,
};
static int hw_atl_a0_hw_reset(struct aq_hw_s *self)
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h
index 3c94cff..a021dc4 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h
@@ -62,12 +62,6 @@
#define HW_ATL_A0_MPI_SPEED_MSK 0xFFFFU
#define HW_ATL_A0_MPI_SPEED_SHIFT 16U
-#define HW_ATL_A0_RATE_10G BIT(0)
-#define HW_ATL_A0_RATE_5G BIT(1)
-#define HW_ATL_A0_RATE_2G5 BIT(3)
-#define HW_ATL_A0_RATE_1G BIT(4)
-#define HW_ATL_A0_RATE_100M BIT(5)
-
#define HW_ATL_A0_TXBUF_MAX 160U
#define HW_ATL_A0_RXBUF_MAX 320U
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
index 6644c96..5092f1b 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
@@ -51,38 +51,38 @@
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,
+ .link_speed_msk = AQ_NIC_RATE_10G |
+ AQ_NIC_RATE_5G |
+ AQ_NIC_RATE_2GS |
+ AQ_NIC_RATE_1G |
+ AQ_NIC_RATE_100M,
};
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,
+ .link_speed_msk = AQ_NIC_RATE_10G |
+ AQ_NIC_RATE_5G |
+ AQ_NIC_RATE_2GS |
+ AQ_NIC_RATE_1G |
+ AQ_NIC_RATE_100M,
};
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,
+ .link_speed_msk = AQ_NIC_RATE_5G |
+ AQ_NIC_RATE_2GS |
+ AQ_NIC_RATE_1G |
+ AQ_NIC_RATE_100M,
};
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,
+ .link_speed_msk = AQ_NIC_RATE_2GS |
+ AQ_NIC_RATE_1G |
+ AQ_NIC_RATE_100M,
};
static int hw_atl_b0_hw_reset(struct aq_hw_s *self)
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h
index 28568f5..b318eef 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h
@@ -67,12 +67,6 @@
#define HW_ATL_B0_MPI_SPEED_MSK 0xFFFFU
#define HW_ATL_B0_MPI_SPEED_SHIFT 16U
-#define HW_ATL_B0_RATE_10G BIT(0)
-#define HW_ATL_B0_RATE_5G BIT(1)
-#define HW_ATL_B0_RATE_2G5 BIT(3)
-#define HW_ATL_B0_RATE_1G BIT(4)
-#define HW_ATL_B0_RATE_100M BIT(5)
-
#define HW_ATL_B0_TXBUF_MAX 160U
#define HW_ATL_B0_RXBUF_MAX 320U
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
index b1a0fb5..436b278 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
@@ -912,5 +912,7 @@ const struct aq_fw_ops aq_fw_1x_ops = {
.update_link_status = hw_atl_utils_mpi_get_link_status,
.update_stats = hw_atl_utils_update_stats,
.set_power = aq_fw1x_set_power,
+ .set_eee_rate = NULL,
+ .get_eee_rate = NULL,
.set_flow_control = NULL,
};
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
index 3aceb55..95419e3 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
@@ -171,9 +171,22 @@ struct __packed hw_atl_utils_mbox_header {
u32 error;
};
+struct __packed hw_aq_info {
+ u8 reserved[6];
+ u16 phy_fault_code;
+ u16 phy_temperature;
+ u8 cable_len;
+ u8 reserved1;
+ u32 cable_diag_data[4];
+ u8 reserved2[32];
+ u32 caps_lo;
+ u32 caps_hi;
+};
+
struct __packed hw_atl_utils_mbox {
struct hw_atl_utils_mbox_header header;
struct hw_atl_stats_s stats;
+ struct hw_aq_info info;
};
/* fw2x */
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c
index 0ad6ac5..7bd1bea 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c
@@ -40,6 +40,11 @@
#define HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE BIT(CTRL_ASYMMETRIC_PAUSE)
#define HW_ATL_FW2X_CTRL_FORCE_RECONNECT BIT(CTRL_FORCE_RECONNECT)
+#define HW_ATL_FW2X_CAP_EEE_1G_MASK BIT(CAPS_HI_1000BASET_FD_EEE)
+#define HW_ATL_FW2X_CAP_EEE_2G5_MASK BIT(CAPS_HI_2P5GBASET_FD_EEE)
+#define HW_ATL_FW2X_CAP_EEE_5G_MASK BIT(CAPS_HI_5GBASET_FD_EEE)
+#define HW_ATL_FW2X_CAP_EEE_10G_MASK BIT(CAPS_HI_10GBASET_FD_EEE)
+
#define HAL_ATLANTIC_WOL_FILTERS_COUNT 8
#define HAL_ATLANTIC_UTILS_FW2X_MSG_WOL 0x0E
@@ -115,6 +120,38 @@ static enum hw_atl_fw2x_rate link_speed_mask_2fw2x_ratemask(u32 speed)
return rate;
}
+static u32 fw2x_to_eee_mask(u32 speed)
+{
+ u32 rate = 0;
+
+ if (speed & HW_ATL_FW2X_CAP_EEE_10G_MASK)
+ rate |= AQ_NIC_RATE_EEE_10G;
+ if (speed & HW_ATL_FW2X_CAP_EEE_5G_MASK)
+ rate |= AQ_NIC_RATE_EEE_5G;
+ if (speed & HW_ATL_FW2X_CAP_EEE_2G5_MASK)
+ rate |= AQ_NIC_RATE_EEE_2GS;
+ if (speed & HW_ATL_FW2X_CAP_EEE_1G_MASK)
+ rate |= AQ_NIC_RATE_EEE_1G;
+
+ return rate;
+}
+
+static u32 eee_mask_to_fw2x(u32 speed)
+{
+ u32 rate = 0;
+
+ if (speed & AQ_NIC_RATE_EEE_10G)
+ rate |= HW_ATL_FW2X_CAP_EEE_10G_MASK;
+ if (speed & AQ_NIC_RATE_EEE_5G)
+ rate |= HW_ATL_FW2X_CAP_EEE_5G_MASK;
+ if (speed & AQ_NIC_RATE_EEE_2GS)
+ rate |= HW_ATL_FW2X_CAP_EEE_2G5_MASK;
+ if (speed & AQ_NIC_RATE_EEE_1G)
+ rate |= HW_ATL_FW2X_CAP_EEE_1G_MASK;
+
+ return rate;
+}
+
static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed)
{
u32 val = link_speed_mask_2fw2x_ratemask(speed);
@@ -124,31 +161,46 @@ 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)
+static void aq_fw2x_upd_flow_control_bits(struct aq_hw_s *self,
+ u32 *mpi_state, u32 fc)
{
- if (self->aq_nic_cfg->flow_control & AQ_NIC_FC_RX)
- *mpi_state |= BIT(CAPS_HI_PAUSE);
+ if (fc & AQ_NIC_FC_RX)
+ *mpi_state |= HW_ATL_FW2X_CTRL_PAUSE;
else
- *mpi_state &= ~BIT(CAPS_HI_PAUSE);
+ *mpi_state &= ~HW_ATL_FW2X_CTRL_PAUSE;
- if (self->aq_nic_cfg->flow_control & AQ_NIC_FC_TX)
- *mpi_state |= BIT(CAPS_HI_ASYMMETRIC_PAUSE);
+ if (fc & AQ_NIC_FC_TX)
+ *mpi_state |= HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE;
else
- *mpi_state &= ~BIT(CAPS_HI_ASYMMETRIC_PAUSE);
+ *mpi_state &= ~HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE;
+}
+
+static void aq_fw2x_upd_eee_rate_bits(struct aq_hw_s *self, u32 *mpi_opts,
+ u32 eee_speeds)
+{
+ *mpi_opts &= ~(HW_ATL_FW2X_CAP_EEE_1G_MASK |
+ HW_ATL_FW2X_CAP_EEE_2G5_MASK |
+ HW_ATL_FW2X_CAP_EEE_5G_MASK |
+ HW_ATL_FW2X_CAP_EEE_10G_MASK);
+
+ *mpi_opts |= eee_mask_to_fw2x(eee_speeds);
}
static int aq_fw2x_set_state(struct aq_hw_s *self,
enum hal_atl_utils_fw_state_e state)
{
u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
+ struct aq_nic_cfg_s *cfg = self->aq_nic_cfg;
switch (state) {
case MPI_INIT:
- mpi_state &= ~BIT(CAPS_HI_LINK_DROP);
- aq_fw2x_set_mpi_flow_control(self, &mpi_state);
+ mpi_state &= ~HW_ATL_FW2X_CTRL_LINK_DROP;
+ aq_fw2x_upd_eee_rate_bits(self, &mpi_state, cfg->eee_speeds);
+ aq_fw2x_upd_flow_control_bits(self, &mpi_state,
+ cfg->flow_control);
break;
case MPI_DEINIT:
- mpi_state |= BIT(CAPS_HI_LINK_DROP);
+ mpi_state |= HW_ATL_FW2X_CTRL_LINK_DROP;
break;
case MPI_RESET:
case MPI_POWER:
@@ -163,7 +215,7 @@ 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);
+ FW2X_RATE_2G5 | FW2X_RATE_5G | FW2X_RATE_10G);
struct aq_hw_link_status_s *link_status = &self->aq_link_status;
if (speed) {
@@ -212,9 +264,7 @@ static int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
get_random_bytes(&rnd, sizeof(unsigned int));
- l = 0xE3000000U
- | (0xFFFFU & rnd)
- | (0x00 << 16);
+ l = 0xE3000000U | (0xFFFFU & rnd) | (0x00 << 16);
h = 0x8001300EU;
mac[5] = (u8)(0xFFU & l);
@@ -348,11 +398,49 @@ static int aq_fw2x_set_power(struct aq_hw_s *self, unsigned int power_state,
return err;
}
+static int aq_fw2x_set_eee_rate(struct aq_hw_s *self, u32 speed)
+{
+ u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
+
+ aq_fw2x_upd_eee_rate_bits(self, &mpi_opts, speed);
+
+ aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
+
+ return 0;
+}
+
+static int aq_fw2x_get_eee_rate(struct aq_hw_s *self, u32 *rate,
+ u32 *supported_rates)
+{
+ int err = 0;
+ u32 caps_hi;
+ u32 mpi_state;
+
+ err =
+ hw_atl_utils_fw_downld_dwords(self,
+ self->mbox_addr +
+ offsetof(struct hw_atl_utils_mbox,
+ info) +
+ offsetof(struct hw_aq_info, caps_hi),
+ &caps_hi,
+ sizeof(caps_hi) / sizeof(u32));
+
+ if (err)
+ return err;
+
+ *supported_rates = fw2x_to_eee_mask(caps_hi);
+
+ mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR);
+ *rate = fw2x_to_eee_mask(mpi_state);
+
+ return err;
+}
+
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);
+ mpi_opts |= HW_ATL_FW2X_CTRL_FORCE_RECONNECT;
aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
@@ -363,7 +451,8 @@ 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_fw2x_upd_flow_control_bits(self, &mpi_state,
+ self->aq_nic_cfg->flow_control);
aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state);
@@ -371,15 +460,17 @@ static int aq_fw2x_set_flow_control(struct aq_hw_s *self)
}
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,
+ .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_power = aq_fw2x_set_power,
+ .update_stats = aq_fw2x_update_stats,
+ .set_power = aq_fw2x_set_power,
+ .set_eee_rate = aq_fw2x_set_eee_rate,
+ .get_eee_rate = aq_fw2x_get_eee_rate,
.set_flow_control = aq_fw2x_set_flow_control,
};
--
2.7.4
Powered by blists - more mailing lists