aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb/rndis_host.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-02-01 05:06:29 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2008-02-01 05:06:29 -0500
commitcec03afcb62fbbb0eaf943f6349ade61b89d7d40 (patch)
treecc80c13e373337d1c1dee9dd7269173da1f7c079 /drivers/net/usb/rndis_host.c
parent2da53b0134ad41b91556d2d2a322cc03487a1ab7 (diff)
parent4814bdbd590e835ecec2d5e505165ec1c19796b2 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (173 commits) [NETNS]: Lookup in FIB semantic hashes taking into account the namespace. [NETNS]: Add a namespace mark to fib_info. [IPV4]: fib_sync_down rework. [NETNS]: Process interface address manipulation routines in the namespace. [IPV4]: Small style cleanup of the error path in rtm_to_ifaddr. [IPV4]: Fix memory leak on error path during FIB initialization. [NETFILTER]: Ipv6-related xt_hashlimit compilation fix. [NET_SCHED]: Add flow classifier [NET_SCHED]: sch_sfq: make internal queues visible as classes [NET_SCHED]: sch_sfq: add support for external classifiers [NET_SCHED]: Constify struct tcf_ext_map [BLUETOOTH]: Fix bugs in previous conn add/del workqueue changes. [TCP]: Unexport sysctl_tcp_tso_win_divisor [IPV4]: Make struct ipv4_devconf static. [TR] net/802/tr.c: sysctl_tr_rif_timeout static [XFRM]: Fix statistics. [XFRM]: Remove unused exports. [PKT_SCHED] sch_teql.c: Duplicate IFF_BROADCAST in FMASK, remove 2nd. [BNX2]: Fix ASYM PAUSE advertisement for remote PHY. [IPV4] route cache: Introduce rt_genid for smooth cache invalidation ...
Diffstat (limited to 'drivers/net/usb/rndis_host.c')
-rw-r--r--drivers/net/usb/rndis_host.c303
1 files changed, 83 insertions, 220 deletions
diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c
index 1ebe3259be0d..a61324757b17 100644
--- a/drivers/net/usb/rndis_host.c
+++ b/drivers/net/usb/rndis_host.c
@@ -29,8 +29,8 @@
29#include <linux/mii.h> 29#include <linux/mii.h>
30#include <linux/usb.h> 30#include <linux/usb.h>
31#include <linux/usb/cdc.h> 31#include <linux/usb/cdc.h>
32 32#include <linux/usb/usbnet.h>
33#include "usbnet.h" 33#include <linux/usb/rndis_host.h>
34 34
35 35
36/* 36/*
@@ -56,217 +56,17 @@
56 */ 56 */
57 57
58/* 58/*
59 * CONTROL uses CDC "encapsulated commands" with funky notifications.
60 * - control-out: SEND_ENCAPSULATED
61 * - interrupt-in: RESPONSE_AVAILABLE
62 * - control-in: GET_ENCAPSULATED
63 *
64 * We'll try to ignore the RESPONSE_AVAILABLE notifications.
65 *
66 * REVISIT some RNDIS implementations seem to have curious issues still
67 * to be resolved.
68 */
69struct rndis_msg_hdr {
70 __le32 msg_type; /* RNDIS_MSG_* */
71 __le32 msg_len;
72 // followed by data that varies between messages
73 __le32 request_id;
74 __le32 status;
75 // ... and more
76} __attribute__ ((packed));
77
78/* MS-Windows uses this strange size, but RNDIS spec says 1024 minimum */
79#define CONTROL_BUFFER_SIZE 1025
80
81/* RNDIS defines an (absurdly huge) 10 second control timeout,
82 * but ActiveSync seems to use a more usual 5 second timeout
83 * (which matches the USB 2.0 spec).
84 */
85#define RNDIS_CONTROL_TIMEOUT_MS (5 * 1000)
86
87
88#define ccpu2 __constant_cpu_to_le32
89
90#define RNDIS_MSG_COMPLETION ccpu2(0x80000000)
91
92/* codes for "msg_type" field of rndis messages;
93 * only the data channel uses packet messages (maybe batched);
94 * everything else goes on the control channel.
95 */
96#define RNDIS_MSG_PACKET ccpu2(0x00000001) /* 1-N packets */
97#define RNDIS_MSG_INIT ccpu2(0x00000002)
98#define RNDIS_MSG_INIT_C (RNDIS_MSG_INIT|RNDIS_MSG_COMPLETION)
99#define RNDIS_MSG_HALT ccpu2(0x00000003)
100#define RNDIS_MSG_QUERY ccpu2(0x00000004)
101#define RNDIS_MSG_QUERY_C (RNDIS_MSG_QUERY|RNDIS_MSG_COMPLETION)
102#define RNDIS_MSG_SET ccpu2(0x00000005)
103#define RNDIS_MSG_SET_C (RNDIS_MSG_SET|RNDIS_MSG_COMPLETION)
104#define RNDIS_MSG_RESET ccpu2(0x00000006)
105#define RNDIS_MSG_RESET_C (RNDIS_MSG_RESET|RNDIS_MSG_COMPLETION)
106#define RNDIS_MSG_INDICATE ccpu2(0x00000007)
107#define RNDIS_MSG_KEEPALIVE ccpu2(0x00000008)
108#define RNDIS_MSG_KEEPALIVE_C (RNDIS_MSG_KEEPALIVE|RNDIS_MSG_COMPLETION)
109
110/* codes for "status" field of completion messages */
111#define RNDIS_STATUS_SUCCESS ccpu2(0x00000000)
112#define RNDIS_STATUS_FAILURE ccpu2(0xc0000001)
113#define RNDIS_STATUS_INVALID_DATA ccpu2(0xc0010015)
114#define RNDIS_STATUS_NOT_SUPPORTED ccpu2(0xc00000bb)
115#define RNDIS_STATUS_MEDIA_CONNECT ccpu2(0x4001000b)
116#define RNDIS_STATUS_MEDIA_DISCONNECT ccpu2(0x4001000c)
117
118
119struct rndis_data_hdr {
120 __le32 msg_type; /* RNDIS_MSG_PACKET */
121 __le32 msg_len; // rndis_data_hdr + data_len + pad
122 __le32 data_offset; // 36 -- right after header
123 __le32 data_len; // ... real packet size
124
125 __le32 oob_data_offset; // zero
126 __le32 oob_data_len; // zero
127 __le32 num_oob; // zero
128 __le32 packet_data_offset; // zero
129
130 __le32 packet_data_len; // zero
131 __le32 vc_handle; // zero
132 __le32 reserved; // zero
133} __attribute__ ((packed));
134
135struct rndis_init { /* OUT */
136 // header and:
137 __le32 msg_type; /* RNDIS_MSG_INIT */
138 __le32 msg_len; // 24
139 __le32 request_id;
140 __le32 major_version; // of rndis (1.0)
141 __le32 minor_version;
142 __le32 max_transfer_size;
143} __attribute__ ((packed));
144
145struct rndis_init_c { /* IN */
146 // header and:
147 __le32 msg_type; /* RNDIS_MSG_INIT_C */
148 __le32 msg_len;
149 __le32 request_id;
150 __le32 status;
151 __le32 major_version; // of rndis (1.0)
152 __le32 minor_version;
153 __le32 device_flags;
154 __le32 medium; // zero == 802.3
155 __le32 max_packets_per_message;
156 __le32 max_transfer_size;
157 __le32 packet_alignment; // max 7; (1<<n) bytes
158 __le32 af_list_offset; // zero
159 __le32 af_list_size; // zero
160} __attribute__ ((packed));
161
162struct rndis_halt { /* OUT (no reply) */
163 // header and:
164 __le32 msg_type; /* RNDIS_MSG_HALT */
165 __le32 msg_len;
166 __le32 request_id;
167} __attribute__ ((packed));
168
169struct rndis_query { /* OUT */
170 // header and:
171 __le32 msg_type; /* RNDIS_MSG_QUERY */
172 __le32 msg_len;
173 __le32 request_id;
174 __le32 oid;
175 __le32 len;
176 __le32 offset;
177/*?*/ __le32 handle; // zero
178} __attribute__ ((packed));
179
180struct rndis_query_c { /* IN */
181 // header and:
182 __le32 msg_type; /* RNDIS_MSG_QUERY_C */
183 __le32 msg_len;
184 __le32 request_id;
185 __le32 status;
186 __le32 len;
187 __le32 offset;
188} __attribute__ ((packed));
189
190struct rndis_set { /* OUT */
191 // header and:
192 __le32 msg_type; /* RNDIS_MSG_SET */
193 __le32 msg_len;
194 __le32 request_id;
195 __le32 oid;
196 __le32 len;
197 __le32 offset;
198/*?*/ __le32 handle; // zero
199} __attribute__ ((packed));
200
201struct rndis_set_c { /* IN */
202 // header and:
203 __le32 msg_type; /* RNDIS_MSG_SET_C */
204 __le32 msg_len;
205 __le32 request_id;
206 __le32 status;
207} __attribute__ ((packed));
208
209struct rndis_reset { /* IN */
210 // header and:
211 __le32 msg_type; /* RNDIS_MSG_RESET */
212 __le32 msg_len;
213 __le32 reserved;
214} __attribute__ ((packed));
215
216struct rndis_reset_c { /* OUT */
217 // header and:
218 __le32 msg_type; /* RNDIS_MSG_RESET_C */
219 __le32 msg_len;
220 __le32 status;
221 __le32 addressing_lost;
222} __attribute__ ((packed));
223
224struct rndis_indicate { /* IN (unrequested) */
225 // header and:
226 __le32 msg_type; /* RNDIS_MSG_INDICATE */
227 __le32 msg_len;
228 __le32 status;
229 __le32 length;
230 __le32 offset;
231/**/ __le32 diag_status;
232 __le32 error_offset;
233/**/ __le32 message;
234} __attribute__ ((packed));
235
236struct rndis_keepalive { /* OUT (optionally IN) */
237 // header and:
238 __le32 msg_type; /* RNDIS_MSG_KEEPALIVE */
239 __le32 msg_len;
240 __le32 request_id;
241} __attribute__ ((packed));
242
243struct rndis_keepalive_c { /* IN (optionally OUT) */
244 // header and:
245 __le32 msg_type; /* RNDIS_MSG_KEEPALIVE_C */
246 __le32 msg_len;
247 __le32 request_id;
248 __le32 status;
249} __attribute__ ((packed));
250
251/* NOTE: about 30 OIDs are "mandatory" for peripherals to support ... and
252 * there are gobs more that may optionally be supported. We'll avoid as much
253 * of that mess as possible.
254 */
255#define OID_802_3_PERMANENT_ADDRESS ccpu2(0x01010101)
256#define OID_GEN_MAXIMUM_FRAME_SIZE ccpu2(0x00010106)
257#define OID_GEN_CURRENT_PACKET_FILTER ccpu2(0x0001010e)
258
259/*
260 * RNDIS notifications from device: command completion; "reverse" 59 * RNDIS notifications from device: command completion; "reverse"
261 * keepalives; etc 60 * keepalives; etc
262 */ 61 */
263static void rndis_status(struct usbnet *dev, struct urb *urb) 62void rndis_status(struct usbnet *dev, struct urb *urb)
264{ 63{
265 devdbg(dev, "rndis status urb, len %d stat %d", 64 devdbg(dev, "rndis status urb, len %d stat %d",
266 urb->actual_length, urb->status); 65 urb->actual_length, urb->status);
267 // FIXME for keepalives, respond immediately (asynchronously) 66 // FIXME for keepalives, respond immediately (asynchronously)
268 // if not an RNDIS status, do like cdc_status(dev,urb) does 67 // if not an RNDIS status, do like cdc_status(dev,urb) does
269} 68}
69EXPORT_SYMBOL_GPL(rndis_status);
270 70
271/* 71/*
272 * RPC done RNDIS-style. Caller guarantees: 72 * RPC done RNDIS-style. Caller guarantees:
@@ -278,7 +78,7 @@ static void rndis_status(struct usbnet *dev, struct urb *urb)
278 * Call context is likely probe(), before interface name is known, 78 * Call context is likely probe(), before interface name is known,
279 * which is why we won't try to use it in the diagnostics. 79 * which is why we won't try to use it in the diagnostics.
280 */ 80 */
281static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf) 81int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf)
282{ 82{
283 struct cdc_state *info = (void *) &dev->data; 83 struct cdc_state *info = (void *) &dev->data;
284 int master_ifnum; 84 int master_ifnum;
@@ -347,10 +147,26 @@ static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf)
347 request_id, xid); 147 request_id, xid);
348 /* then likely retry */ 148 /* then likely retry */
349 } else switch (buf->msg_type) { 149 } else switch (buf->msg_type) {
350 case RNDIS_MSG_INDICATE: { /* fault */ 150 case RNDIS_MSG_INDICATE: { /* fault/event */
351 // struct rndis_indicate *msg = (void *)buf; 151 struct rndis_indicate *msg = (void *)buf;
352 dev_info(&info->control->dev, 152 int state = 0;
353 "rndis fault indication\n"); 153
154 switch (msg->status) {
155 case RNDIS_STATUS_MEDIA_CONNECT:
156 state = 1;
157 case RNDIS_STATUS_MEDIA_DISCONNECT:
158 dev_info(&info->control->dev,
159 "rndis media %sconnect\n",
160 !state?"dis":"");
161 if (dev->driver_info->link_change)
162 dev->driver_info->link_change(
163 dev, state);
164 break;
165 default:
166 dev_info(&info->control->dev,
167 "rndis indication: 0x%08x\n",
168 le32_to_cpu(msg->status));
169 }
354 } 170 }
355 break; 171 break;
356 case RNDIS_MSG_KEEPALIVE: { /* ping */ 172 case RNDIS_MSG_KEEPALIVE: { /* ping */
@@ -387,6 +203,7 @@ static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf)
387 dev_dbg(&info->control->dev, "rndis response timeout\n"); 203 dev_dbg(&info->control->dev, "rndis response timeout\n");
388 return -ETIMEDOUT; 204 return -ETIMEDOUT;
389} 205}
206EXPORT_SYMBOL_GPL(rndis_command);
390 207
391/* 208/*
392 * rndis_query: 209 * rndis_query:
@@ -453,7 +270,8 @@ response_error:
453 return -EDOM; 270 return -EDOM;
454} 271}
455 272
456static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) 273int
274generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags)
457{ 275{
458 int retval; 276 int retval;
459 struct net_device *net = dev->net; 277 struct net_device *net = dev->net;
@@ -467,8 +285,9 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
467 struct rndis_query_c *get_c; 285 struct rndis_query_c *get_c;
468 struct rndis_set *set; 286 struct rndis_set *set;
469 struct rndis_set_c *set_c; 287 struct rndis_set_c *set_c;
288 struct rndis_halt *halt;
470 } u; 289 } u;
471 u32 tmp; 290 u32 tmp, *phym;
472 int reply_len; 291 int reply_len;
473 unsigned char *bp; 292 unsigned char *bp;
474 293
@@ -517,7 +336,7 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
517 "dev can't take %u byte packets (max %u)\n", 336 "dev can't take %u byte packets (max %u)\n",
518 dev->hard_mtu, tmp); 337 dev->hard_mtu, tmp);
519 retval = -EINVAL; 338 retval = -EINVAL;
520 goto fail_and_release; 339 goto halt_fail_and_release;
521 } 340 }
522 dev->hard_mtu = tmp; 341 dev->hard_mtu = tmp;
523 net->mtu = dev->hard_mtu - net->hard_header_len; 342 net->mtu = dev->hard_mtu - net->hard_header_len;
@@ -533,13 +352,43 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
533 dev->hard_mtu, tmp, dev->rx_urb_size, 352 dev->hard_mtu, tmp, dev->rx_urb_size,
534 1 << le32_to_cpu(u.init_c->packet_alignment)); 353 1 << le32_to_cpu(u.init_c->packet_alignment));
535 354
355 /* module has some device initialization code needs to be done right
356 * after RNDIS_INIT */
357 if (dev->driver_info->early_init &&
358 dev->driver_info->early_init(dev) != 0)
359 goto halt_fail_and_release;
360
361 /* Check physical medium */
362 reply_len = sizeof *phym;
363 retval = rndis_query(dev, intf, u.buf, OID_GEN_PHYSICAL_MEDIUM,
364 0, (void **) &phym, &reply_len);
365 if (retval != 0)
366 /* OID is optional so don't fail here. */
367 *phym = RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED;
368 if ((flags & FLAG_RNDIS_PHYM_WIRELESS) &&
369 *phym != RNDIS_PHYSICAL_MEDIUM_WIRELESS_LAN) {
370 if (netif_msg_probe(dev))
371 dev_dbg(&intf->dev, "driver requires wireless "
372 "physical medium, but device is not.\n");
373 retval = -ENODEV;
374 goto halt_fail_and_release;
375 }
376 if ((flags & FLAG_RNDIS_PHYM_NOT_WIRELESS) &&
377 *phym == RNDIS_PHYSICAL_MEDIUM_WIRELESS_LAN) {
378 if (netif_msg_probe(dev))
379 dev_dbg(&intf->dev, "driver requires non-wireless "
380 "physical medium, but device is wireless.\n");
381 retval = -ENODEV;
382 goto halt_fail_and_release;
383 }
384
536 /* Get designated host ethernet address */ 385 /* Get designated host ethernet address */
537 reply_len = ETH_ALEN; 386 reply_len = ETH_ALEN;
538 retval = rndis_query(dev, intf, u.buf, OID_802_3_PERMANENT_ADDRESS, 387 retval = rndis_query(dev, intf, u.buf, OID_802_3_PERMANENT_ADDRESS,
539 48, (void **) &bp, &reply_len); 388 48, (void **) &bp, &reply_len);
540 if (unlikely(retval< 0)) { 389 if (unlikely(retval< 0)) {
541 dev_err(&intf->dev, "rndis get ethaddr, %d\n", retval); 390 dev_err(&intf->dev, "rndis get ethaddr, %d\n", retval);
542 goto fail_and_release; 391 goto halt_fail_and_release;
543 } 392 }
544 memcpy(net->dev_addr, bp, ETH_ALEN); 393 memcpy(net->dev_addr, bp, ETH_ALEN);
545 394
@@ -550,12 +399,12 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
550 u.set->oid = OID_GEN_CURRENT_PACKET_FILTER; 399 u.set->oid = OID_GEN_CURRENT_PACKET_FILTER;
551 u.set->len = ccpu2(4); 400 u.set->len = ccpu2(4);
552 u.set->offset = ccpu2((sizeof *u.set) - 8); 401 u.set->offset = ccpu2((sizeof *u.set) - 8);
553 *(__le32 *)(u.buf + sizeof *u.set) = ccpu2(DEFAULT_FILTER); 402 *(__le32 *)(u.buf + sizeof *u.set) = RNDIS_DEFAULT_FILTER;
554 403
555 retval = rndis_command(dev, u.header); 404 retval = rndis_command(dev, u.header);
556 if (unlikely(retval < 0)) { 405 if (unlikely(retval < 0)) {
557 dev_err(&intf->dev, "rndis set packet filter, %d\n", retval); 406 dev_err(&intf->dev, "rndis set packet filter, %d\n", retval);
558 goto fail_and_release; 407 goto halt_fail_and_release;
559 } 408 }
560 409
561 retval = 0; 410 retval = 0;
@@ -563,6 +412,11 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
563 kfree(u.buf); 412 kfree(u.buf);
564 return retval; 413 return retval;
565 414
415halt_fail_and_release:
416 memset(u.halt, 0, sizeof *u.halt);
417 u.halt->msg_type = RNDIS_MSG_HALT;
418 u.halt->msg_len = ccpu2(sizeof *u.halt);
419 (void) rndis_command(dev, (void *)u.halt);
566fail_and_release: 420fail_and_release:
567 usb_set_intfdata(info->data, NULL); 421 usb_set_intfdata(info->data, NULL);
568 usb_driver_release_interface(driver_of(intf), info->data); 422 usb_driver_release_interface(driver_of(intf), info->data);
@@ -571,13 +425,19 @@ fail:
571 kfree(u.buf); 425 kfree(u.buf);
572 return retval; 426 return retval;
573} 427}
428EXPORT_SYMBOL_GPL(generic_rndis_bind);
429
430static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
431{
432 return generic_rndis_bind(dev, intf, FLAG_RNDIS_PHYM_NOT_WIRELESS);
433}
574 434
575static void rndis_unbind(struct usbnet *dev, struct usb_interface *intf) 435void rndis_unbind(struct usbnet *dev, struct usb_interface *intf)
576{ 436{
577 struct rndis_halt *halt; 437 struct rndis_halt *halt;
578 438
579 /* try to clear any rndis state/activity (no i/o from stack!) */ 439 /* try to clear any rndis state/activity (no i/o from stack!) */
580 halt = kzalloc(sizeof *halt, GFP_KERNEL); 440 halt = kzalloc(CONTROL_BUFFER_SIZE, GFP_KERNEL);
581 if (halt) { 441 if (halt) {
582 halt->msg_type = RNDIS_MSG_HALT; 442 halt->msg_type = RNDIS_MSG_HALT;
583 halt->msg_len = ccpu2(sizeof *halt); 443 halt->msg_len = ccpu2(sizeof *halt);
@@ -585,13 +445,14 @@ static void rndis_unbind(struct usbnet *dev, struct usb_interface *intf)
585 kfree(halt); 445 kfree(halt);
586 } 446 }
587 447
588 return usbnet_cdc_unbind(dev, intf); 448 usbnet_cdc_unbind(dev, intf);
589} 449}
450EXPORT_SYMBOL_GPL(rndis_unbind);
590 451
591/* 452/*
592 * DATA -- host must not write zlps 453 * DATA -- host must not write zlps
593 */ 454 */
594static int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb) 455int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
595{ 456{
596 /* peripheral may have batched packets to us... */ 457 /* peripheral may have batched packets to us... */
597 while (likely(skb->len)) { 458 while (likely(skb->len)) {
@@ -633,8 +494,9 @@ static int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
633 /* caller will usbnet_skb_return the remaining packet */ 494 /* caller will usbnet_skb_return the remaining packet */
634 return 1; 495 return 1;
635} 496}
497EXPORT_SYMBOL_GPL(rndis_rx_fixup);
636 498
637static struct sk_buff * 499struct sk_buff *
638rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) 500rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
639{ 501{
640 struct rndis_data_hdr *hdr; 502 struct rndis_data_hdr *hdr;
@@ -679,6 +541,7 @@ fill:
679 /* FIXME make the last packet always be short ... */ 541 /* FIXME make the last packet always be short ... */
680 return skb; 542 return skb;
681} 543}
544EXPORT_SYMBOL_GPL(rndis_tx_fixup);
682 545
683 546
684static const struct driver_info rndis_info = { 547static const struct driver_info rndis_info = {