From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 163D5A0C4A; Wed, 16 Jun 2021 23:51:23 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 9333240683; Wed, 16 Jun 2021 23:51:22 +0200 (CEST) Received: from mail-qt1-f174.google.com (mail-qt1-f174.google.com [209.85.160.174]) by mails.dpdk.org (Postfix) with ESMTP id 357F24067A for ; Wed, 16 Jun 2021 23:51:21 +0200 (CEST) Received: by mail-qt1-f174.google.com with SMTP id o19so3131766qtp.5 for ; Wed, 16 Jun 2021 14:51:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=FknDI4lgLxXslGKrSpkZc4gsYNlX0ywa4JGWDe/amWc=; b=IJjyIuVHM/bZTOcyu/mjiClNY98PpsB6ShvNJpDCgbR+BqT9HOjyGcMlzU1FcBh19v Z18lMqCbNUPxmeH920LdX8pPs+8bunvOSym7HT5dB3WkT4XM6sSEmUyHehznQHF8JSaf F++iyoFQmzM6WwZAGpupwdSgghG6x55VxS0/Q= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=FknDI4lgLxXslGKrSpkZc4gsYNlX0ywa4JGWDe/amWc=; b=Xbf6Js4MCS4kS61oPyEt+54rchsxUe/DeCbO6KDf+JOkZ3sVenalRq3WYAGpEqMQjW WZ01uao5oKcW4wV9wyfTfuX0sK9iZCc2ikRrfYKy16rro8g/F91uDmyl4HIUATm9842X kPxu/Rkj4bDBsbkMyZnkIylgaYhj+n+PyR6aOyCaDY+u+3YtdNy6wjxKJ0kmoNULZ/rB Tkcy/ni9FNW5C+o4akz/lMJaxMT02IZFR/UAm4x5/xWLmCaMgptR0kkNLGt5THI3ej7j 2zkor8urBnF33TQnGg/p5gceSdC2UynVd+zsYOjhsFpp1QFAYkfy/DiouszIgvNheuvF Z9+A== X-Gm-Message-State: AOAM532aogmoaYLWNb6YZm+1IWIO0fmhRikAwzsT29WJek0/7hquUmh/ xFNeZ/ihTyAqeVXF3TMOJdeJhqss0ZIdYpEzecP3xQ== X-Google-Smtp-Source: ABdhPJxhwJxtFQy/c5gUbf6qWLJKKi/G03N+WYkhChQyR1nUQcqGWM30Owr+au/V/NsCmcqtGg5bX+aznLQ9TiX4zBc= X-Received: by 2002:ac8:505a:: with SMTP id h26mr1941130qtm.225.1623880280334; Wed, 16 Jun 2021 14:51:20 -0700 (PDT) MIME-Version: 1.0 References: <20210609024515.14534-1-kalesh-anakkur.purayil@broadcom.com> In-Reply-To: <20210609024515.14534-1-kalesh-anakkur.purayil@broadcom.com> From: Ajit Khaparde Date: Wed, 16 Jun 2021 14:51:03 -0700 Message-ID: To: Kalesh A P Cc: dpdk-dev , Ferruh Yigit Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-256; boundary="0000000000004b16ba05c4e917ba" X-Content-Filtered-By: Mailman/MimeDel 2.1.29 Subject: Re: [dpdk-dev] [PATCH] net/bnxt: add support to dump SFP module info X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" --0000000000004b16ba05c4e917ba Content-Type: text/plain; charset="UTF-8" On Tue, Jun 8, 2021 at 7:23 PM Kalesh A P wrote: > > From: Kalesh AP > > Add support to fetch the SFP EEPROM settings from the firmware. > For SFP+ modules we will display 0xA0 page for status and 0xA2 page > for other information. For QSFP modules we will show the 0xA0 page. > > Also identify the module types for QSFP28, QSFP, QSFP+ apart > from the SFP modules and return an error for 10GBase-T PHY. > > Signed-off-by: Kalesh AP > Reviewed-by: Somnath Kotur > Reviewed-by: Ajit Khaparde > Reviewed-by: Venkat Duvvuru Patch applied to the for-next-net branch of dpdk-next-net-brcm. > --- > doc/guides/nics/features/bnxt.ini | 1 + > drivers/net/bnxt/bnxt.h | 15 ++++ > drivers/net/bnxt/bnxt_ethdev.c | 145 +++++++++++++++++++++++++++++++++ > drivers/net/bnxt/bnxt_hwrm.c | 36 ++++++++ > drivers/net/bnxt/bnxt_hwrm.h | 3 + > drivers/net/bnxt/hsi_struct_def_dpdk.h | 83 +++++++++++++++++++ > 6 files changed, 283 insertions(+) > > diff --git a/doc/guides/nics/features/bnxt.ini b/doc/guides/nics/features/bnxt.ini > index 291faaa..b6eaca8 100644 > --- a/doc/guides/nics/features/bnxt.ini > +++ b/doc/guides/nics/features/bnxt.ini > @@ -42,6 +42,7 @@ Extended stats = Y > Stats per queue = Y > FW version = Y > EEPROM dump = Y > +Module EEPROM dump = Y > LED = Y > Multiprocess aware = Y > FreeBSD = Y > diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h > index e93a7eb..8ec8ddc 100644 > --- a/drivers/net/bnxt/bnxt.h > +++ b/drivers/net/bnxt/bnxt.h > @@ -292,6 +292,7 @@ struct bnxt_link_info { > uint16_t auto_pam4_link_speeds; > uint16_t support_pam4_auto_speeds; > uint8_t req_signal_mode; > + uint8_t module_status; > }; > > #define BNXT_COS_QUEUE_COUNT 8 > @@ -965,6 +966,20 @@ struct bnxt_vf_rep_tx_queue { > struct bnxt_representor *bp; > }; > > +#define I2C_DEV_ADDR_A0 0xa0 > +#define I2C_DEV_ADDR_A2 0xa2 > +#define SFF_DIAG_SUPPORT_OFFSET 0x5c > +#define SFF_MODULE_ID_SFP 0x3 > +#define SFF_MODULE_ID_QSFP 0xc > +#define SFF_MODULE_ID_QSFP_PLUS 0xd > +#define SFF_MODULE_ID_QSFP28 0x11 > +#define SFF8636_FLATMEM_OFFSET 0x2 > +#define SFF8636_FLATMEM_MASK 0x4 > +#define SFF8636_OPT_PAGES_OFFSET 0xc3 > +#define SFF8636_PAGE1_MASK 0x40 > +#define SFF8636_PAGE2_MASK 0x80 > +#define BNXT_MAX_PHY_I2C_RESP_SIZE 64 > + > int bnxt_mtu_set_op(struct rte_eth_dev *eth_dev, uint16_t new_mtu); > int bnxt_link_update(struct rte_eth_dev *eth_dev, int wait_to_complete, > bool exp_link_status); > diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c > index c9536f7..30aa0ef 100644 > --- a/drivers/net/bnxt/bnxt_ethdev.c > +++ b/drivers/net/bnxt/bnxt_ethdev.c > @@ -3851,6 +3851,149 @@ bnxt_set_eeprom_op(struct rte_eth_dev *dev, > in_eeprom->data, in_eeprom->length); > } > > +static int bnxt_get_module_info(struct rte_eth_dev *dev, > + struct rte_eth_dev_module_info *modinfo) > +{ > + uint8_t module_info[SFF_DIAG_SUPPORT_OFFSET + 1]; > + struct bnxt *bp = dev->data->dev_private; > + int rc; > + > + /* No point in going further if phy status indicates > + * module is not inserted or if it is powered down or > + * if it is of type 10GBase-T > + */ > + if (bp->link_info->module_status > > + HWRM_PORT_PHY_QCFG_OUTPUT_MODULE_STATUS_WARNINGMSG) { > + PMD_DRV_LOG(NOTICE, "Port %u : Module is not inserted or is powered down\n", > + dev->data->port_id); > + return -ENOTSUP; > + } > + > + /* This feature is not supported in older firmware versions */ > + if (bp->hwrm_spec_code < 0x10202) { > + PMD_DRV_LOG(NOTICE, "Port %u : Feature is not supported in older firmware\n", > + dev->data->port_id); > + return -ENOTSUP; > + } > + > + rc = bnxt_hwrm_read_sfp_module_eeprom_info(bp, I2C_DEV_ADDR_A0, 0, 0, > + SFF_DIAG_SUPPORT_OFFSET + 1, > + module_info); > + > + if (rc) > + return rc; > + > + switch (module_info[0]) { > + case SFF_MODULE_ID_SFP: > + modinfo->type = RTE_ETH_MODULE_SFF_8472; > + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN; > + if (module_info[SFF_DIAG_SUPPORT_OFFSET] == 0) > + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8436_LEN; > + break; > + case SFF_MODULE_ID_QSFP: > + case SFF_MODULE_ID_QSFP_PLUS: > + modinfo->type = RTE_ETH_MODULE_SFF_8436; > + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8436_LEN; > + break; > + case SFF_MODULE_ID_QSFP28: > + modinfo->type = RTE_ETH_MODULE_SFF_8636; > + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8636_MAX_LEN; > + if (module_info[SFF8636_FLATMEM_OFFSET] & SFF8636_FLATMEM_MASK) > + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8636_LEN; > + break; > + default: > + PMD_DRV_LOG(NOTICE, "Port %u : Unsupported module\n", dev->data->port_id); > + return -ENOTSUP; > + } > + > + PMD_DRV_LOG(INFO, "Port %u : modinfo->type = %d modinfo->eeprom_len = %d\n", > + dev->data->port_id, modinfo->type, modinfo->eeprom_len); > + > + return 0; > +} > + > +static int bnxt_get_module_eeprom(struct rte_eth_dev *dev, > + struct rte_dev_eeprom_info *info) > +{ > + uint8_t pg_addr[5] = { I2C_DEV_ADDR_A0, I2C_DEV_ADDR_A0 }; > + uint32_t offset = info->offset, length = info->length; > + uint8_t module_info[SFF_DIAG_SUPPORT_OFFSET + 1]; > + struct bnxt *bp = dev->data->dev_private; > + uint8_t *data = info->data; > + uint8_t page = offset >> 7; > + uint8_t max_pages = 2; > + uint8_t opt_pages; > + int rc; > + > + rc = bnxt_hwrm_read_sfp_module_eeprom_info(bp, I2C_DEV_ADDR_A0, 0, 0, > + SFF_DIAG_SUPPORT_OFFSET + 1, > + module_info); > + if (rc) > + return rc; > + > + switch (module_info[0]) { > + case SFF_MODULE_ID_SFP: > + module_info[SFF_DIAG_SUPPORT_OFFSET] = 0; > + if (module_info[SFF_DIAG_SUPPORT_OFFSET]) { > + pg_addr[2] = I2C_DEV_ADDR_A2; > + pg_addr[3] = I2C_DEV_ADDR_A2; > + max_pages = 4; > + } > + break; > + case SFF_MODULE_ID_QSFP28: > + rc = bnxt_hwrm_read_sfp_module_eeprom_info(bp, I2C_DEV_ADDR_A0, 0, > + SFF8636_OPT_PAGES_OFFSET, > + 1, &opt_pages); > + if (rc) > + return rc; > + > + if (opt_pages & SFF8636_PAGE1_MASK) { > + pg_addr[2] = I2C_DEV_ADDR_A0; > + max_pages = 3; > + } > + if (opt_pages & SFF8636_PAGE2_MASK) { > + pg_addr[3] = I2C_DEV_ADDR_A0; > + max_pages = 4; > + } > + if (~module_info[SFF8636_FLATMEM_OFFSET] & SFF8636_FLATMEM_MASK) { > + pg_addr[4] = I2C_DEV_ADDR_A0; > + max_pages = 5; > + } > + break; > + default: > + break; > + } > + > + memset(data, 0, length); > + > + offset &= 0xff; > + while (length && page < max_pages) { > + uint8_t raw_page = page ? page - 1 : 0; > + uint16_t chunk; > + > + if (pg_addr[page] == I2C_DEV_ADDR_A2) > + raw_page = 0; > + else if (page) > + offset |= 0x80; > + chunk = RTE_MIN(length, 256 - offset); > + > + if (pg_addr[page]) { > + rc = bnxt_hwrm_read_sfp_module_eeprom_info(bp, pg_addr[page], > + raw_page, offset, > + chunk, data); > + if (rc) > + return rc; > + } > + > + data += chunk; > + length -= chunk; > + offset = 0; > + page += 1 + (chunk > 128); > + } > + > + return length ? -EINVAL : 0; > +} > + > /* > * Initialization > */ > @@ -3912,6 +4055,8 @@ static const struct eth_dev_ops bnxt_dev_ops = { > .get_eeprom_length = bnxt_get_eeprom_length_op, > .get_eeprom = bnxt_get_eeprom_op, > .set_eeprom = bnxt_set_eeprom_op, > + .get_module_info = bnxt_get_module_info, > + .get_module_eeprom = bnxt_get_module_eeprom, > .timesync_enable = bnxt_timesync_enable, > .timesync_disable = bnxt_timesync_disable, > .timesync_read_time = bnxt_timesync_read_time, > diff --git a/drivers/net/bnxt/bnxt_hwrm.c b/drivers/net/bnxt/bnxt_hwrm.c > index a65ac6c..31f1d31 100644 > --- a/drivers/net/bnxt/bnxt_hwrm.c > +++ b/drivers/net/bnxt/bnxt_hwrm.c > @@ -1502,6 +1502,7 @@ static int bnxt_hwrm_port_phy_qcfg(struct bnxt *bp, > rte_le_to_cpu_16(resp->support_pam4_speeds); > link_info->auto_pam4_link_speeds = > rte_le_to_cpu_16(resp->auto_pam4_link_speed_mask); > + link_info->module_status = resp->module_status; > HWRM_UNLOCK(); > > PMD_DRV_LOG(DEBUG, "Link Speed:%d,Auto:%d:%x:%x,Support:%x,Force:%x\n", > @@ -6157,3 +6158,38 @@ int bnxt_hwrm_poll_ver_get(struct bnxt *bp) > > return rc; > } > + > +int bnxt_hwrm_read_sfp_module_eeprom_info(struct bnxt *bp, uint16_t i2c_addr, > + uint16_t page_number, uint16_t start_addr, > + uint16_t data_length, uint8_t *buf) > +{ > + struct hwrm_port_phy_i2c_read_output *resp = bp->hwrm_cmd_resp_addr; > + struct hwrm_port_phy_i2c_read_input req = {0}; > + uint32_t enables = HWRM_PORT_PHY_I2C_READ_INPUT_ENABLES_PAGE_OFFSET; > + int rc, byte_offset = 0; > + > + do { > + uint16_t xfer_size; > + > + HWRM_PREP(&req, HWRM_PORT_PHY_I2C_READ, BNXT_USE_CHIMP_MB); > + req.i2c_slave_addr = i2c_addr; > + req.page_number = rte_cpu_to_le_16(page_number); > + req.port_id = rte_cpu_to_le_16(bp->pf->port_id); > + > + xfer_size = RTE_MIN(data_length, BNXT_MAX_PHY_I2C_RESP_SIZE); > + req.page_offset = rte_cpu_to_le_16(start_addr + byte_offset); > + req.data_length = xfer_size; > + req.enables = rte_cpu_to_le_32(start_addr + byte_offset ? enables : 0); > + rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB); > + HWRM_CHECK_RESULT(); > + > + memcpy(buf + byte_offset, resp->data, xfer_size); > + > + data_length -= xfer_size; > + byte_offset += xfer_size; > + > + HWRM_UNLOCK(); > + } while (data_length > 0); > + > + return rc; > +} > diff --git a/drivers/net/bnxt/bnxt_hwrm.h b/drivers/net/bnxt/bnxt_hwrm.h > index b60aa0c..057f7f9 100644 > --- a/drivers/net/bnxt/bnxt_hwrm.h > +++ b/drivers/net/bnxt/bnxt_hwrm.h > @@ -301,4 +301,7 @@ int bnxt_hwrm_poll_ver_get(struct bnxt *bp); > int bnxt_hwrm_rx_ring_reset(struct bnxt *bp, int queue_index); > int bnxt_hwrm_ring_stats(struct bnxt *bp, uint32_t cid, int idx, > struct bnxt_ring_stats *stats, bool rx); > +int bnxt_hwrm_read_sfp_module_eeprom_info(struct bnxt *bp, uint16_t i2c_addr, > + uint16_t page_number, uint16_t start_addr, > + uint16_t data_length, uint8_t *buf); > #endif > diff --git a/drivers/net/bnxt/hsi_struct_def_dpdk.h b/drivers/net/bnxt/hsi_struct_def_dpdk.h > index aea9305..7428c9c 100644 > --- a/drivers/net/bnxt/hsi_struct_def_dpdk.h > +++ b/drivers/net/bnxt/hsi_struct_def_dpdk.h > @@ -48625,4 +48625,87 @@ struct hcomm_status { > } __rte_packed; > /* This is the GRC offset where the hcomm_status struct resides. */ > #define HCOMM_STATUS_STRUCT_LOC 0x31001F0UL > + > +/************************** > + * hwrm_port_phy_i2c_read * > + **************************/ > + > + > +/* hwrm_port_phy_i2c_read_input (size:320b/40B) */ > +struct hwrm_port_phy_i2c_read_input { > + /* The HWRM command request type. */ > + uint16_t req_type; > + /* > + * The completion ring to send the completion event on. This should > + * be the NQ ID returned from the `nq_alloc` HWRM command. > + */ > + uint16_t cmpl_ring; > + /* > + * The sequence ID is used by the driver for tracking multiple > + * commands. This ID is treated as opaque data by the firmware and > + * the value is returned in the `hwrm_resp_hdr` upon completion. > + */ > + uint16_t seq_id; > + /* > + * The target ID of the command: > + * * 0x0-0xFFF8 - The function ID > + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors > + * * 0xFFFD - Reserved for user-space HWRM interface > + * * 0xFFFF - HWRM > + */ > + uint16_t target_id; > + /* > + * A physical address pointer pointing to a host buffer that the > + * command's response data will be written. This can be either a host > + * physical address (HPA) or a guest physical address (GPA) and must > + * point to a physically contiguous block of memory. > + */ > + uint64_t resp_addr; > + uint32_t flags; > + uint32_t enables; > + /* > + * This bit must be '1' for the page_offset field to be > + * configured. > + */ > + #define HWRM_PORT_PHY_I2C_READ_INPUT_ENABLES_PAGE_OFFSET 0x1UL > + /* Port ID of port. */ > + uint16_t port_id; > + /* 8-bit I2C slave address. */ > + uint8_t i2c_slave_addr; > + uint8_t unused_0; > + /* The page number that is being accessed over I2C. */ > + uint16_t page_number; > + /* Offset within the page that is being accessed over I2C. */ > + uint16_t page_offset; > + /* > + * Length of data to read, in bytes starting at the offset > + * specified above. If the offset is not specified, then > + * the data shall be read from the beginning of the page. > + */ > + uint8_t data_length; > + uint8_t unused_1[7]; > +} __rte_packed; > + > +/* hwrm_port_phy_i2c_read_output (size:640b/80B) */ > +struct hwrm_port_phy_i2c_read_output { > + /* The specific error status for the command. */ > + uint16_t error_code; > + /* The HWRM command request type. */ > + uint16_t req_type; > + /* The sequence ID from the original command. */ > + uint16_t seq_id; > + /* The length of the response data in number of bytes. */ > + uint16_t resp_len; > + /* Up to 64B of data. */ > + uint32_t data[16]; > + uint8_t unused_0[7]; > + /* > + * This field is used in Output records to indicate that the output > + * is completely written to RAM. This field should be read as '1' > + * to indicate that the output has been completely written. > + * When writing a command completion or response to an internal processor, > + * the order of writes has to be such that this field is written last. > + */ > + uint8_t valid; > +} __rte_packed; > #endif /* _HSI_STRUCT_DEF_DPDK_H_ */ > -- > 2.10.1 > --0000000000004b16ba05c4e917ba--