diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-02-01 05:06:29 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-02-01 05:06:29 -0500 |
commit | cec03afcb62fbbb0eaf943f6349ade61b89d7d40 (patch) | |
tree | cc80c13e373337d1c1dee9dd7269173da1f7c079 /drivers/net/usb/rndis_host.c | |
parent | 2da53b0134ad41b91556d2d2a322cc03487a1ab7 (diff) | |
parent | 4814bdbd590e835ecec2d5e505165ec1c19796b2 (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.c | 303 |
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 | */ | ||
69 | struct 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 | |||
119 | struct 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 | |||
135 | struct 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 | |||
145 | struct 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 | |||
162 | struct 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 | |||
169 | struct 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 | |||
180 | struct 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 | |||
190 | struct 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 | |||
201 | struct 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 | |||
209 | struct rndis_reset { /* IN */ | ||
210 | // header and: | ||
211 | __le32 msg_type; /* RNDIS_MSG_RESET */ | ||
212 | __le32 msg_len; | ||
213 | __le32 reserved; | ||
214 | } __attribute__ ((packed)); | ||
215 | |||
216 | struct 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 | |||
224 | struct 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 | |||
236 | struct 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 | |||
243 | struct 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 | */ |
263 | static void rndis_status(struct usbnet *dev, struct urb *urb) | 62 | void 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 | } |
69 | EXPORT_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 | */ |
281 | static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf) | 81 | int 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 | } |
206 | EXPORT_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 | ||
456 | static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) | 273 | int |
274 | generic_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 | ||
415 | halt_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); | ||
566 | fail_and_release: | 420 | fail_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 | } |
428 | EXPORT_SYMBOL_GPL(generic_rndis_bind); | ||
429 | |||
430 | static 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 | ||
575 | static void rndis_unbind(struct usbnet *dev, struct usb_interface *intf) | 435 | void 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 | } |
450 | EXPORT_SYMBOL_GPL(rndis_unbind); | ||
590 | 451 | ||
591 | /* | 452 | /* |
592 | * DATA -- host must not write zlps | 453 | * DATA -- host must not write zlps |
593 | */ | 454 | */ |
594 | static int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | 455 | int 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 | } |
497 | EXPORT_SYMBOL_GPL(rndis_rx_fixup); | ||
636 | 498 | ||
637 | static struct sk_buff * | 499 | struct sk_buff * |
638 | rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) | 500 | rndis_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 | } |
544 | EXPORT_SYMBOL_GPL(rndis_tx_fixup); | ||
682 | 545 | ||
683 | 546 | ||
684 | static const struct driver_info rndis_info = { | 547 | static const struct driver_info rndis_info = { |