* [PATCH 1/2] cx82310_eth: re-enable ethernet mode after router reboot
@ 2020-10-10 14:00 Ondrej Zary
2020-10-10 14:00 ` [PATCH 2/2] cx82310_eth: use netdev_err instead of dev_err Ondrej Zary
2020-10-11 22:55 ` [PATCH 1/2] cx82310_eth: re-enable ethernet mode after router reboot Jakub Kicinski
0 siblings, 2 replies; 5+ messages in thread
From: Ondrej Zary @ 2020-10-10 14:00 UTC (permalink / raw)
To: Oliver Neukum, netdev, linux-usb, linux-kernel
When the router is rebooted without a power cycle, the USB device
remains connected but its configuration is reset. This results in
a non-working ethernet connection with messages like this in syslog:
usb 2-2: RX packet too long: 65535 B
Re-enable ethernet mode when receiving a packet with invalid size of
0xffff.
Signed-off-by: Ondrej Zary <linux@zary.sk>
---
drivers/net/usb/cx82310_eth.c | 50 ++++++++++++++++++++++++++++++-----
1 file changed, 44 insertions(+), 6 deletions(-)
diff --git a/drivers/net/usb/cx82310_eth.c b/drivers/net/usb/cx82310_eth.c
index 32b08b18e120..043679311399 100644
--- a/drivers/net/usb/cx82310_eth.c
+++ b/drivers/net/usb/cx82310_eth.c
@@ -40,6 +40,11 @@ enum cx82310_status {
#define CX82310_MTU 1514
#define CMD_EP 0x01
+struct cx82310_priv {
+ struct work_struct reenable_work;
+ struct usbnet *dev;
+};
+
/*
* execute control command
* - optionally send some data (command parameters)
@@ -115,6 +120,23 @@ static int cx82310_cmd(struct usbnet *dev, enum cx82310_cmd cmd, bool reply,
return ret;
}
+static int cx82310_enable_ethernet(struct usbnet *dev)
+{
+ int ret = cx82310_cmd(dev, CMD_ETHERNET_MODE, true, "\x01", 1, NULL, 0);
+
+ if (ret)
+ netdev_err(dev->net, "unable to enable ethernet mode: %d\n",
+ ret);
+ return ret;
+}
+
+static void cx82310_reenable_work(struct work_struct *work)
+{
+ struct cx82310_priv *priv = container_of(work, struct cx82310_priv,
+ reenable_work);
+ cx82310_enable_ethernet(priv->dev);
+}
+
#define partial_len data[0] /* length of partial packet data */
#define partial_rem data[1] /* remaining (missing) data length */
#define partial_data data[2] /* partial packet data */
@@ -126,6 +148,7 @@ static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
struct usb_device *udev = dev->udev;
u8 link[3];
int timeout = 50;
+ struct cx82310_priv *priv;
/* avoid ADSL modems - continue only if iProduct is "USB NET CARD" */
if (usb_string(udev, udev->descriptor.iProduct, buf, sizeof(buf)) > 0
@@ -152,6 +175,15 @@ static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
if (!dev->partial_data)
return -ENOMEM;
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ ret = -ENOMEM;
+ goto err_partial;
+ }
+ dev->driver_priv = priv;
+ INIT_WORK(&priv->reenable_work, cx82310_reenable_work);
+ priv->dev = dev;
+
/* wait for firmware to become ready (indicated by the link being up) */
while (--timeout) {
ret = cx82310_cmd(dev, CMD_GET_LINK_STATUS, true, NULL, 0,
@@ -168,12 +200,8 @@ static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
}
/* enable ethernet mode (?) */
- ret = cx82310_cmd(dev, CMD_ETHERNET_MODE, true, "\x01", 1, NULL, 0);
- if (ret) {
- dev_err(&udev->dev, "unable to enable ethernet mode: %d\n",
- ret);
+ if (cx82310_enable_ethernet(dev))
goto err;
- }
/* get the MAC address */
ret = cx82310_cmd(dev, CMD_GET_MAC_ADDR, true, NULL, 0,
@@ -190,13 +218,19 @@ static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
return 0;
err:
+ kfree(dev->driver_priv);
+err_partial:
kfree((void *)dev->partial_data);
return ret;
}
static void cx82310_unbind(struct usbnet *dev, struct usb_interface *intf)
{
+ struct cx82310_priv *priv = dev->driver_priv;
+
kfree((void *)dev->partial_data);
+ cancel_work_sync(&priv->reenable_work);
+ kfree(dev->driver_priv);
}
/*
@@ -211,6 +245,7 @@ static int cx82310_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
{
int len;
struct sk_buff *skb2;
+ struct cx82310_priv *priv = dev->driver_priv;
/*
* If the last skb ended with an incomplete packet, this skb contains
@@ -245,7 +280,10 @@ static int cx82310_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
break;
}
- if (len > CX82310_MTU) {
+ if (len == 0xffff) {
+ netdev_info(dev->net, "router was rebooted, re-enabling ethernet mode");
+ schedule_work(&priv->reenable_work);
+ } else if (len > CX82310_MTU) {
dev_err(&dev->udev->dev, "RX packet too long: %d B\n",
len);
return 0;
--
Ondrej Zary
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] cx82310_eth: use netdev_err instead of dev_err
2020-10-10 14:00 [PATCH 1/2] cx82310_eth: re-enable ethernet mode after router reboot Ondrej Zary
@ 2020-10-10 14:00 ` Ondrej Zary
2020-10-11 22:55 ` [PATCH 1/2] cx82310_eth: re-enable ethernet mode after router reboot Jakub Kicinski
1 sibling, 0 replies; 5+ messages in thread
From: Ondrej Zary @ 2020-10-10 14:00 UTC (permalink / raw)
To: Oliver Neukum, netdev, linux-usb, linux-kernel
Use netdev_err for better device identification in syslog.
Signed-off-by: Ondrej Zary <linux@zary.sk>
---
drivers/net/usb/cx82310_eth.c | 28 ++++++++++++----------------
1 file changed, 12 insertions(+), 16 deletions(-)
diff --git a/drivers/net/usb/cx82310_eth.c b/drivers/net/usb/cx82310_eth.c
index 043679311399..ca89d8258dd3 100644
--- a/drivers/net/usb/cx82310_eth.c
+++ b/drivers/net/usb/cx82310_eth.c
@@ -71,8 +71,8 @@ static int cx82310_cmd(struct usbnet *dev, enum cx82310_cmd cmd, bool reply,
CMD_PACKET_SIZE, &actual_len, CMD_TIMEOUT);
if (ret < 0) {
if (cmd != CMD_GET_LINK_STATUS)
- dev_err(&dev->udev->dev, "send command %#x: error %d\n",
- cmd, ret);
+ netdev_err(dev->net, "send command %#x: error %d\n",
+ cmd, ret);
goto end;
}
@@ -84,30 +84,27 @@ static int cx82310_cmd(struct usbnet *dev, enum cx82310_cmd cmd, bool reply,
CMD_TIMEOUT);
if (ret < 0) {
if (cmd != CMD_GET_LINK_STATUS)
- dev_err(&dev->udev->dev,
- "reply receive error %d\n",
- ret);
+ netdev_err(dev->net, "reply receive error %d\n",
+ ret);
goto end;
}
if (actual_len > 0)
break;
}
if (actual_len == 0) {
- dev_err(&dev->udev->dev, "no reply to command %#x\n",
- cmd);
+ netdev_err(dev->net, "no reply to command %#x\n", cmd);
ret = -EIO;
goto end;
}
if (buf[0] != cmd) {
- dev_err(&dev->udev->dev,
- "got reply to command %#x, expected: %#x\n",
- buf[0], cmd);
+ netdev_err(dev->net, "got reply to command %#x, expected: %#x\n",
+ buf[0], cmd);
ret = -EIO;
goto end;
}
if (buf[1] != STATUS_SUCCESS) {
- dev_err(&dev->udev->dev, "command %#x failed: %#x\n",
- cmd, buf[1]);
+ netdev_err(dev->net, "command %#x failed: %#x\n", cmd,
+ buf[1]);
ret = -EIO;
goto end;
}
@@ -194,7 +191,7 @@ static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
msleep(500);
}
if (!timeout) {
- dev_err(&udev->dev, "firmware not ready in time\n");
+ netdev_err(dev->net, "firmware not ready in time\n");
ret = -ETIMEDOUT;
goto err;
}
@@ -207,7 +204,7 @@ static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
ret = cx82310_cmd(dev, CMD_GET_MAC_ADDR, true, NULL, 0,
dev->net->dev_addr, ETH_ALEN);
if (ret) {
- dev_err(&udev->dev, "unable to read MAC address: %d\n", ret);
+ netdev_err(dev->net, "unable to read MAC address: %d\n", ret);
goto err;
}
@@ -284,8 +281,7 @@ static int cx82310_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
netdev_info(dev->net, "router was rebooted, re-enabling ethernet mode");
schedule_work(&priv->reenable_work);
} else if (len > CX82310_MTU) {
- dev_err(&dev->udev->dev, "RX packet too long: %d B\n",
- len);
+ netdev_err(dev->net, "RX packet too long: %d B\n", len);
return 0;
}
--
Ondrej Zary
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] cx82310_eth: re-enable ethernet mode after router reboot
2020-10-10 14:00 [PATCH 1/2] cx82310_eth: re-enable ethernet mode after router reboot Ondrej Zary
2020-10-10 14:00 ` [PATCH 2/2] cx82310_eth: use netdev_err instead of dev_err Ondrej Zary
@ 2020-10-11 22:55 ` Jakub Kicinski
2020-10-12 10:42 ` Ondrej Zary
1 sibling, 1 reply; 5+ messages in thread
From: Jakub Kicinski @ 2020-10-11 22:55 UTC (permalink / raw)
To: Ondrej Zary; +Cc: Oliver Neukum, netdev, linux-usb, linux-kernel
On Sat, 10 Oct 2020 16:00:46 +0200 Ondrej Zary wrote:
> When the router is rebooted without a power cycle, the USB device
> remains connected but its configuration is reset. This results in
> a non-working ethernet connection with messages like this in syslog:
> usb 2-2: RX packet too long: 65535 B
>
> Re-enable ethernet mode when receiving a packet with invalid size of
> 0xffff.
Patch looks good, but could you explain what's a reboot without a power
cycle in this case? The modem gets reset but USB subsystem doesn't know
it and doesn't go though a unbind() + bind() cycle?
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] cx82310_eth: re-enable ethernet mode after router reboot
2020-10-11 22:55 ` [PATCH 1/2] cx82310_eth: re-enable ethernet mode after router reboot Jakub Kicinski
@ 2020-10-12 10:42 ` Ondrej Zary
2020-10-12 16:50 ` Jakub Kicinski
0 siblings, 1 reply; 5+ messages in thread
From: Ondrej Zary @ 2020-10-12 10:42 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: Oliver Neukum, netdev, linux-usb, linux-kernel
On Monday 12 October 2020, Jakub Kicinski wrote:
> On Sat, 10 Oct 2020 16:00:46 +0200 Ondrej Zary wrote:
> > When the router is rebooted without a power cycle, the USB device
> > remains connected but its configuration is reset. This results in
> > a non-working ethernet connection with messages like this in syslog:
> > usb 2-2: RX packet too long: 65535 B
> >
> > Re-enable ethernet mode when receiving a packet with invalid size of
> > 0xffff.
>
> Patch looks good, but could you explain what's a reboot without a power
> cycle in this case? The modem gets reset but USB subsystem doesn't know
> it and doesn't go though a unbind() + bind() cycle?
The router can be rebooted through the web interface. The reboot does not
disconnect the USB device - it remains connected as if nothing happened. Only
wrong data starts to come in.
--
Ondrej Zary
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] cx82310_eth: re-enable ethernet mode after router reboot
2020-10-12 10:42 ` Ondrej Zary
@ 2020-10-12 16:50 ` Jakub Kicinski
0 siblings, 0 replies; 5+ messages in thread
From: Jakub Kicinski @ 2020-10-12 16:50 UTC (permalink / raw)
To: Ondrej Zary; +Cc: Oliver Neukum, netdev, linux-usb, linux-kernel
On Mon, 12 Oct 2020 12:42:55 +0200 Ondrej Zary wrote:
> On Monday 12 October 2020, Jakub Kicinski wrote:
> > On Sat, 10 Oct 2020 16:00:46 +0200 Ondrej Zary wrote:
> > > When the router is rebooted without a power cycle, the USB device
> > > remains connected but its configuration is reset. This results in
> > > a non-working ethernet connection with messages like this in syslog:
> > > usb 2-2: RX packet too long: 65535 B
> > >
> > > Re-enable ethernet mode when receiving a packet with invalid size of
> > > 0xffff.
> >
> > Patch looks good, but could you explain what's a reboot without a power
> > cycle in this case? The modem gets reset but USB subsystem doesn't know
> > it and doesn't go though a unbind() + bind() cycle?
>
> The router can be rebooted through the web interface. The reboot does not
> disconnect the USB device - it remains connected as if nothing happened. Only
> wrong data starts to come in.
I see. Applied to net-next, thanks!
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2020-10-12 16:50 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-10 14:00 [PATCH 1/2] cx82310_eth: re-enable ethernet mode after router reboot Ondrej Zary
2020-10-10 14:00 ` [PATCH 2/2] cx82310_eth: use netdev_err instead of dev_err Ondrej Zary
2020-10-11 22:55 ` [PATCH 1/2] cx82310_eth: re-enable ethernet mode after router reboot Jakub Kicinski
2020-10-12 10:42 ` Ondrej Zary
2020-10-12 16:50 ` Jakub Kicinski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).