[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20241025230550.25536-1-Fabi.Benschuh@fau.de>
Date: Sat, 26 Oct 2024 01:05:46 +0200
From: Fabian Benschuh <Fabi.Benschuh@....de>
To: Woojung Huh <woojung.huh@...rochip.com>,
UNGLinuxDriver@...rochip.com,
Andrew Lunn <andrew+netdev@...n.ch>,
"David S. Miller" <davem@...emloft.net>,
Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>,
Paolo Abeni <pabeni@...hat.com>,
netdev@...r.kernel.org,
linux-usb@...r.kernel.org
Cc: Fabian Benschuh <Fabi.Benschuh@....de>
Subject: [PATCH] Add LAN78XX OTP_ACCESS flag support
With this flag we can now use ethtool to access the OTP:
ethtool --set-priv-flags eth0 OTP_ACCESS on
ethtool -e eth0 # this will read OTP if OTP_ACCESS is on, else EEPROM
When writing to OTP we need to set OTP_ACCESS on and write with the correct magic 0x7873 for OTP
---
drivers/net/usb/lan78xx.c | 55 ++++++++++++++++++++++++++++++++-------
1 file changed, 45 insertions(+), 10 deletions(-)
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index 8adf77e3557e..2fc9b9b138b0 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -85,6 +85,7 @@
#define EEPROM_INDICATOR (0xA5)
#define EEPROM_MAC_OFFSET (0x01)
#define MAX_EEPROM_SIZE 512
+#define MAX_OTP_SIZE 512
#define OTP_INDICATOR_1 (0xF3)
#define OTP_INDICATOR_2 (0xF7)
@@ -172,6 +173,7 @@
#define INT_EP_GPIO_2 (2)
#define INT_EP_GPIO_1 (1)
#define INT_EP_GPIO_0 (0)
+#define LAN78XX_NET_FLAG_OTP BIT(0)
static const char lan78xx_gstrings[][ETH_GSTRING_LEN] = {
"RX FCS Errors",
@@ -446,6 +448,7 @@ struct lan78xx_net {
unsigned int burst_cap;
unsigned long flags;
+ u32 priv_flags;
wait_queue_head_t *wait;
unsigned char suspend_count;
@@ -1542,6 +1545,10 @@ static void lan78xx_status(struct lan78xx_net *dev, struct urb *urb)
static int lan78xx_ethtool_get_eeprom_len(struct net_device *netdev)
{
+ struct lan78xx_net *dev = netdev_priv(netdev);
+
+ if (dev->priv_flags & LAN78XX_NET_FLAG_OTP)
+ return MAX_OTP_SIZE;
return MAX_EEPROM_SIZE;
}
@@ -1555,9 +1562,10 @@ static int lan78xx_ethtool_get_eeprom(struct net_device *netdev,
if (ret)
return ret;
- ee->magic = LAN78XX_EEPROM_MAGIC;
-
- ret = lan78xx_read_raw_eeprom(dev, ee->offset, ee->len, data);
+ if (dev->priv_flags & LAN78XX_NET_FLAG_OTP)
+ ret = lan78xx_read_raw_otp(dev, ee->offset, ee->len, data);
+ else
+ ret = lan78xx_read_raw_eeprom(dev, ee->offset, ee->len, data);
usb_autopm_put_interface(dev->intf);
@@ -1577,30 +1585,39 @@ static int lan78xx_ethtool_set_eeprom(struct net_device *netdev,
/* Invalid EEPROM_INDICATOR at offset zero will result in a failure
* to load data from EEPROM
*/
- if (ee->magic == LAN78XX_EEPROM_MAGIC)
- ret = lan78xx_write_raw_eeprom(dev, ee->offset, ee->len, data);
- else if ((ee->magic == LAN78XX_OTP_MAGIC) &&
- (ee->offset == 0) &&
- (ee->len == 512) &&
- (data[0] == OTP_INDICATOR_1))
- ret = lan78xx_write_raw_otp(dev, ee->offset, ee->len, data);
+ if (dev->priv_flags & LAN78XX_NET_FLAG_OTP) {
+ /* Beware! OTP is One Time Programming ONLY! */
+ if (ee->magic == LAN78XX_OTP_MAGIC)
+ ret = lan78xx_write_raw_otp(dev, ee->offset, ee->len, data);
+ } else {
+ if (ee->magic == LAN78XX_EEPROM_MAGIC)
+ ret = lan78xx_write_raw_eeprom(dev, ee->offset, ee->len, data);
+ }
usb_autopm_put_interface(dev->intf);
return ret;
}
+static const char lan78xx_priv_flags_strings[][ETH_GSTRING_LEN] = {
+ "OTP_ACCESS",
+};
+
static void lan78xx_get_strings(struct net_device *netdev, u32 stringset,
u8 *data)
{
if (stringset == ETH_SS_STATS)
memcpy(data, lan78xx_gstrings, sizeof(lan78xx_gstrings));
+ else if (stringset == ETH_SS_PRIV_FLAGS)
+ memcpy(data, lan78xx_priv_flags_strings, sizeof(lan78xx_priv_flags_strings));
}
static int lan78xx_get_sset_count(struct net_device *netdev, int sset)
{
if (sset == ETH_SS_STATS)
return ARRAY_SIZE(lan78xx_gstrings);
+ else if (sset == ETH_SS_PRIV_FLAGS)
+ return ARRAY_SIZE(lan78xx_priv_flags_strings);
else
return -EOPNOTSUPP;
}
@@ -1617,6 +1634,22 @@ static void lan78xx_get_stats(struct net_device *netdev,
mutex_unlock(&dev->stats.access_lock);
}
+static u32 lan78xx_ethtool_get_priv_flags(struct net_device *netdev)
+{
+ struct lan78xx_net *dev = netdev_priv(netdev);
+
+ return dev->priv_flags;
+}
+
+static int lan78xx_ethtool_set_priv_flags(struct net_device *netdev, u32 flags)
+{
+ struct lan78xx_net *dev = netdev_priv(netdev);
+
+ dev->priv_flags = flags;
+
+ return 0;
+}
+
static void lan78xx_get_wol(struct net_device *netdev,
struct ethtool_wolinfo *wol)
{
@@ -1905,6 +1938,8 @@ static const struct ethtool_ops lan78xx_ethtool_ops = {
.get_eeprom = lan78xx_ethtool_get_eeprom,
.set_eeprom = lan78xx_ethtool_set_eeprom,
.get_ethtool_stats = lan78xx_get_stats,
+ .get_priv_flags = lan78xx_ethtool_get_priv_flags,
+ .set_priv_flags = lan78xx_ethtool_set_priv_flags,
.get_sset_count = lan78xx_get_sset_count,
.get_strings = lan78xx_get_strings,
.get_wol = lan78xx_get_wol,
--
2.43.0
Powered by blists - more mailing lists