@@ -58,12 +58,198 @@ struct qmi_wwan_state {
58
58
59
59
enum qmi_wwan_flags {
60
60
QMI_WWAN_FLAG_RAWIP = 1 << 0 ,
61
+ QMI_WWAN_FLAG_MUX = 1 << 1 ,
61
62
};
62
63
63
64
enum qmi_wwan_quirks {
64
65
QMI_WWAN_QUIRK_DTR = 1 << 0 , /* needs "set DTR" request */
65
66
};
66
67
68
+ struct qmimux_hdr {
69
+ u8 pad ;
70
+ u8 mux_id ;
71
+ __be16 pkt_len ;
72
+ };
73
+
74
+ struct qmimux_priv {
75
+ struct net_device * real_dev ;
76
+ u8 mux_id ;
77
+ };
78
+
79
+ static int qmimux_open (struct net_device * dev )
80
+ {
81
+ struct qmimux_priv * priv = netdev_priv (dev );
82
+ struct net_device * real_dev = priv -> real_dev ;
83
+
84
+ if (!(priv -> real_dev -> flags & IFF_UP ))
85
+ return - ENETDOWN ;
86
+
87
+ if (netif_carrier_ok (real_dev ))
88
+ netif_carrier_on (dev );
89
+ return 0 ;
90
+ }
91
+
92
+ static int qmimux_stop (struct net_device * dev )
93
+ {
94
+ netif_carrier_off (dev );
95
+ return 0 ;
96
+ }
97
+
98
+ static netdev_tx_t qmimux_start_xmit (struct sk_buff * skb , struct net_device * dev )
99
+ {
100
+ struct qmimux_priv * priv = netdev_priv (dev );
101
+ unsigned int len = skb -> len ;
102
+ struct qmimux_hdr * hdr ;
103
+
104
+ hdr = (struct qmimux_hdr * )skb_push (skb , sizeof (struct qmimux_hdr ));
105
+ hdr -> pad = 0 ;
106
+ hdr -> mux_id = priv -> mux_id ;
107
+ hdr -> pkt_len = cpu_to_be16 (len );
108
+ skb -> dev = priv -> real_dev ;
109
+ return dev_queue_xmit (skb );
110
+ }
111
+
112
+ static const struct net_device_ops qmimux_netdev_ops = {
113
+ .ndo_open = qmimux_open ,
114
+ .ndo_stop = qmimux_stop ,
115
+ .ndo_start_xmit = qmimux_start_xmit ,
116
+ };
117
+
118
+ static void qmimux_setup (struct net_device * dev )
119
+ {
120
+ dev -> header_ops = NULL ; /* No header */
121
+ dev -> type = ARPHRD_NONE ;
122
+ dev -> hard_header_len = 0 ;
123
+ dev -> addr_len = 0 ;
124
+ dev -> flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST ;
125
+ dev -> netdev_ops = & qmimux_netdev_ops ;
126
+ dev -> destructor = free_netdev ;
127
+ }
128
+
129
+ static struct net_device * qmimux_find_dev (struct usbnet * dev , u8 mux_id )
130
+ {
131
+ struct qmimux_priv * priv ;
132
+ struct list_head * iter ;
133
+ struct net_device * ldev ;
134
+
135
+ rcu_read_lock ();
136
+ netdev_for_each_upper_dev_rcu (dev -> net , ldev , iter ) {
137
+ priv = netdev_priv (ldev );
138
+ if (priv -> mux_id == mux_id ) {
139
+ rcu_read_unlock ();
140
+ return ldev ;
141
+ }
142
+ }
143
+ rcu_read_unlock ();
144
+ return NULL ;
145
+ }
146
+
147
+ static bool qmimux_has_slaves (struct usbnet * dev )
148
+ {
149
+ return !list_empty (& dev -> net -> adj_list .upper );
150
+ }
151
+
152
+ static int qmimux_rx_fixup (struct usbnet * dev , struct sk_buff * skb )
153
+ {
154
+ unsigned int len , offset = sizeof (struct qmimux_hdr );
155
+ struct qmimux_hdr * hdr ;
156
+ struct net_device * net ;
157
+ struct sk_buff * skbn ;
158
+
159
+ while (offset < skb -> len ) {
160
+ hdr = (struct qmimux_hdr * )skb -> data ;
161
+ len = be16_to_cpu (hdr -> pkt_len );
162
+
163
+ /* drop the packet, bogus length */
164
+ if (offset + len > skb -> len )
165
+ return 0 ;
166
+
167
+ /* control packet, we do not know what to do */
168
+ if (hdr -> pad & 0x80 )
169
+ goto skip ;
170
+
171
+ net = qmimux_find_dev (dev , hdr -> mux_id );
172
+ if (!net )
173
+ goto skip ;
174
+ skbn = netdev_alloc_skb (net , len );
175
+ if (!skbn )
176
+ return 0 ;
177
+ skbn -> dev = net ;
178
+
179
+ switch (skb -> data [offset ] & 0xf0 ) {
180
+ case 0x40 :
181
+ skbn -> protocol = htons (ETH_P_IP );
182
+ break ;
183
+ case 0x60 :
184
+ skbn -> protocol = htons (ETH_P_IPV6 );
185
+ break ;
186
+ default :
187
+ /* not ip - do not know what to do */
188
+ goto skip ;
189
+ }
190
+
191
+ memcpy (skb_put (skbn , len ), skb -> data + offset , len );
192
+ if (netif_rx (skbn ) != NET_RX_SUCCESS )
193
+ return 0 ;
194
+
195
+ skip :
196
+ offset += len + sizeof (struct qmimux_hdr );
197
+ }
198
+ return 1 ;
199
+ }
200
+
201
+ static int qmimux_register_device (struct net_device * real_dev , u8 mux_id )
202
+ {
203
+ struct net_device * new_dev ;
204
+ struct qmimux_priv * priv ;
205
+ int err ;
206
+
207
+ new_dev = alloc_netdev (sizeof (struct qmimux_priv ),
208
+ "qmimux%d" , NET_NAME_UNKNOWN , qmimux_setup );
209
+ if (!new_dev )
210
+ return - ENOBUFS ;
211
+
212
+ dev_net_set (new_dev , dev_net (real_dev ));
213
+ priv = netdev_priv (new_dev );
214
+ priv -> mux_id = mux_id ;
215
+ priv -> real_dev = real_dev ;
216
+
217
+ err = register_netdevice (new_dev );
218
+ if (err < 0 )
219
+ goto out_free_newdev ;
220
+
221
+ /* Account for reference in struct qmimux_priv_priv */
222
+ dev_hold (real_dev );
223
+
224
+ err = netdev_upper_dev_link (real_dev , new_dev );
225
+ if (err )
226
+ goto out_unregister_netdev ;
227
+
228
+ netif_stacked_transfer_operstate (real_dev , new_dev );
229
+
230
+ return 0 ;
231
+
232
+ out_unregister_netdev :
233
+ unregister_netdevice (new_dev );
234
+ dev_put (real_dev );
235
+
236
+ out_free_newdev :
237
+ free_netdev (new_dev );
238
+ return err ;
239
+ }
240
+
241
+ static void qmimux_unregister_device (struct net_device * dev )
242
+ {
243
+ struct qmimux_priv * priv = netdev_priv (dev );
244
+ struct net_device * real_dev = priv -> real_dev ;
245
+
246
+ netdev_upper_dev_unlink (real_dev , dev );
247
+ unregister_netdevice (dev );
248
+
249
+ /* Get rid of the reference to real_dev */
250
+ dev_put (real_dev );
251
+ }
252
+
67
253
static void qmi_wwan_netdev_setup (struct net_device * net )
68
254
{
69
255
struct usbnet * dev = netdev_priv (net );
@@ -137,10 +323,114 @@ static ssize_t raw_ip_store(struct device *d, struct device_attribute *attr, co
137
323
return ret ;
138
324
}
139
325
326
+ static ssize_t add_mux_show (struct device * d , struct device_attribute * attr , char * buf )
327
+ {
328
+ struct net_device * dev = to_net_dev (d );
329
+ struct qmimux_priv * priv ;
330
+ struct list_head * iter ;
331
+ struct net_device * ldev ;
332
+ ssize_t count = 0 ;
333
+
334
+ rcu_read_lock ();
335
+ netdev_for_each_upper_dev_rcu (dev , ldev , iter ) {
336
+ priv = netdev_priv (ldev );
337
+ count += scnprintf (& buf [count ], PAGE_SIZE - count ,
338
+ "0x%02x\n" , priv -> mux_id );
339
+ }
340
+ rcu_read_unlock ();
341
+ return count ;
342
+ }
343
+
344
+ static ssize_t add_mux_store (struct device * d , struct device_attribute * attr , const char * buf , size_t len )
345
+ {
346
+ struct usbnet * dev = netdev_priv (to_net_dev (d ));
347
+ struct qmi_wwan_state * info = (void * )& dev -> data ;
348
+ u8 mux_id ;
349
+ int ret ;
350
+
351
+ if (kstrtou8 (buf , 0 , & mux_id ))
352
+ return - EINVAL ;
353
+
354
+ /* mux_id [1 - 0x7f] range empirically found */
355
+ if (mux_id < 1 || mux_id > 0x7f )
356
+ return - EINVAL ;
357
+
358
+ if (!rtnl_trylock ())
359
+ return restart_syscall ();
360
+
361
+ if (qmimux_find_dev (dev , mux_id )) {
362
+ netdev_err (dev -> net , "mux_id already present\n" );
363
+ ret = - EINVAL ;
364
+ goto err ;
365
+ }
366
+
367
+ /* we don't want to modify a running netdev */
368
+ if (netif_running (dev -> net )) {
369
+ netdev_err (dev -> net , "Cannot change a running device\n" );
370
+ ret = - EBUSY ;
371
+ goto err ;
372
+ }
373
+
374
+ ret = qmimux_register_device (dev -> net , mux_id );
375
+ if (!ret ) {
376
+ info -> flags |= QMI_WWAN_FLAG_MUX ;
377
+ ret = len ;
378
+ }
379
+ err :
380
+ rtnl_unlock ();
381
+ return ret ;
382
+ }
383
+
384
+ static ssize_t del_mux_show (struct device * d , struct device_attribute * attr , char * buf )
385
+ {
386
+ return add_mux_show (d , attr , buf );
387
+ }
388
+
389
+ static ssize_t del_mux_store (struct device * d , struct device_attribute * attr , const char * buf , size_t len )
390
+ {
391
+ struct usbnet * dev = netdev_priv (to_net_dev (d ));
392
+ struct qmi_wwan_state * info = (void * )& dev -> data ;
393
+ struct net_device * del_dev ;
394
+ u8 mux_id ;
395
+ int ret = 0 ;
396
+
397
+ if (kstrtou8 (buf , 0 , & mux_id ))
398
+ return - EINVAL ;
399
+
400
+ if (!rtnl_trylock ())
401
+ return restart_syscall ();
402
+
403
+ /* we don't want to modify a running netdev */
404
+ if (netif_running (dev -> net )) {
405
+ netdev_err (dev -> net , "Cannot change a running device\n" );
406
+ ret = - EBUSY ;
407
+ goto err ;
408
+ }
409
+
410
+ del_dev = qmimux_find_dev (dev , mux_id );
411
+ if (!del_dev ) {
412
+ netdev_err (dev -> net , "mux_id not present\n" );
413
+ ret = - EINVAL ;
414
+ goto err ;
415
+ }
416
+ qmimux_unregister_device (del_dev );
417
+
418
+ if (!qmimux_has_slaves (dev ))
419
+ info -> flags &= ~QMI_WWAN_FLAG_MUX ;
420
+ ret = len ;
421
+ err :
422
+ rtnl_unlock ();
423
+ return ret ;
424
+ }
425
+
140
426
static DEVICE_ATTR_RW (raw_ip );
427
+ static DEVICE_ATTR_RW (add_mux );
428
+ static DEVICE_ATTR_RW (del_mux );
141
429
142
430
static struct attribute * qmi_wwan_sysfs_attrs [] = {
143
431
& dev_attr_raw_ip .attr ,
432
+ & dev_attr_add_mux .attr ,
433
+ & dev_attr_del_mux .attr ,
144
434
NULL ,
145
435
};
146
436
@@ -184,6 +474,9 @@ static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
184
474
if (skb -> len < dev -> net -> hard_header_len )
185
475
return 0 ;
186
476
477
+ if (info -> flags & QMI_WWAN_FLAG_MUX )
478
+ return qmimux_rx_fixup (dev , skb );
479
+
187
480
switch (skb -> data [0 ] & 0xf0 ) {
188
481
case 0x40 :
189
482
proto = htons (ETH_P_IP );
@@ -1036,11 +1329,33 @@ static int qmi_wwan_probe(struct usb_interface *intf,
1036
1329
return usbnet_probe (intf , id );
1037
1330
}
1038
1331
1332
+ static void qmi_wwan_disconnect (struct usb_interface * intf )
1333
+ {
1334
+ struct usbnet * dev = usb_get_intfdata (intf );
1335
+ struct qmi_wwan_state * info = (void * )& dev -> data ;
1336
+ struct list_head * iter ;
1337
+ struct net_device * ldev ;
1338
+
1339
+ if (info -> flags & QMI_WWAN_FLAG_MUX ) {
1340
+ if (!rtnl_trylock ()) {
1341
+ restart_syscall ();
1342
+ return ;
1343
+ }
1344
+ rcu_read_lock ();
1345
+ netdev_for_each_upper_dev_rcu (dev -> net , ldev , iter )
1346
+ qmimux_unregister_device (ldev );
1347
+ rcu_read_unlock ();
1348
+ rtnl_unlock ();
1349
+ info -> flags &= ~QMI_WWAN_FLAG_MUX ;
1350
+ }
1351
+ usbnet_disconnect (intf );
1352
+ }
1353
+
1039
1354
static struct usb_driver qmi_wwan_driver = {
1040
1355
.name = "qmi_wwan" ,
1041
1356
.id_table = products ,
1042
1357
.probe = qmi_wwan_probe ,
1043
- .disconnect = usbnet_disconnect ,
1358
+ .disconnect = qmi_wwan_disconnect ,
1044
1359
.suspend = qmi_wwan_suspend ,
1045
1360
.resume = qmi_wwan_resume ,
1046
1361
.reset_resume = qmi_wwan_resume ,
0 commit comments