From 8d53e9f3c6001dcb2865f6e894da5b54e1418f88 Mon Sep 17 00:00:00 2001 From: Christian Ehrhardt Date: Thu, 4 Jul 2019 10:40:06 +0200 Subject: New upstream version 18.11.2 Change-Id: I23eb4f9179abf1f9c659891f8fddb27ee68ad26b Signed-off-by: Christian Ehrhardt --- drivers/net/atlantic/hw_atl/hw_atl_b0.c | 14 ++- drivers/net/atlantic/hw_atl/hw_atl_b0.h | 2 + drivers/net/atlantic/hw_atl/hw_atl_utils.c | 19 ++-- drivers/net/atlantic/hw_atl/hw_atl_utils.h | 16 +-- drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c | 130 ++++++++++++++++++------ 5 files changed, 124 insertions(+), 57 deletions(-) (limited to 'drivers/net/atlantic/hw_atl') diff --git a/drivers/net/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/atlantic/hw_atl/hw_atl_b0.c index 9400e0ed..a76268e9 100644 --- a/drivers/net/atlantic/hw_atl/hw_atl_b0.c +++ b/drivers/net/atlantic/hw_atl/hw_atl_b0.c @@ -26,12 +26,17 @@ int hw_atl_b0_hw_reset(struct aq_hw_s *self) return err; } +int hw_atl_b0_set_fc(struct aq_hw_s *self, u32 fc, u32 tc) +{ + hw_atl_rpb_rx_xoff_en_per_tc_set(self, !!(fc & AQ_NIC_FC_RX), tc); + return 0; +} + static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) { u32 tc = 0U; u32 buff_size = 0U; unsigned int i_priority = 0U; - bool is_rx_flow_control = false; /* TPS Descriptor rate init */ hw_atl_tps_tx_pkt_shed_desc_rate_curr_time_res_set(self, 0x0U); @@ -64,7 +69,6 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) /* QoS Rx buf size per TC */ tc = 0; - is_rx_flow_control = 0; buff_size = HW_ATL_B0_RXBUF_MAX; hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, buff_size, tc); @@ -76,9 +80,7 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) (buff_size * (1024U / 32U) * 50U) / 100U, tc); - hw_atl_rpb_rx_xoff_en_per_tc_set(self, - is_rx_flow_control ? 1U : 0U, - tc); + hw_atl_rpb_rx_xoff_en_per_tc_set(self, 0U, tc); /* QoS 802.1p priority -> TC mapping */ for (i_priority = 8U; i_priority--;) @@ -290,6 +292,8 @@ int hw_atl_b0_hw_init_rx_path(struct aq_hw_s *self) hw_atl_rpfl2broadcast_flr_act_set(self, 1U); hw_atl_rpfl2broadcast_count_threshold_set(self, 0xFFFFU & (~0U / 256U)); + hw_atl_rpfl2broadcast_en_set(self, 1U); + hw_atl_rdm_rx_dca_en_set(self, 0U); hw_atl_rdm_rx_dca_mode_set(self, 0U); diff --git a/drivers/net/atlantic/hw_atl/hw_atl_b0.h b/drivers/net/atlantic/hw_atl/hw_atl_b0.h index 06feb56c..d1ba2ace 100644 --- a/drivers/net/atlantic/hw_atl/hw_atl_b0.h +++ b/drivers/net/atlantic/hw_atl/hw_atl_b0.h @@ -11,6 +11,8 @@ int hw_atl_b0_hw_reset(struct aq_hw_s *self); int hw_atl_b0_hw_init(struct aq_hw_s *self, u8 *mac_addr); +int hw_atl_b0_set_fc(struct aq_hw_s *self, u32 fc, u32 tc); + int hw_atl_b0_hw_ring_tx_init(struct aq_hw_s *self, uint64_t base_addr, int index, int size, int cpu, int vec); int hw_atl_b0_hw_ring_rx_init(struct aq_hw_s *self, uint64_t base_addr, diff --git a/drivers/net/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/atlantic/hw_atl/hw_atl_utils.c index f11093a5..26260194 100644 --- a/drivers/net/atlantic/hw_atl/hw_atl_utils.c +++ b/drivers/net/atlantic/hw_atl/hw_atl_utils.c @@ -306,6 +306,11 @@ int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a, HW_ATL_MIF_CMD)), 1, 1000U); + if (err) { + err = -ETIMEDOUT; + goto err_exit; + } + *(p++) = aq_hw_read_reg(self, HW_ATL_MIF_VAL); a += 4; } @@ -328,12 +333,13 @@ int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, goto err_exit; } if (IS_CHIP_FEATURE(REVISION_B1)) { - u32 offset = 0; + u32 mbox_offset = (a - self->rpc_addr) / sizeof(u32); + u32 data_offset = 0; - for (; offset < cnt; ++offset) { - aq_hw_write_reg(self, 0x328, p[offset]); + for (; data_offset < cnt; ++mbox_offset, ++data_offset) { + aq_hw_write_reg(self, 0x328, p[data_offset]); aq_hw_write_reg(self, 0x32C, - (0x80000000 | (0xFFFF & (offset * 4)))); + (0x80000000 | (0xFFFF & (mbox_offset * 4)))); hw_atl_mcp_up_force_intr_set(self, 1); /* 1000 times by 10us = 10ms */ AQ_HW_WAIT_FOR((aq_hw_read_reg(self, @@ -462,8 +468,6 @@ int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self, goto err_exit; } } while (sw.tid != fw.tid || 0xFFFFU == fw.len); - if (err < 0) - goto err_exit; if (rpc) { if (fw.len) { @@ -875,8 +879,7 @@ static int aq_fw1x_set_wol(struct aq_hw_s *self, bool wol_enabled, u8 *mac) } err = hw_atl_utils_fw_rpc_call(self, rpc_size); - if (err < 0) - goto err_exit; + err_exit: return err; } diff --git a/drivers/net/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/atlantic/hw_atl/hw_atl_utils.h index 5f3f7084..b1f03f42 100644 --- a/drivers/net/atlantic/hw_atl/hw_atl_utils.h +++ b/drivers/net/atlantic/hw_atl/hw_atl_utils.h @@ -336,15 +336,8 @@ struct offload_info { u8 buf[0]; } __attribute__((__packed__)); -struct smbus_read_request { - u32 offset; /* not used */ - u32 device_id; - u32 address; - u32 length; -} __attribute__((__packed__)); - -struct smbus_write_request { - u32 offset; /* not used */ +struct smbus_request { + u32 msg_id; /* not used */ u32 device_id; u32 address; u32 length; @@ -389,8 +382,6 @@ enum hal_atl_utils_fw_state_e { #define HAL_ATLANTIC_UTILS_FW_MSG_OFFLOAD_DEL 10U #define HAL_ATLANTIC_UTILS_FW_MSG_CABLE_DIAG 13U // 0xd -#define SMBUS_READ_REQUEST BIT(13) -#define SMBUS_WRITE_REQUEST BIT(14) #define SMBUS_DEVICE_ID 0x50 enum hw_atl_fw2x_rate { @@ -414,6 +405,9 @@ enum hw_atl_fw2x_caps_lo { CAPS_LO_2P5GBASET_FD, CAPS_LO_5GBASET_FD, CAPS_LO_10GBASET_FD, + CAPS_LO_AUTONEG, + CAPS_LO_SMBUS_READ, + CAPS_LO_SMBUS_WRITE, }; enum hw_atl_fw2x_caps_hi { diff --git a/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c index 6841d9bc..11f14d1a 100644 --- a/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c +++ b/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c @@ -34,7 +34,6 @@ #define HAL_ATLANTIC_WOL_FILTERS_COUNT 8 #define HAL_ATLANTIC_UTILS_FW2X_MSG_WOL 0x0E -#define HW_ATL_FW_FEATURE_EEPROM 0x03010025 #define HW_ATL_FW_FEATURE_LED 0x03010026 struct fw2x_msg_wol_pattern { @@ -62,6 +61,7 @@ static int aq_fw2x_set_state(struct aq_hw_s *self, static int aq_fw2x_init(struct aq_hw_s *self) { int err = 0; + struct hw_aq_atl_utils_mbox mbox; /* check 10 times by 1ms */ AQ_HW_WAIT_FOR(0U != (self->mbox_addr = @@ -70,6 +70,12 @@ static int aq_fw2x_init(struct aq_hw_s *self) AQ_HW_WAIT_FOR(0U != (self->rpc_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_RPC_ADDR)), 1000U, 100U); + + /* Read caps */ + hw_atl_utils_mpi_read_stats(self, &mbox); + + self->caps_lo = mbox.info.caps_lo; + return err; } @@ -462,7 +468,15 @@ static int aq_fw2x_get_eee_rate(struct aq_hw_s *self, u32 *rate, return err; } +static int aq_fw2x_get_flow_control(struct aq_hw_s *self, u32 *fc) +{ + u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); + *fc = ((mpi_state & BIT(CAPS_HI_PAUSE)) ? AQ_NIC_FC_RX : 0) | + ((mpi_state & BIT(CAPS_HI_ASYMMETRIC_PAUSE)) ? AQ_NIC_FC_TX : 0); + + return 0; +} static int aq_fw2x_set_flow_control(struct aq_hw_s *self) { @@ -484,38 +498,42 @@ static int aq_fw2x_led_control(struct aq_hw_s *self, u32 mode) return 0; } -static int aq_fw2x_get_eeprom(struct aq_hw_s *self, u32 *data, u32 len) +static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr, + u32 *data, u32 len, u32 offset) { - int err = 0; - struct smbus_read_request request; - u32 mpi_opts; + u32 bytes_remains = len % sizeof(u32); + u32 num_dwords = len / sizeof(u32); + struct smbus_request request; u32 result = 0; + u32 mpi_opts; + int err = 0; - if (self->fw_ver_actual < HW_ATL_FW_FEATURE_EEPROM) + if ((self->caps_lo & BIT(CAPS_LO_SMBUS_READ)) == 0) return -EOPNOTSUPP; - request.device_id = SMBUS_DEVICE_ID; - request.address = 0; + request.msg_id = 0; + request.device_id = dev_addr; + request.address = offset; request.length = len; /* Write SMBUS request to cfg memory */ err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr, (u32 *)(void *)&request, - RTE_ALIGN(sizeof(request), sizeof(u32))); + sizeof(request) / sizeof(u32)); if (err < 0) return err; - /* Toggle 0x368.SMBUS_READ_REQUEST bit */ + /* Toggle 0x368.CAPS_LO_SMBUS_READ bit */ mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR); - mpi_opts ^= SMBUS_READ_REQUEST; + mpi_opts ^= BIT(CAPS_LO_SMBUS_READ); aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, mpi_opts); /* Wait until REQUEST_BIT matched in 0x370 */ AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR) & - SMBUS_READ_REQUEST) == (mpi_opts & SMBUS_READ_REQUEST), + BIT(CAPS_LO_SMBUS_READ)) == (mpi_opts & BIT(CAPS_LO_SMBUS_READ)), 10U, 10000U); if (err < 0) @@ -523,64 +541,106 @@ static int aq_fw2x_get_eeprom(struct aq_hw_s *self, u32 *data, u32 len) err = hw_atl_utils_fw_downld_dwords(self, self->rpc_addr + sizeof(u32), &result, - RTE_ALIGN(sizeof(result), sizeof(u32))); + sizeof(result) / sizeof(u32)); if (err < 0) return err; - if (result == 0) { + if (result) + return -EIO; + + if (num_dwords) { err = hw_atl_utils_fw_downld_dwords(self, - self->rpc_addr + sizeof(u32) * 2, - data, - RTE_ALIGN(len, sizeof(u32))); + self->rpc_addr + sizeof(u32) * 2, + data, + num_dwords); if (err < 0) return err; } + if (bytes_remains) { + u32 val = 0; + + err = hw_atl_utils_fw_downld_dwords(self, + self->rpc_addr + (sizeof(u32) * 2) + + (num_dwords * sizeof(u32)), + &val, + 1); + + if (err < 0) + return err; + + rte_memcpy((u8 *)data + len - bytes_remains, + &val, bytes_remains); + } + return 0; } -static int aq_fw2x_set_eeprom(struct aq_hw_s *self, u32 *data, u32 len) +static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr, + u32 *data, u32 len, u32 offset) { - struct smbus_write_request request; + struct smbus_request request; u32 mpi_opts, result = 0; int err = 0; - if (self->fw_ver_actual < HW_ATL_FW_FEATURE_EEPROM) + if ((self->caps_lo & BIT(CAPS_LO_SMBUS_WRITE)) == 0) return -EOPNOTSUPP; - request.device_id = SMBUS_DEVICE_ID; - request.address = 0; + request.msg_id = 0; + request.device_id = dev_addr; + request.address = offset; request.length = len; /* Write SMBUS request to cfg memory */ err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr, (u32 *)(void *)&request, - RTE_ALIGN(sizeof(request), sizeof(u32))); + sizeof(request) / sizeof(u32)); if (err < 0) return err; /* Write SMBUS data to cfg memory */ - err = hw_atl_utils_fw_upload_dwords(self, - self->rpc_addr + sizeof(request), - (u32 *)(void *)data, - RTE_ALIGN(len, sizeof(u32))); + u32 num_dwords = len / sizeof(u32); + u32 bytes_remains = len % sizeof(u32); - if (err < 0) - return err; + if (num_dwords) { + err = hw_atl_utils_fw_upload_dwords(self, + self->rpc_addr + sizeof(request), + (u32 *)(void *)data, + num_dwords); + + if (err < 0) + return err; + } - /* Toggle 0x368.SMBUS_WRITE_REQUEST bit */ + if (bytes_remains) { + u32 val = 0; + + rte_memcpy(&val, (u8 *)data + (sizeof(u32) * num_dwords), + bytes_remains); + + err = hw_atl_utils_fw_upload_dwords(self, + self->rpc_addr + sizeof(request) + + (num_dwords * sizeof(u32)), + &val, + 1); + + if (err < 0) + return err; + } + + /* Toggle 0x368.CAPS_LO_SMBUS_WRITE bit */ mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR); - mpi_opts ^= SMBUS_WRITE_REQUEST; + mpi_opts ^= BIT(CAPS_LO_SMBUS_WRITE); aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, mpi_opts); /* Wait until REQUEST_BIT matched in 0x370 */ AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR) & - SMBUS_WRITE_REQUEST) == (mpi_opts & SMBUS_WRITE_REQUEST), + BIT(CAPS_LO_SMBUS_WRITE)) == (mpi_opts & BIT(CAPS_LO_SMBUS_WRITE)), 10U, 10000U); if (err < 0) @@ -589,11 +649,14 @@ static int aq_fw2x_set_eeprom(struct aq_hw_s *self, u32 *data, u32 len) /* Read status of write operation */ err = hw_atl_utils_fw_downld_dwords(self, self->rpc_addr + sizeof(u32), &result, - RTE_ALIGN(sizeof(result), sizeof(u32))); + sizeof(result) / sizeof(u32)); if (err < 0) return err; + if (result) + return -EIO; + return 0; } @@ -611,6 +674,7 @@ const struct aq_fw_ops aq_fw_2x_ops = { .get_cable_len = aq_fw2x_get_cable_len, .set_eee_rate = aq_fw2x_set_eee_rate, .get_eee_rate = aq_fw2x_get_eee_rate, + .get_flow_control = aq_fw2x_get_flow_control, .set_flow_control = aq_fw2x_set_flow_control, .led_control = aq_fw2x_led_control, .get_eeprom = aq_fw2x_get_eeprom, -- cgit 1.2.3-korg