From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933080AbcHXNwr (ORCPT ); Wed, 24 Aug 2016 09:52:47 -0400 Received: from mout.kundenserver.de ([212.227.126.187]:65091 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756632AbcHXNwo (ORCPT ); Wed, 24 Aug 2016 09:52:44 -0400 From: Alban Bedel To: linux-usb@vger.kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Freddy Xin , Alban Bedel Subject: [PATCH] usbnet: ax88179_178a: Add support for writing the EEPROM Date: Wed, 24 Aug 2016 15:52:31 +0200 Message-Id: <20160824135231.21782-1-alban.bedel@avionic-design.de> X-Mailer: git-send-email 2.9.3 X-Provags-ID: V03:K0:iWcv8IXiqaG5R7NjHEYIK+PPNAKyjJzqf7S+45L8uVGdHJ60W6E QSCiIYc953qSOkfV8uRtq+p9Qf6KiQAJPegDUV2c/GAmo2+fVEsW15MeD8ppMo/KWjqp1E4 V6Y+0L4+5JpsVOpqobICT9kGcqho6xsV1a45htw3elbAwnEizSJ2+nq6eb2mSjdh9b5DpKX cHjiSYrqBx/knDFg1M/tg== X-UI-Out-Filterresults: notjunk:1;V01:K0:7WFWzBIfweo=:mKKRRIQzNWZODQ9TTQl+4k YY/H+po4LVvCrqCeczAyyxmu5DptGTTiV7UMHpEZTC3Tsxg9+gjhRoHiNfDoqhVaCbU4ToM0G j81wVL2n2JNFu51d1aI/0BvalozWs3bn3Q8DL/YVSpL8BUAKYBkmFwyY7QDKRl5iVDBHPBPJF buSdy3GZXtNZ00mLzzlKS4VPoDTuTTjk/ImP8V3++PTSIfpktYQsVxafA5/OE9OcTjF/O5N4u g40toPziJZ7XzgW9aTCjr1JLnI8HK36v/Q7nSca1MxzHV9tjn6Elcjy8hILissAtwgND//Jy9 2VbJ1MLlgGoDZTG5B9VNRGSrRUxmQpcUbY7UBWFY68/0r1/e5mUnTTC2jf23PsQSEOYAfT+1Z 8pa207vUXmSVFfwRiyVZFFtzBS2nk0isOY5XI1mk7JrjB0pkqOjFyTUTyz3mMcXrMpDiTzY9w AXGbB/udASJ2lAYFPD+onwWwTaoooBhr3nvP8cYaj/PgxRZpw870n4wC64EXQ6wGbd4c4qObi podxN0310ZH/Pdgq5dh96VFLq7wAkUZRC1fHZf9EW7I2q2r6CPXXpzgjhGOpkA67tN2y1vqgv zh0xM31Eb9Efi0NB2Tbqp948XThcuw0hE38iUEZBmpVptVckNtOLFxA1uZ3jpVieYe1ypNjUn LJKAfqGnbjpDwewfM0DxGm4JKNBmn1UB7YG5A4+eNBklqZss2bxIiLmEqFMxqhDVXDxQ= Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Implement the .set_eeprom callback to allow setting the MAC address as well as a few other parameters. Note that the EEPROM must have a correct PID/VID checksum set otherwise the SROM is used and reads return the SROM content. Signed-off-by: Alban Bedel --- drivers/net/usb/ax88179_178a.c | 57 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index e6338c16081a..e6a986303dad 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -28,6 +28,7 @@ #define AX88179_PHY_ID 0x03 #define AX_EEPROM_LEN 0x100 +#define AX_EEPROM_BLOCK 0x40u #define AX88179_EEPROM_MAGIC 0x17900b95 #define AX_MCAST_FLTSIZE 8 #define AX_MAX_MCAST 64 @@ -43,6 +44,7 @@ #define AX_ACCESS_PHY 0x02 #define AX_ACCESS_EEPROM 0x04 #define AX_ACCESS_EFUS 0x05 +#define AX_RELOAD_EEPROM 0x06 #define AX_PAUSE_WATERLVL_HIGH 0x54 #define AX_PAUSE_WATERLVL_LOW 0x55 @@ -620,6 +622,60 @@ ax88179_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, return 0; } +static int +ax88179_set_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, + u8 *data) +{ + struct usbnet *dev = netdev_priv(net); + unsigned int offset = eeprom->offset; + unsigned int len = eeprom->len; + int i, err = 0; + u8 *block; + + /* The EEPROM data must be aligned on blocks of 64 bytes */ + if ((offset % AX_EEPROM_BLOCK) || (len % AX_EEPROM_BLOCK)) { + offset = eeprom->offset / AX_EEPROM_BLOCK * AX_EEPROM_BLOCK; + len = eeprom->len + eeprom->offset - offset; + len = DIV_ROUND_UP(len, AX_EEPROM_BLOCK) * AX_EEPROM_BLOCK; + + block = kmalloc(len, GFP_KERNEL); + if (!block) + return -ENOMEM; + + /* Copy the current data, we could skip some but KISS */ + for (i = 0; i < len; i += AX_EEPROM_BLOCK) { + err = __ax88179_read_cmd(dev, AX_ACCESS_EEPROM, + (offset + i) >> 1, + AX_EEPROM_BLOCK >> 1, + AX_EEPROM_BLOCK, + &block[i], 0); + if (err < 0) { + kfree(block); + return err; + } + } + memcpy(block + eeprom->offset - offset, data, eeprom->len); + } else { + block = data; + } + + for (i = 0; err >= 0 && i < len; i += AX_EEPROM_BLOCK) { + err = ax88179_write_cmd(dev, AX_ACCESS_EEPROM, + (offset + i) >> 1, + AX_EEPROM_BLOCK >> 1, + AX_EEPROM_BLOCK, &block[i]); + } + + if (block != data) + kfree(block); + + /* Reload the EEPROM */ + if (err >= 0) + err = ax88179_write_cmd(dev, AX_RELOAD_EEPROM, 0, 0, 0, NULL); + + return err < 0 ? err : 0; +} + static int ax88179_get_settings(struct net_device *net, struct ethtool_cmd *cmd) { struct usbnet *dev = netdev_priv(net); @@ -826,6 +882,7 @@ static const struct ethtool_ops ax88179_ethtool_ops = { .set_wol = ax88179_set_wol, .get_eeprom_len = ax88179_get_eeprom_len, .get_eeprom = ax88179_get_eeprom, + .set_eeprom = ax88179_set_eeprom, .get_settings = ax88179_get_settings, .set_settings = ax88179_set_settings, .get_eee = ax88179_get_eee, -- 2.9.3