From patchwork Wed Sep 28 00:58:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Chan X-Patchwork-Id: 12991529 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EC731C6FA83 for ; Wed, 28 Sep 2022 00:59:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232103AbiI1A7R (ORCPT ); Tue, 27 Sep 2022 20:59:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55044 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231956AbiI1A7Q (ORCPT ); Tue, 27 Sep 2022 20:59:16 -0400 Received: from mail-qv1-xf36.google.com (mail-qv1-xf36.google.com [IPv6:2607:f8b0:4864:20::f36]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E6E98125792 for ; Tue, 27 Sep 2022 17:59:14 -0700 (PDT) Received: by mail-qv1-xf36.google.com with SMTP id j8so7249950qvt.13 for ; Tue, 27 Sep 2022 17:59:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; h=references:in-reply-to:message-id:date:subject:cc:to:from:from:to :cc:subject:date; bh=OHwAI3nnJ9ivn9YDdN080Pfup4Gs6WWT6rGnbUcF1Ro=; b=Dg9W8x8lQUG0wqb1+lmTKI2cRvFz9tuEPppS85xBjFXQwHdB0r3yEz/8JeKiIUlyVI i3/A7wuP0xjcPhNCSu7zjO+cOu+3fARYKyrP0rMVCw+u9uxPOxWLfkpmC1jcjnPb+wva FTE8gNPwGmeA1vHUFHSZC+UraEY3pYrlzFOjc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=references:in-reply-to:message-id:date:subject:cc:to:from :x-gm-message-state:from:to:cc:subject:date; bh=OHwAI3nnJ9ivn9YDdN080Pfup4Gs6WWT6rGnbUcF1Ro=; b=rMkyQFgjthxKkWj/o3RPxVnqU/ROcHGdk80kcTlL4FNHesHEPWPnMxwWdy0nKQAAhH nwF6RHJ2z2XUNfZArRwGx5mna3Kmt0kxnNzUKFLKGMwKnnSv0uJxkNisuLtZL+87oS2q btoiKCdr0x0cYnvlJLCkESYlDrEbSp53hGNmFMembDwCN5CQgR6bJlKxOMqgzn4LZwas FbuZPQ5uzQw3uZyxdkn2DacgIc4VE/oX3mJyeevpw2lA1MbZTFofK0FXchZ1+rdoAb+9 rvGPR9hiEN/yhAmaFmh3JU+Z53+nPK7ntzd9UztTbX3piMzU9InwHH1danDz3YxZjSPe MS1g== X-Gm-Message-State: ACrzQf38tjWT4oeEWxYwEfWS0mjsdBgU0t4p3lCOqLdP4ePoJNqPMRVB /j7akCR6+cJXa/8zy++7/Vnd0g== X-Google-Smtp-Source: AMsMyM7KnOHr3BVsfSg1/evOBm0gRk47o8ca7u5o6apB3IlMP5e0QI+oUfpLHoTIUdk6wNiYybeijA== X-Received: by 2002:ad4:4eae:0:b0:4af:9a04:ae3d with SMTP id ed14-20020ad44eae000000b004af9a04ae3dmr170100qvb.49.1664326753871; Tue, 27 Sep 2022 17:59:13 -0700 (PDT) Received: from localhost.swdvt.lab.broadcom.net ([192.19.223.252]) by smtp.gmail.com with ESMTPSA id i11-20020a05620a248b00b006cbb8ca04f8sm2078668qkn.40.2022.09.27.17.59.12 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 27 Sep 2022 17:59:13 -0700 (PDT) From: Michael Chan To: davem@davemloft.net Cc: netdev@vger.kernel.org, kuba@kernel.org, edumazet@google.com, pabeni@redhat.com, gospo@broadcom.com, vikas.gupta@broadcom.com Subject: [PATCH net-next 2/6] bnxt_en: add support for QSFP optional EEPROM data Date: Tue, 27 Sep 2022 20:58:40 -0400 Message-Id: <1664326724-1415-3-git-send-email-michael.chan@broadcom.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1664326724-1415-1-git-send-email-michael.chan@broadcom.com> References: <1664326724-1415-1-git-send-email-michael.chan@broadcom.com> Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org From: Edwin Peer SFF 8636 defines several optional pages. This patch adds support up to and including page 3. The ethtool offset needs to be mapped onto the appropriate device page and I2C address, which is handled differently depending on module type. The necessary linear offset to raw page mapping is performed based on a table that is configured according to the module capabilities. Signed-off-by: Edwin Peer Signed-off-by: Michael Chan --- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 5 + .../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 120 +++++++++++++++--- 2 files changed, 108 insertions(+), 17 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index b1b17f911300..c54f8c9ab3ad 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -2206,6 +2206,11 @@ struct bnxt { #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 static inline u32 bnxt_tx_avail(struct bnxt *bp, struct bnxt_tx_ring_info *txr) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index f57e524c7e30..6596dca94c3d 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -3220,7 +3220,9 @@ static int bnxt_get_module_info(struct net_device *dev, break; case SFF_MODULE_ID_QSFP28: modinfo->type = ETH_MODULE_SFF_8636; - modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; + modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN; + if (data[SFF8636_FLATMEM_OFFSET] & SFF8636_FLATMEM_MASK) + modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; break; default: rc = -EOPNOTSUPP; @@ -3234,32 +3236,116 @@ static int bnxt_get_module_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) { + u8 pg_addr[5] = { I2C_DEV_ADDR_A0, I2C_DEV_ADDR_A0 }; + u16 offset = eeprom->offset, length = eeprom->len; + u8 module_info[SFF_DIAG_SUPPORT_OFFSET + 1]; struct bnxt *bp = netdev_priv(dev); - u16 start = eeprom->offset, length = eeprom->len; + u8 page = offset >> 7; + u8 max_pages = 2; int rc = 0; - memset(data, 0, eeprom->len); + rc = bnxt_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: + 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: { + u8 opt_pages; - /* Read A0 portion of the EEPROM */ - if (start < ETH_MODULE_SFF_8436_LEN) { - if (start + eeprom->len > ETH_MODULE_SFF_8436_LEN) - length = ETH_MODULE_SFF_8436_LEN - start; rc = bnxt_read_sfp_module_eeprom_info(bp, I2C_DEV_ADDR_A0, 0, - start, length, data); + SFF8636_OPT_PAGES_OFFSET, + 1, &opt_pages); if (rc) return rc; - start += length; - data += length; - length = eeprom->len - length; + + 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, eeprom->len); - /* Read A2 portion of the EEPROM */ - if (length) { - start -= ETH_MODULE_SFF_8436_LEN; - rc = bnxt_read_sfp_module_eeprom_info(bp, I2C_DEV_ADDR_A2, 0, - start, length, data); + /* Read the two 128B base pages in a single pass, since they are + * always supported and both sourced from I2C_DEV_ADDR_A0. Then, + * read individual 128B or 256B chunks as appropriate, according + * to the mappings defined in pg_addr[], which is setup based on + * module capabilities. + * + * The first two pages are both numbered page zero, lower page 0 + * and upper page 0 respectively. Raw device pages are numbered + * sequentially thereafter. For SFP modules, reads are always + * from page zero. In this case, the A2 base address is used in + * lieu of the page number to signal reading the upper 256B, with + * offsets relative to the base of this larger I2C region. + * + * Note there may be gaps in the linear ethtool mapping that are + * not backed by raw module pages. Reads to such pages should not + * be attempted because the HWRM call would fail. The caller will + * simply see the preinitialized zeroes in these holes. + * + * Also note, the implementation below depends on pages mapped as + * I2C_DEV_ADDR_A2 in pg_addr[] appearing as 256B aligned pairs. + * This constraint means that it doesn't matter whether the even + * or odd page is used in determining the I2C base address of a + * given region. This allows for larger chunk sizes to be read + * for A2 pages and happens to correspond nicely with the memory + * maps of all currently supported modules. The optional 128B + * A0 pages need to be read relative to an offset of 128B, which + * is where they appear in module memory maps, while the 256B A2 + * page pair regions are interpreted by firmware relative to + * offset 0. + */ + offset &= 0xff; + while (length && page < max_pages) { + u8 raw_page = page ? page - 1 : 0; + u16 chunk; + + if (pg_addr[page] == I2C_DEV_ADDR_A2) + raw_page = 0; + else if (page) + offset |= 0x80; + chunk = min_t(u16, length, 256 - offset); + + if (pg_addr[page]) { + rc = bnxt_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 rc; + + if (length) + return -EINVAL; + + return 0; } static int bnxt_nway_reset(struct net_device *dev)