]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.4/usbnet-ipheth-prevent-tx-queue-timeouts-when-device-not-ready.patch
4.4-stable patches
[thirdparty/kernel/stable-queue.git] / queue-4.4 / usbnet-ipheth-prevent-tx-queue-timeouts-when-device-not-ready.patch
1 From bb1b40c7cb863f0800a6410c7dcb86cf3f28d3b1 Mon Sep 17 00:00:00 2001
2 From: Alexander Kappner <agk@godking.net>
3 Date: Mon, 13 Nov 2017 17:44:20 -0800
4 Subject: usbnet: ipheth: prevent TX queue timeouts when device not ready
5
6 From: Alexander Kappner <agk@godking.net>
7
8 commit bb1b40c7cb863f0800a6410c7dcb86cf3f28d3b1 upstream.
9
10 iOS devices require the host to be "trusted" before servicing network
11 packets. Establishing trust requires the user to confirm a dialog on the
12 iOS device.Until trust is established, the iOS device will silently discard
13 network packets from the host. Currently, the ipheth driver does not detect
14 whether an iOS device has established trust with the host, and immediately
15 sets up the transmit queues.
16
17 This causes the following problems:
18
19 - Kernel taint due to WARN() in netdev watchdog.
20 - Dmesg spam ("TX timeout").
21 - Disruption of user space networking activity (dhcpd, etc...) when new
22 interface comes up but cannot be used.
23 - Unnecessary host and device wakeups and USB traffic
24
25 Example dmesg output:
26
27 [ 1101.319778] NETDEV WATCHDOG: eth1 (ipheth): transmit queue 0 timed out
28 [ 1101.319817] ------------[ cut here ]------------
29 [ 1101.319828] WARNING: CPU: 0 PID: 0 at net/sched/sch_generic.c:316 dev_watchdog+0x20f/0x220
30 [ 1101.319831] Modules linked in: ipheth usbmon nvidia_drm(PO) nvidia_modeset(PO) nvidia(PO) iwlmvm mac80211 iwlwifi btusb btrtl btbcm btintel qmi_wwan bluetooth cfg80211 ecdh_generic thinkpad_acpi rfkill [last unloaded: ipheth]
31 [ 1101.319861] CPU: 0 PID: 0 Comm: swapper/0 Tainted: P O 4.13.12.1 #1
32 [ 1101.319864] Hardware name: LENOVO 20ENCTO1WW/20ENCTO1WW, BIOS N1EET62W (1.35 ) 11/10/2016
33 [ 1101.319867] task: ffffffff81e11500 task.stack: ffffffff81e00000
34 [ 1101.319873] RIP: 0010:dev_watchdog+0x20f/0x220
35 [ 1101.319876] RSP: 0018:ffff8810a3c03e98 EFLAGS: 00010292
36 [ 1101.319880] RAX: 000000000000003a RBX: 0000000000000000 RCX: 0000000000000000
37 [ 1101.319883] RDX: ffff8810a3c15c48 RSI: ffffffff81ccbfc2 RDI: 00000000ffffffff
38 [ 1101.319886] RBP: ffff880c04ebc41c R08: 0000000000000000 R09: 0000000000000379
39 [ 1101.319889] R10: 00000100696589d0 R11: 0000000000000378 R12: ffff880c04ebc000
40 [ 1101.319892] R13: 0000000000000000 R14: 0000000000000001 R15: ffff880c2865fc80
41 [ 1101.319896] FS: 0000000000000000(0000) GS:ffff8810a3c00000(0000) knlGS:0000000000000000
42 [ 1101.319899] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
43 [ 1101.319902] CR2: 00007f3ff24ac000 CR3: 0000000001e0a000 CR4: 00000000003406f0
44 [ 1101.319905] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
45 [ 1101.319908] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
46 [ 1101.319910] Call Trace:
47 [ 1101.319914] <IRQ>
48 [ 1101.319921] ? dev_graft_qdisc+0x70/0x70
49 [ 1101.319928] ? dev_graft_qdisc+0x70/0x70
50 [ 1101.319934] ? call_timer_fn+0x2e/0x170
51 [ 1101.319939] ? dev_graft_qdisc+0x70/0x70
52 [ 1101.319944] ? run_timer_softirq+0x1ea/0x440
53 [ 1101.319951] ? timerqueue_add+0x54/0x80
54 [ 1101.319956] ? enqueue_hrtimer+0x38/0xa0
55 [ 1101.319963] ? __do_softirq+0xed/0x2e7
56 [ 1101.319970] ? irq_exit+0xb4/0xc0
57 [ 1101.319976] ? smp_apic_timer_interrupt+0x39/0x50
58 [ 1101.319981] ? apic_timer_interrupt+0x8c/0xa0
59 [ 1101.319983] </IRQ>
60 [ 1101.319992] ? cpuidle_enter_state+0xfa/0x2a0
61 [ 1101.319999] ? do_idle+0x1a3/0x1f0
62 [ 1101.320004] ? cpu_startup_entry+0x5f/0x70
63 [ 1101.320011] ? start_kernel+0x444/0x44c
64 [ 1101.320017] ? early_idt_handler_array+0x120/0x120
65 [ 1101.320023] ? x86_64_start_kernel+0x145/0x154
66 [ 1101.320028] ? secondary_startup_64+0x9f/0x9f
67 [ 1101.320033] Code: 20 04 00 00 eb 9f 4c 89 e7 c6 05 59 44 71 00 01 e8 a7 df fd ff 89 d9 4c 89 e6 48 c7 c7 70 b7 cd 81 48 89 c2 31 c0 e8 97 64 90 ff <0f> ff eb bf 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00
68 [ 1101.320103] ---[ end trace 0cc4d251e2b57080 ]---
69 [ 1101.320110] ipheth 1-5:4.2: ipheth_tx_timeout: TX timeout
70
71 The last message "TX timeout" is repeated every 5 seconds until trust is
72 established or the device is disconnected, filling up dmesg.
73
74 The proposed patch eliminates the problem by, upon connection, keeping the
75 TX queue and carrier disabled until a packet is first received from the iOS
76 device. This is reflected by the confirmed_pairing variable in the device
77 structure. Only after at least one packet has been received from the iOS
78 device, the transmit queue and carrier are brought up during the periodic
79 device poll in ipheth_carrier_set. Because the iOS device will always send
80 a packet immediately upon trust being established, this should not delay
81 the interface becoming useable. To prevent failed UBRs in
82 ipheth_rcvbulk_callback from perpetually re-enabling the queue if it was
83 disabled, a new check is added so only successful transfers re-enable the
84 queue, whereas failed transfers only trigger an immediate poll.
85
86 This has the added benefit of removing the periodic control requests to the
87 iOS device until trust has been established and thus should reduce wakeup
88 events on both the host and the iOS device.
89
90 Signed-off-by: Alexander Kappner <agk@godking.net>
91 Signed-off-by: David S. Miller <davem@davemloft.net>
92 [groeck: Fixed context conflict seen because 45611c61dd50 was applied first]
93 Signed-off-by: Guenter Roeck <linux@roeck-us.net>
94 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
95 ---
96 drivers/net/usb/ipheth.c | 30 +++++++++++++++++++++---------
97 1 file changed, 21 insertions(+), 9 deletions(-)
98
99 --- a/drivers/net/usb/ipheth.c
100 +++ b/drivers/net/usb/ipheth.c
101 @@ -148,6 +148,7 @@ struct ipheth_device {
102 u8 bulk_in;
103 u8 bulk_out;
104 struct delayed_work carrier_work;
105 + bool confirmed_pairing;
106 };
107
108 static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags);
109 @@ -259,7 +260,7 @@ static void ipheth_rcvbulk_callback(stru
110
111 dev->net->stats.rx_packets++;
112 dev->net->stats.rx_bytes += len;
113 -
114 + dev->confirmed_pairing = true;
115 netif_rx(skb);
116 ipheth_rx_submit(dev, GFP_ATOMIC);
117 }
118 @@ -280,14 +281,21 @@ static void ipheth_sndbulk_callback(stru
119 dev_err(&dev->intf->dev, "%s: urb status: %d\n",
120 __func__, status);
121
122 - netif_wake_queue(dev->net);
123 + if (status == 0)
124 + netif_wake_queue(dev->net);
125 + else
126 + // on URB error, trigger immediate poll
127 + schedule_delayed_work(&dev->carrier_work, 0);
128 }
129
130 static int ipheth_carrier_set(struct ipheth_device *dev)
131 {
132 struct usb_device *udev = dev->udev;
133 int retval;
134 -
135 + if (!dev)
136 + return 0;
137 + if (!dev->confirmed_pairing)
138 + return 0;
139 retval = usb_control_msg(udev,
140 usb_rcvctrlpipe(udev, IPHETH_CTRL_ENDP),
141 IPHETH_CMD_CARRIER_CHECK, /* request */
142 @@ -302,11 +310,14 @@ static int ipheth_carrier_set(struct iph
143 return retval;
144 }
145
146 - if (dev->ctrl_buf[0] == IPHETH_CARRIER_ON)
147 + if (dev->ctrl_buf[0] == IPHETH_CARRIER_ON) {
148 netif_carrier_on(dev->net);
149 - else
150 + if (dev->tx_urb->status != -EINPROGRESS)
151 + netif_wake_queue(dev->net);
152 + } else {
153 netif_carrier_off(dev->net);
154 -
155 + netif_stop_queue(dev->net);
156 + }
157 return 0;
158 }
159
160 @@ -386,7 +397,6 @@ static int ipheth_open(struct net_device
161 return retval;
162
163 schedule_delayed_work(&dev->carrier_work, IPHETH_CARRIER_CHECK_TIMEOUT);
164 - netif_start_queue(net);
165 return retval;
166 }
167
168 @@ -489,7 +499,7 @@ static int ipheth_probe(struct usb_inter
169 dev->udev = udev;
170 dev->net = netdev;
171 dev->intf = intf;
172 -
173 + dev->confirmed_pairing = false;
174 /* Set up endpoints */
175 hintf = usb_altnum_to_altsetting(intf, IPHETH_ALT_INTFNUM);
176 if (hintf == NULL) {
177 @@ -540,7 +550,9 @@ static int ipheth_probe(struct usb_inter
178 retval = -EIO;
179 goto err_register_netdev;
180 }
181 -
182 + // carrier down and transmit queues stopped until packet from device
183 + netif_carrier_off(netdev);
184 + netif_tx_stop_all_queues(netdev);
185 dev_info(&intf->dev, "Apple iPhone USB Ethernet device attached\n");
186 return 0;
187