From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jeff Kirsher Subject: [net-next 05/13] igb: Support to read and export SFF-8472/8079 data Date: Thu, 4 Apr 2013 04:37:52 -0700 Message-ID: <1365075480-20183-6-git-send-email-jeffrey.t.kirsher@intel.com> References: <1365075480-20183-1-git-send-email-jeffrey.t.kirsher@intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: QUOTED-PRINTABLE Cc: "Akeem G. Abodunrin" , netdev@vger.kernel.org, gospo@redhat.com, sassmann@redhat.com, =?UTF-8?q?Aur=C3=A9lien=20Guillaume?= , Jeff Kirsher To: davem@davemloft.net Return-path: Received: from mga02.intel.com ([134.134.136.20]:25690 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758849Ab3DDLiX (ORCPT ); Thu, 4 Apr 2013 07:38:23 -0400 In-Reply-To: <1365075480-20183-1-git-send-email-jeffrey.t.kirsher@intel.com> Sender: netdev-owner@vger.kernel.org List-ID: =46rom: "Akeem G. Abodunrin" This patch adds support to read and export SFF-8472/8079 (SFP data) over i2c, through Ethtool. CC: Aur=C3=A9lien Guillaume Reported-by: Aur=C3=A9lien Guillaume Signed-off-by: Akeem G Abodunrin Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb.h | 8 +++ drivers/net/ethernet/intel/igb/igb_ethtool.c | 84 ++++++++++++++++++++= ++++++++ 2 files changed, 92 insertions(+) diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/etherne= t/intel/igb/igb.h index 2515140..7cb0398 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -178,6 +178,14 @@ enum igb_tx_flags { #define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IGB_MAX_DATA_PER_TXD) #define DESC_NEEDED (MAX_SKB_FRAGS + 4) =20 +/* EEPROM byte offsets */ +#define IGB_SFF_8472_SWAP 0x5C +#define IGB_SFF_8472_COMP 0x5E + +/* Bitmasks */ +#define IGB_SFF_ADDRESSING_MODE 0x4 +#define IGB_SFF_8472_UNSUP 0x00 + /* wrapper around a pointer to a socket buffer, * so a DMA handle can be stored along with the buffer */ struct igb_tx_buffer { diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net= /ethernet/intel/igb/igb_ethtool.c index 8499c48..17443e4 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -2622,6 +2622,88 @@ static int igb_set_eee(struct net_device *netdev= , return 0; } =20 +static int igb_get_module_info(struct net_device *netdev, + struct ethtool_modinfo *modinfo) +{ + struct igb_adapter *adapter =3D netdev_priv(netdev); + struct e1000_hw *hw =3D &adapter->hw; + u32 status =3D E1000_SUCCESS; + u16 sff8472_rev, addr_mode; + bool page_swap =3D false; + + if ((hw->phy.media_type =3D=3D e1000_media_type_copper) || + (hw->phy.media_type =3D=3D e1000_media_type_unknown)) + return -EOPNOTSUPP; + + /* Check whether we support SFF-8472 or not */ + status =3D igb_read_phy_reg_i2c(hw, IGB_SFF_8472_COMP, &sff8472_rev); + if (status !=3D E1000_SUCCESS) + return -EIO; + + /* addressing mode is not supported */ + status =3D igb_read_phy_reg_i2c(hw, IGB_SFF_8472_SWAP, &addr_mode); + if (status !=3D E1000_SUCCESS) + return -EIO; + + /* addressing mode is not supported */ + if ((addr_mode & 0xFF) & IGB_SFF_ADDRESSING_MODE) { + hw_dbg("Address change required to access page 0xA2, but not support= ed. Please report the module type to the driver maintainers.\n"); + page_swap =3D true; + } + + if ((sff8472_rev & 0xFF) =3D=3D IGB_SFF_8472_UNSUP || page_swap) { + /* We have an SFP, but it does not support SFF-8472 */ + modinfo->type =3D ETH_MODULE_SFF_8079; + modinfo->eeprom_len =3D ETH_MODULE_SFF_8079_LEN; + } else { + /* We have an SFP which supports a revision of SFF-8472 */ + modinfo->type =3D ETH_MODULE_SFF_8472; + modinfo->eeprom_len =3D ETH_MODULE_SFF_8472_LEN; + } + + return 0; +} + +static int igb_get_module_eeprom(struct net_device *netdev, + struct ethtool_eeprom *ee, u8 *data) +{ + struct igb_adapter *adapter =3D netdev_priv(netdev); + struct e1000_hw *hw =3D &adapter->hw; + u32 status =3D E1000_SUCCESS; + u16 dataword =3D 0xFF; + int i =3D 0; + + /* Read the first block, SFF-8079, 2 bytes at a time */ + for (i =3D 0; i < ETH_MODULE_SFF_8079_LEN; i +=3D 2) { + status =3D igb_read_phy_reg_i2c(hw, i, &dataword); + if (status !=3D E1000_SUCCESS) + /* Error occurred while reading module */ + return -EIO; + + data[i] =3D (dataword >> 8) & 0xFF; + data[i+1] =3D dataword & 0xFF; + } + + /* If the second block is requested, check if SFF-8472 is supported. = */ + if (ee->len =3D=3D ETH_MODULE_SFF_8472_LEN) { + if (data[IGB_SFF_8472_COMP] =3D=3D IGB_SFF_8472_UNSUP) + return -EOPNOTSUPP; + + /* Read the second block, SFF-8472, 2 bytes at a time */ + for (i =3D ETH_MODULE_SFF_8079_LEN; + i < ETH_MODULE_SFF_8472_LEN; i +=3D 2) { + status =3D igb_read_phy_reg_i2c(hw, i, &dataword); + if (status !=3D E1000_SUCCESS) + return -EIO; + + data[i] =3D (dataword >> 8) & 0xFF; + data[i+1] =3D dataword & 0xFF; + } + } + + return 0; +} + static int igb_ethtool_begin(struct net_device *netdev) { struct igb_adapter *adapter =3D netdev_priv(netdev); @@ -2666,6 +2748,8 @@ static const struct ethtool_ops igb_ethtool_ops =3D= { .set_rxnfc =3D igb_set_rxnfc, .get_eee =3D igb_get_eee, .set_eee =3D igb_set_eee, + .get_module_info =3D igb_get_module_info, + .get_module_eeprom =3D igb_get_module_eeprom, .begin =3D igb_ethtool_begin, .complete =3D igb_ethtool_complete, }; --=20 1.7.11.7