diff options
Diffstat (limited to 'drivers/net/atlantic')
-rw-r--r-- | drivers/net/atlantic/atl_ethdev.c | 106 | ||||
-rw-r--r-- | drivers/net/atlantic/atl_rxtx.c | 21 | ||||
-rw-r--r-- | drivers/net/atlantic/atl_types.h | 9 | ||||
-rw-r--r-- | drivers/net/atlantic/hw_atl/hw_atl_b0.c | 14 | ||||
-rw-r--r-- | drivers/net/atlantic/hw_atl/hw_atl_b0.h | 2 | ||||
-rw-r--r-- | drivers/net/atlantic/hw_atl/hw_atl_utils.c | 19 | ||||
-rw-r--r-- | drivers/net/atlantic/hw_atl/hw_atl_utils.h | 16 | ||||
-rw-r--r-- | drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c | 130 |
8 files changed, 205 insertions, 112 deletions
diff --git a/drivers/net/atlantic/atl_ethdev.c b/drivers/net/atlantic/atl_ethdev.c index 5bc04f55..2d05bb4c 100644 --- a/drivers/net/atlantic/atl_ethdev.c +++ b/drivers/net/atlantic/atl_ethdev.c @@ -165,7 +165,8 @@ static struct rte_pci_driver rte_atl_pmd = { | DEV_RX_OFFLOAD_IPV4_CKSUM \ | DEV_RX_OFFLOAD_UDP_CKSUM \ | DEV_RX_OFFLOAD_TCP_CKSUM \ - | DEV_RX_OFFLOAD_JUMBO_FRAME) + | DEV_RX_OFFLOAD_JUMBO_FRAME \ + | DEV_RX_OFFLOAD_VLAN_FILTER) #define ATL_TX_OFFLOADS (DEV_TX_OFFLOAD_VLAN_INSERT \ | DEV_TX_OFFLOAD_IPV4_CKSUM \ @@ -174,6 +175,8 @@ static struct rte_pci_driver rte_atl_pmd = { | DEV_TX_OFFLOAD_TCP_TSO \ | DEV_TX_OFFLOAD_MULTI_SEGS) +#define SFP_EEPROM_SIZE 0x100 + static const struct rte_eth_desc_lim rx_desc_lim = { .nb_max = ATL_MAX_RING_DESC, .nb_min = ATL_MIN_RING_DESC, @@ -465,8 +468,6 @@ atl_dev_start(struct rte_eth_dev *dev) struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; uint32_t intr_vector = 0; - uint32_t *link_speeds; - uint32_t speed = 0; int status; int err; @@ -543,6 +544,8 @@ atl_dev_start(struct rte_eth_dev *dev) goto error; } + err = atl_dev_set_link_up(dev); + err = hw->aq_fw_ops->update_link_status(hw); if (err) @@ -550,26 +553,6 @@ atl_dev_start(struct rte_eth_dev *dev) dev->data->dev_link.link_status = hw->aq_link_status.mbps != 0; - link_speeds = &dev->data->dev_conf.link_speeds; - - speed = 0x0; - - if (*link_speeds == ETH_LINK_SPEED_AUTONEG) { - speed = hw->aq_nic_cfg->link_speed_msk; - } else { - if (*link_speeds & ETH_LINK_SPEED_10G) - speed |= AQ_NIC_RATE_10G; - if (*link_speeds & ETH_LINK_SPEED_5G) - speed |= AQ_NIC_RATE_5G; - if (*link_speeds & ETH_LINK_SPEED_1G) - speed |= AQ_NIC_RATE_1G; - if (*link_speeds & ETH_LINK_SPEED_2_5G) - speed |= AQ_NIC_RATE_2G5; - if (*link_speeds & ETH_LINK_SPEED_100M) - speed |= AQ_NIC_RATE_100M; - } - - err = hw->aq_fw_ops->set_link_speed(hw, speed); if (err) goto error; @@ -657,9 +640,25 @@ static int atl_dev_set_link_up(struct rte_eth_dev *dev) { struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t link_speeds = dev->data->dev_conf.link_speeds; + uint32_t speed_mask = 0; + + if (link_speeds == ETH_LINK_SPEED_AUTONEG) { + speed_mask = hw->aq_nic_cfg->link_speed_msk; + } else { + if (link_speeds & ETH_LINK_SPEED_10G) + speed_mask |= AQ_NIC_RATE_10G; + if (link_speeds & ETH_LINK_SPEED_5G) + speed_mask |= AQ_NIC_RATE_5G; + if (link_speeds & ETH_LINK_SPEED_1G) + speed_mask |= AQ_NIC_RATE_1G; + if (link_speeds & ETH_LINK_SPEED_2_5G) + speed_mask |= AQ_NIC_RATE_2G5; + if (link_speeds & ETH_LINK_SPEED_100M) + speed_mask |= AQ_NIC_RATE_100M; + } - return hw->aq_fw_ops->set_link_speed(hw, - hw->aq_nic_cfg->link_speed_msk); + return hw->aq_fw_ops->set_link_speed(hw, speed_mask); } /* @@ -761,7 +760,7 @@ atl_dev_xstats_get_names(struct rte_eth_dev *dev __rte_unused, snprintf(xstats_names[i].name, RTE_ETH_XSTATS_NAME_SIZE, "%s", atl_xstats_tbl[i].name); - return size; + return i; } static int @@ -781,7 +780,7 @@ atl_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *stats, atl_xstats_tbl[i].offset); } - return n; + return i; } static int @@ -879,6 +878,7 @@ atl_dev_link_update(struct rte_eth_dev *dev, int wait __rte_unused) struct atl_interrupt *intr = ATL_DEV_PRIVATE_TO_INTR(dev->data->dev_private); struct rte_eth_link link, old; + u32 fc = AQ_NIC_FC_OFF; int err = 0; link.link_status = ETH_LINK_DOWN; @@ -915,6 +915,15 @@ atl_dev_link_update(struct rte_eth_dev *dev, int wait __rte_unused) if (link.link_status == old.link_status) return -1; + /* Driver has to update flow control settings on RX block + * on any link event. + * We should query FW whether it negotiated FC. + */ + if (hw->aq_fw_ops->get_flow_control) { + hw->aq_fw_ops->get_flow_control(hw, &fc); + hw_atl_b0_set_fc(hw, fc, 0U); + } + return 0; } @@ -1094,8 +1103,6 @@ atl_dev_interrupt_handler(void *param) atl_dev_interrupt_action(dev, dev->intr_handle); } -#define SFP_EEPROM_SIZE 0xff - static int atl_dev_get_eeprom_length(struct rte_eth_dev *dev __rte_unused) { @@ -1106,28 +1113,46 @@ static int atl_dev_get_eeprom(struct rte_eth_dev *dev, struct rte_dev_eeprom_info *eeprom) { struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + int dev_addr = SMBUS_DEVICE_ID; if (hw->aq_fw_ops->get_eeprom == NULL) return -ENOTSUP; - if (eeprom->length != SFP_EEPROM_SIZE || eeprom->data == NULL) + if (eeprom->length + eeprom->offset > SFP_EEPROM_SIZE || + eeprom->data == NULL) + return -EINVAL; + + if (eeprom->magic > 0x7F) return -EINVAL; - return hw->aq_fw_ops->get_eeprom(hw, eeprom->data, eeprom->length); + if (eeprom->magic) + dev_addr = eeprom->magic; + + return hw->aq_fw_ops->get_eeprom(hw, dev_addr, eeprom->data, + eeprom->length, eeprom->offset); } static int atl_dev_set_eeprom(struct rte_eth_dev *dev, struct rte_dev_eeprom_info *eeprom) { struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + int dev_addr = SMBUS_DEVICE_ID; if (hw->aq_fw_ops->set_eeprom == NULL) return -ENOTSUP; - if (eeprom->length != SFP_EEPROM_SIZE || eeprom->data == NULL) + if (eeprom->length + eeprom->offset > SFP_EEPROM_SIZE || + eeprom->data == NULL) + return -EINVAL; + + if (eeprom->magic > 0x7F) return -EINVAL; - return hw->aq_fw_ops->set_eeprom(hw, eeprom->data, eeprom->length); + if (eeprom->magic) + dev_addr = eeprom->magic; + + return hw->aq_fw_ops->set_eeprom(hw, dev_addr, eeprom->data, + eeprom->length, eeprom->offset); } static int @@ -1160,16 +1185,21 @@ static int atl_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) { struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + u32 fc = AQ_NIC_FC_OFF; + + if (hw->aq_fw_ops->get_flow_control == NULL) + return -ENOTSUP; + + hw->aq_fw_ops->get_flow_control(hw, &fc); - if (hw->aq_nic_cfg->flow_control == AQ_NIC_FC_OFF) + if (fc == AQ_NIC_FC_OFF) fc_conf->mode = RTE_FC_NONE; - else if (hw->aq_nic_cfg->flow_control & (AQ_NIC_FC_RX | AQ_NIC_FC_TX)) + else if ((fc & AQ_NIC_FC_RX) && (fc & AQ_NIC_FC_TX)) fc_conf->mode = RTE_FC_FULL; - else if (hw->aq_nic_cfg->flow_control & AQ_NIC_FC_RX) + else if (fc & AQ_NIC_FC_RX) fc_conf->mode = RTE_FC_RX_PAUSE; - else if (hw->aq_nic_cfg->flow_control & AQ_NIC_FC_RX) + else if (fc & AQ_NIC_FC_TX) fc_conf->mode = RTE_FC_TX_PAUSE; - return 0; } diff --git a/drivers/net/atlantic/atl_rxtx.c b/drivers/net/atlantic/atl_rxtx.c index 40c91379..fe007704 100644 --- a/drivers/net/atlantic/atl_rxtx.c +++ b/drivers/net/atlantic/atl_rxtx.c @@ -812,12 +812,12 @@ atl_prep_pkts(__rte_unused void *tx_queue, struct rte_mbuf **tx_pkts, ol_flags = m->ol_flags; if (m->nb_segs > AQ_HW_MAX_SEGS_SIZE) { - rte_errno = -EINVAL; + rte_errno = EINVAL; return i; } if (ol_flags & ATL_TX_OFFLOAD_NOTSUP_MASK) { - rte_errno = -ENOTSUP; + rte_errno = ENOTSUP; return i; } @@ -946,7 +946,7 @@ atl_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) break; } - PMD_RX_LOG(ERR, "port_id=%u queue_id=%u tail=%u " + PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u tail=%u " "eop=0x%x pkt_len=%u hash=0x%x hash_type=0x%x", (unsigned int)rxq->port_id, (unsigned int)rxq->queue_id, @@ -981,7 +981,7 @@ atl_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) while (true) { new_mbuf = rte_mbuf_raw_alloc(rxq->mb_pool); if (new_mbuf == NULL) { - PMD_RX_LOG(ERR, + PMD_RX_LOG(DEBUG, "RX mbuf alloc failed port_id=%u " "queue_id=%u", (unsigned int)rxq->port_id, (unsigned int)rxq->queue_id); @@ -1084,7 +1084,7 @@ atl_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) adapter->sw_stats.q_ibytes[rxq->queue_id] += rx_mbuf_first->pkt_len; - PMD_RX_LOG(ERR, "add mbuf segs=%d pkt_len=%d", + PMD_RX_LOG(DEBUG, "add mbuf segs=%d pkt_len=%d", rx_mbuf_first->nb_segs, rx_mbuf_first->pkt_len); } @@ -1104,7 +1104,7 @@ err_stop: */ nb_hold = (uint16_t)(nb_hold + rxq->nb_rx_hold); if (nb_hold > rxq->rx_free_thresh) { - PMD_RX_LOG(ERR, "port_id=%u queue_id=%u rx_tail=%u " + PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_tail=%u " "nb_hold=%u nb_rx=%u", (unsigned int)rxq->port_id, (unsigned int)rxq->queue_id, (unsigned int)tail, (unsigned int)nb_hold, @@ -1129,8 +1129,6 @@ atl_xmit_cleanup(struct atl_tx_queue *txq) struct hw_atl_txd_s *txd; int to_clean = 0; - PMD_INIT_FUNC_TRACE(); - if (txq != NULL) { sw_ring = txq->sw_ring; int head = txq->tx_head; @@ -1181,11 +1179,7 @@ atl_tso_setup(struct rte_mbuf *tx_pkt, union hw_atl_txc_s *txc) uint32_t tx_cmd = 0; uint64_t ol_flags = tx_pkt->ol_flags; - PMD_INIT_FUNC_TRACE(); - if (ol_flags & PKT_TX_TCP_SEG) { - PMD_DRV_LOG(DEBUG, "xmit TSO pkt"); - tx_cmd |= tx_desc_cmd_lso | tx_desc_cmd_l4cs; txc->cmd = 0x4; @@ -1240,8 +1234,6 @@ atl_xmit_pkt(struct aq_hw_s *hw, struct atl_tx_queue *txq, u32 tx_cmd = 0U; int desc_count = 0; - PMD_INIT_FUNC_TRACE(); - tail = txq->tx_tail; txc = (union hw_atl_txc_s *)&txq->hw_ring[tail]; @@ -1356,4 +1348,3 @@ atl_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) return nb_tx; } - diff --git a/drivers/net/atlantic/atl_types.h b/drivers/net/atlantic/atl_types.h index 3d90f6ca..c53d5896 100644 --- a/drivers/net/atlantic/atl_types.h +++ b/drivers/net/atlantic/atl_types.h @@ -94,6 +94,8 @@ struct aq_hw_s { struct hw_atl_stats_s last_stats; struct aq_stats_s curr_stats; + u32 caps_lo; + u64 speed; unsigned int chip_features; u32 fw_ver_actual; @@ -133,13 +135,16 @@ struct aq_fw_ops { int (*get_eee_rate)(struct aq_hw_s *self, u32 *rate, u32 *supported_rates); + int (*get_flow_control)(struct aq_hw_s *self, u32 *fc); int (*set_flow_control)(struct aq_hw_s *self); int (*led_control)(struct aq_hw_s *self, u32 mode); - int (*get_eeprom)(struct aq_hw_s *self, u32 *data, u32 len); + int (*get_eeprom)(struct aq_hw_s *self, int dev_addr, + u32 *data, u32 len, u32 offset); - int (*set_eeprom)(struct aq_hw_s *self, u32 *data, u32 len); + int (*set_eeprom)(struct aq_hw_s *self, int dev_addr, + u32 *data, u32 len, u32 offset); }; struct atl_sw_stats { 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, |