* [PATCH] usbnet: ax88179_178a: Add support for writing the EEPROM
@ 2016-08-24 13:52 Alban Bedel
2016-08-24 14:30 ` Oliver Neukum
0 siblings, 1 reply; 6+ messages in thread
From: Alban Bedel @ 2016-08-24 13:52 UTC (permalink / raw)
To: linux-usb; +Cc: netdev, linux-kernel, Freddy Xin, Alban Bedel
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 <alban.bedel@avionic-design.de>
---
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
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] usbnet: ax88179_178a: Add support for writing the EEPROM
2016-08-24 13:52 [PATCH] usbnet: ax88179_178a: Add support for writing the EEPROM Alban Bedel
@ 2016-08-24 14:30 ` Oliver Neukum
2016-08-24 14:40 ` Alban Bedel
0 siblings, 1 reply; 6+ messages in thread
From: Oliver Neukum @ 2016-08-24 14:30 UTC (permalink / raw)
To: Alban Bedel; +Cc: linux-usb, Freddy Xin, linux-kernel, netdev
On Wed, 2016-08-24 at 15:52 +0200, Alban Bedel wrote:
> 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 <alban.bedel@avionic-design.de>
> ---
> 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);
And if block == dta, what frees the memory?
Regards
Oliver
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] usbnet: ax88179_178a: Add support for writing the EEPROM
2016-08-24 14:30 ` Oliver Neukum
@ 2016-08-24 14:40 ` Alban Bedel
2016-08-25 9:16 ` Oliver Neukum
0 siblings, 1 reply; 6+ messages in thread
From: Alban Bedel @ 2016-08-24 14:40 UTC (permalink / raw)
To: Oliver Neukum; +Cc: Alban Bedel, linux-usb, Freddy Xin, linux-kernel, netdev
[-- Attachment #1: Type: text/plain, Size: 4076 bytes --]
On Wed, 24 Aug 2016 16:30:39 +0200
Oliver Neukum <oneukum@suse.com> wrote:
> On Wed, 2016-08-24 at 15:52 +0200, Alban Bedel wrote:
> > 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 <alban.bedel@avionic-design.de>
> > ---
> > 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);
>
> And if block == dta, what frees the memory?
In this case this function didn't allocate any memory, so there is
nothing to free.
Alban
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] usbnet: ax88179_178a: Add support for writing the EEPROM
2016-08-24 14:40 ` Alban Bedel
@ 2016-08-25 9:16 ` Oliver Neukum
2016-08-25 10:07 ` Alban Bedel
0 siblings, 1 reply; 6+ messages in thread
From: Oliver Neukum @ 2016-08-25 9:16 UTC (permalink / raw)
To: Alban Bedel; +Cc: Freddy Xin, linux-kernel, linux-usb, netdev
On Wed, 2016-08-24 at 16:40 +0200, Alban Bedel wrote:
> On Wed, 24 Aug 2016 16:30:39 +0200
> Oliver Neukum <oneukum@suse.com> wrote:
>
> > On Wed, 2016-08-24 at 15:52 +0200, Alban Bedel wrote:
> > > + if (block != data)
> > > + kfree(block);
> >
> > And if block == dta, what frees the memory?
>
> In this case this function didn't allocate any memory, so there is
> nothing to free.
Hi,
I see. kfree() has a check for NULL, so you could drop the
test, but it doesn't matter much either way.
Regards
Oliver
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] usbnet: ax88179_178a: Add support for writing the EEPROM
2016-08-25 9:16 ` Oliver Neukum
@ 2016-08-25 10:07 ` Alban Bedel
2016-08-25 10:08 ` Oliver Neukum
0 siblings, 1 reply; 6+ messages in thread
From: Alban Bedel @ 2016-08-25 10:07 UTC (permalink / raw)
To: Oliver Neukum; +Cc: Alban Bedel, Freddy Xin, linux-kernel, linux-usb, netdev
[-- Attachment #1: Type: text/plain, Size: 1120 bytes --]
On Thu, 25 Aug 2016 11:16:36 +0200
Oliver Neukum <oneukum@suse.com> wrote:
> On Wed, 2016-08-24 at 16:40 +0200, Alban Bedel wrote:
> > On Wed, 24 Aug 2016 16:30:39 +0200
> > Oliver Neukum <oneukum@suse.com> wrote:
> >
> > > On Wed, 2016-08-24 at 15:52 +0200, Alban Bedel wrote:
>
> > > > + if (block != data)
> > > > + kfree(block);
> > >
> > > And if block == dta, what frees the memory?
> >
> > In this case this function didn't allocate any memory, so there is
> > nothing to free.
>
> Hi,
>
> I see. kfree() has a check for NULL, so you could drop the
> test, but it doesn't matter much either way.
I think you misunderstand something here. data is the buffer passed
by the caller and block is a local variable. There is two cases:
1) The data to write is block aligned, then we use the caller buffer
as is and set block = data.
2) The requested data is not block aligned, then we kalloc block.
In both case the writing loop then use the block pointer. Afterwards
we only need to kfree block in case 2, that is when block != data.
Alban
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] usbnet: ax88179_178a: Add support for writing the EEPROM
2016-08-25 10:07 ` Alban Bedel
@ 2016-08-25 10:08 ` Oliver Neukum
0 siblings, 0 replies; 6+ messages in thread
From: Oliver Neukum @ 2016-08-25 10:08 UTC (permalink / raw)
To: Alban Bedel; +Cc: Freddy Xin, linux-kernel, linux-usb, netdev
On Thu, 2016-08-25 at 12:07 +0200, Alban Bedel wrote:
> On Thu, 25 Aug 2016 11:16:36 +0200
> Oliver Neukum <oneukum@suse.com> wrote:
>
> > On Wed, 2016-08-24 at 16:40 +0200, Alban Bedel wrote:
> > > On Wed, 24 Aug 2016 16:30:39 +0200
> > > Oliver Neukum <oneukum@suse.com> wrote:
> > >
> > > > On Wed, 2016-08-24 at 15:52 +0200, Alban Bedel wrote:
> >
> > > > > + if (block != data)
> > > > > + kfree(block);
> > > >
> > > > And if block == dta, what frees the memory?
> > >
> > > In this case this function didn't allocate any memory, so there is
> > > nothing to free.
> >
> > Hi,
> >
> > I see. kfree() has a check for NULL, so you could drop the
> > test, but it doesn't matter much either way.
>
> I think you misunderstand something here. data is the buffer passed
> by the caller and block is a local variable. There is two cases:
>
> 1) The data to write is block aligned, then we use the caller buffer
> as is and set block = data.
> 2) The requested data is not block aligned, then we kalloc block.
>
> In both case the writing loop then use the block pointer. Afterwards
> we only need to kfree block in case 2, that is when block != data.
Thanks for the clarification. Maybe worth a comment in the code?
Regards
Oliver
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2016-08-25 10:13 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-24 13:52 [PATCH] usbnet: ax88179_178a: Add support for writing the EEPROM Alban Bedel
2016-08-24 14:30 ` Oliver Neukum
2016-08-24 14:40 ` Alban Bedel
2016-08-25 9:16 ` Oliver Neukum
2016-08-25 10:07 ` Alban Bedel
2016-08-25 10:08 ` Oliver Neukum
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.