source: rtems-libbsd/freebsd/sys/dev/usb/net/usb_ethernet.c @ d145449

55-freebsd-126-freebsd-12
Last change on this file since d145449 was d145449, checked in by Christian Mauderer <Christian.Mauderer@…>, on 11/14/16 at 12:30:48

Import USB and USB WLAN from FreeBSD.

  • Property mode set to 100644
File size: 14.3 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
3/* $FreeBSD$ */
4/*-
5 * Copyright (c) 2009 Andrew Thompson (thompsa@FreeBSD.org)
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD$");
31
32#include <rtems/bsd/sys/param.h>
33#include <sys/systm.h>
34#include <sys/bus.h>
35#include <sys/condvar.h>
36#include <sys/kernel.h>
37#include <rtems/bsd/sys/lock.h>
38#include <sys/malloc.h>
39#include <sys/mbuf.h>
40#include <sys/module.h>
41#include <sys/mutex.h>
42#include <sys/socket.h>
43#include <sys/sockio.h>
44#include <sys/sysctl.h>
45#include <sys/sx.h>
46
47#include <net/if.h>
48#include <net/if_var.h>
49#include <net/ethernet.h>
50#include <net/if_types.h>
51#include <net/if_media.h>
52#include <net/if_vlan_var.h>
53
54#include <dev/mii/mii.h>
55#include <dev/mii/miivar.h>
56
57#include <dev/usb/usb.h>
58#include <dev/usb/usbdi.h>
59
60#include <dev/usb/usb_process.h>
61#include <dev/usb/net/usb_ethernet.h>
62
63static SYSCTL_NODE(_net, OID_AUTO, ue, CTLFLAG_RD, 0,
64    "USB Ethernet parameters");
65
66#define UE_LOCK(_ue)            mtx_lock((_ue)->ue_mtx)
67#define UE_UNLOCK(_ue)          mtx_unlock((_ue)->ue_mtx)
68#define UE_LOCK_ASSERT(_ue, t)  mtx_assert((_ue)->ue_mtx, t)
69
70MODULE_DEPEND(uether, usb, 1, 1, 1);
71MODULE_DEPEND(uether, miibus, 1, 1, 1);
72
73static struct unrhdr *ueunit;
74
75static usb_proc_callback_t ue_attach_post_task;
76static usb_proc_callback_t ue_promisc_task;
77static usb_proc_callback_t ue_setmulti_task;
78static usb_proc_callback_t ue_ifmedia_task;
79static usb_proc_callback_t ue_tick_task;
80static usb_proc_callback_t ue_start_task;
81static usb_proc_callback_t ue_stop_task;
82
83static void     ue_init(void *);
84static void     ue_start(struct ifnet *);
85static int      ue_ifmedia_upd(struct ifnet *);
86static void     ue_watchdog(void *);
87
88/*
89 * Return values:
90 *    0: success
91 * Else: device has been detached
92 */
93uint8_t
94uether_pause(struct usb_ether *ue, unsigned int _ticks)
95{
96        if (usb_proc_is_gone(&ue->ue_tq)) {
97                /* nothing to do */
98                return (1);
99        }
100        usb_pause_mtx(ue->ue_mtx, _ticks);
101        return (0);
102}
103
104static void
105ue_queue_command(struct usb_ether *ue,
106    usb_proc_callback_t *fn,
107    struct usb_proc_msg *t0, struct usb_proc_msg *t1)
108{
109        struct usb_ether_cfg_task *task;
110
111        UE_LOCK_ASSERT(ue, MA_OWNED);
112
113        if (usb_proc_is_gone(&ue->ue_tq)) {
114                return;         /* nothing to do */
115        }
116        /*
117         * NOTE: The task cannot get executed before we drop the
118         * "sc_mtx" mutex. It is safe to update fields in the message
119         * structure after that the message got queued.
120         */
121        task = (struct usb_ether_cfg_task *)
122          usb_proc_msignal(&ue->ue_tq, t0, t1);
123
124        /* Setup callback and self pointers */
125        task->hdr.pm_callback = fn;
126        task->ue = ue;
127
128        /*
129         * Start and stop must be synchronous!
130         */
131        if ((fn == ue_start_task) || (fn == ue_stop_task))
132                usb_proc_mwait(&ue->ue_tq, t0, t1);
133}
134
135struct ifnet *
136uether_getifp(struct usb_ether *ue)
137{
138        return (ue->ue_ifp);
139}
140
141struct mii_data *
142uether_getmii(struct usb_ether *ue)
143{
144        return (device_get_softc(ue->ue_miibus));
145}
146
147void *
148uether_getsc(struct usb_ether *ue)
149{
150        return (ue->ue_sc);
151}
152
153static int
154ue_sysctl_parent(SYSCTL_HANDLER_ARGS)
155{
156        struct usb_ether *ue = arg1;
157        const char *name;
158
159        name = device_get_nameunit(ue->ue_dev);
160        return SYSCTL_OUT_STR(req, name);
161}
162
163int
164uether_ifattach(struct usb_ether *ue)
165{
166        int error;
167
168        /* check some critical parameters */
169        if ((ue->ue_dev == NULL) ||
170            (ue->ue_udev == NULL) ||
171            (ue->ue_mtx == NULL) ||
172            (ue->ue_methods == NULL))
173                return (EINVAL);
174
175        error = usb_proc_create(&ue->ue_tq, ue->ue_mtx,
176            device_get_nameunit(ue->ue_dev), USB_PRI_MED);
177        if (error) {
178                device_printf(ue->ue_dev, "could not setup taskqueue\n");
179                goto error;
180        }
181
182        /* fork rest of the attach code */
183        UE_LOCK(ue);
184        ue_queue_command(ue, ue_attach_post_task,
185            &ue->ue_sync_task[0].hdr,
186            &ue->ue_sync_task[1].hdr);
187        UE_UNLOCK(ue);
188
189error:
190        return (error);
191}
192
193static void
194ue_attach_post_task(struct usb_proc_msg *_task)
195{
196        struct usb_ether_cfg_task *task =
197            (struct usb_ether_cfg_task *)_task;
198        struct usb_ether *ue = task->ue;
199        struct ifnet *ifp;
200        int error;
201        char num[14];                   /* sufficient for 32 bits */
202
203        /* first call driver's post attach routine */
204        ue->ue_methods->ue_attach_post(ue);
205
206        UE_UNLOCK(ue);
207
208        ue->ue_unit = alloc_unr(ueunit);
209        usb_callout_init_mtx(&ue->ue_watchdog, ue->ue_mtx, 0);
210        sysctl_ctx_init(&ue->ue_sysctl_ctx);
211
212        error = 0;
213        CURVNET_SET_QUIET(vnet0);
214        ifp = if_alloc(IFT_ETHER);
215        if (ifp == NULL) {
216                device_printf(ue->ue_dev, "could not allocate ifnet\n");
217                goto fail;
218        }
219
220        ifp->if_softc = ue;
221        if_initname(ifp, "ue", ue->ue_unit);
222        if (ue->ue_methods->ue_attach_post_sub != NULL) {
223                ue->ue_ifp = ifp;
224                error = ue->ue_methods->ue_attach_post_sub(ue);
225        } else {
226                ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
227                if (ue->ue_methods->ue_ioctl != NULL)
228                        ifp->if_ioctl = ue->ue_methods->ue_ioctl;
229                else
230                        ifp->if_ioctl = uether_ioctl;
231                ifp->if_start = ue_start;
232                ifp->if_init = ue_init;
233                IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
234                ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
235                IFQ_SET_READY(&ifp->if_snd);
236                ue->ue_ifp = ifp;
237
238                if (ue->ue_methods->ue_mii_upd != NULL &&
239                    ue->ue_methods->ue_mii_sts != NULL) {
240                        /* device_xxx() depends on this */
241                        mtx_lock(&Giant);
242                        error = mii_attach(ue->ue_dev, &ue->ue_miibus, ifp,
243                            ue_ifmedia_upd, ue->ue_methods->ue_mii_sts,
244                            BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0);
245                        mtx_unlock(&Giant);
246                }
247        }
248
249        if (error) {
250                device_printf(ue->ue_dev, "attaching PHYs failed\n");
251                goto fail;
252        }
253
254        if_printf(ifp, "<USB Ethernet> on %s\n", device_get_nameunit(ue->ue_dev));
255        ether_ifattach(ifp, ue->ue_eaddr);
256        /* Tell upper layer we support VLAN oversized frames. */
257        if (ifp->if_capabilities & IFCAP_VLAN_MTU)
258                ifp->if_hdrlen = sizeof(struct ether_vlan_header);
259
260        CURVNET_RESTORE();
261
262        snprintf(num, sizeof(num), "%u", ue->ue_unit);
263        ue->ue_sysctl_oid = SYSCTL_ADD_NODE(&ue->ue_sysctl_ctx,
264            &SYSCTL_NODE_CHILDREN(_net, ue),
265            OID_AUTO, num, CTLFLAG_RD, NULL, "");
266        SYSCTL_ADD_PROC(&ue->ue_sysctl_ctx,
267            SYSCTL_CHILDREN(ue->ue_sysctl_oid), OID_AUTO,
268            "%parent", CTLTYPE_STRING | CTLFLAG_RD, ue, 0,
269            ue_sysctl_parent, "A", "parent device");
270
271        UE_LOCK(ue);
272        return;
273
274fail:
275        CURVNET_RESTORE();
276        free_unr(ueunit, ue->ue_unit);
277        if (ue->ue_ifp != NULL) {
278                if_free(ue->ue_ifp);
279                ue->ue_ifp = NULL;
280        }
281        UE_LOCK(ue);
282        return;
283}
284
285void
286uether_ifdetach(struct usb_ether *ue)
287{
288        struct ifnet *ifp;
289
290        /* wait for any post attach or other command to complete */
291        usb_proc_drain(&ue->ue_tq);
292
293        /* read "ifnet" pointer after taskqueue drain */
294        ifp = ue->ue_ifp;
295
296        if (ifp != NULL) {
297
298                /* we are not running any more */
299                UE_LOCK(ue);
300                ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
301                UE_UNLOCK(ue);
302
303                /* drain any callouts */
304                usb_callout_drain(&ue->ue_watchdog);
305
306                /* detach miibus */
307                if (ue->ue_miibus != NULL) {
308                        mtx_lock(&Giant);       /* device_xxx() depends on this */
309                        device_delete_child(ue->ue_dev, ue->ue_miibus);
310                        mtx_unlock(&Giant);
311                }
312
313                /* detach ethernet */
314                ether_ifdetach(ifp);
315
316                /* free interface instance */
317                if_free(ifp);
318
319                /* free sysctl */
320                sysctl_ctx_free(&ue->ue_sysctl_ctx);
321
322                /* free unit */
323                free_unr(ueunit, ue->ue_unit);
324        }
325
326        /* free taskqueue, if any */
327        usb_proc_free(&ue->ue_tq);
328}
329
330uint8_t
331uether_is_gone(struct usb_ether *ue)
332{
333        return (usb_proc_is_gone(&ue->ue_tq));
334}
335
336void
337uether_init(void *arg)
338{
339
340        ue_init(arg);
341}
342
343static void
344ue_init(void *arg)
345{
346        struct usb_ether *ue = arg;
347
348        UE_LOCK(ue);
349        ue_queue_command(ue, ue_start_task,
350            &ue->ue_sync_task[0].hdr,
351            &ue->ue_sync_task[1].hdr);
352        UE_UNLOCK(ue);
353}
354
355static void
356ue_start_task(struct usb_proc_msg *_task)
357{
358        struct usb_ether_cfg_task *task =
359            (struct usb_ether_cfg_task *)_task;
360        struct usb_ether *ue = task->ue;
361        struct ifnet *ifp = ue->ue_ifp;
362
363        UE_LOCK_ASSERT(ue, MA_OWNED);
364
365        ue->ue_methods->ue_init(ue);
366
367        if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
368                return;
369
370        if (ue->ue_methods->ue_tick != NULL)
371                usb_callout_reset(&ue->ue_watchdog, hz, ue_watchdog, ue);
372}
373
374static void
375ue_stop_task(struct usb_proc_msg *_task)
376{
377        struct usb_ether_cfg_task *task =
378            (struct usb_ether_cfg_task *)_task;
379        struct usb_ether *ue = task->ue;
380
381        UE_LOCK_ASSERT(ue, MA_OWNED);
382
383        usb_callout_stop(&ue->ue_watchdog);
384
385        ue->ue_methods->ue_stop(ue);
386}
387
388void
389uether_start(struct ifnet *ifp)
390{
391
392        ue_start(ifp);
393}
394
395static void
396ue_start(struct ifnet *ifp)
397{
398        struct usb_ether *ue = ifp->if_softc;
399
400        if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
401                return;
402
403        UE_LOCK(ue);
404        ue->ue_methods->ue_start(ue);
405        UE_UNLOCK(ue);
406}
407
408static void
409ue_promisc_task(struct usb_proc_msg *_task)
410{
411        struct usb_ether_cfg_task *task =
412            (struct usb_ether_cfg_task *)_task;
413        struct usb_ether *ue = task->ue;
414
415        ue->ue_methods->ue_setpromisc(ue);
416}
417
418static void
419ue_setmulti_task(struct usb_proc_msg *_task)
420{
421        struct usb_ether_cfg_task *task =
422            (struct usb_ether_cfg_task *)_task;
423        struct usb_ether *ue = task->ue;
424
425        ue->ue_methods->ue_setmulti(ue);
426}
427
428int
429uether_ifmedia_upd(struct ifnet *ifp)
430{
431
432        return (ue_ifmedia_upd(ifp));
433}
434
435static int
436ue_ifmedia_upd(struct ifnet *ifp)
437{
438        struct usb_ether *ue = ifp->if_softc;
439
440        /* Defer to process context */
441        UE_LOCK(ue);
442        ue_queue_command(ue, ue_ifmedia_task,
443            &ue->ue_media_task[0].hdr,
444            &ue->ue_media_task[1].hdr);
445        UE_UNLOCK(ue);
446
447        return (0);
448}
449
450static void
451ue_ifmedia_task(struct usb_proc_msg *_task)
452{
453        struct usb_ether_cfg_task *task =
454            (struct usb_ether_cfg_task *)_task;
455        struct usb_ether *ue = task->ue;
456        struct ifnet *ifp = ue->ue_ifp;
457
458        ue->ue_methods->ue_mii_upd(ifp);
459}
460
461static void
462ue_watchdog(void *arg)
463{
464        struct usb_ether *ue = arg;
465        struct ifnet *ifp = ue->ue_ifp;
466
467        if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
468                return;
469
470        ue_queue_command(ue, ue_tick_task,
471            &ue->ue_tick_task[0].hdr,
472            &ue->ue_tick_task[1].hdr);
473
474        usb_callout_reset(&ue->ue_watchdog, hz, ue_watchdog, ue);
475}
476
477static void
478ue_tick_task(struct usb_proc_msg *_task)
479{
480        struct usb_ether_cfg_task *task =
481            (struct usb_ether_cfg_task *)_task;
482        struct usb_ether *ue = task->ue;
483        struct ifnet *ifp = ue->ue_ifp;
484
485        if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
486                return;
487
488        ue->ue_methods->ue_tick(ue);
489}
490
491int
492uether_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
493{
494        struct usb_ether *ue = ifp->if_softc;
495        struct ifreq *ifr = (struct ifreq *)data;
496        struct mii_data *mii;
497        int error = 0;
498
499        switch (command) {
500        case SIOCSIFFLAGS:
501                UE_LOCK(ue);
502                if (ifp->if_flags & IFF_UP) {
503                        if (ifp->if_drv_flags & IFF_DRV_RUNNING)
504                                ue_queue_command(ue, ue_promisc_task,
505                                    &ue->ue_promisc_task[0].hdr,
506                                    &ue->ue_promisc_task[1].hdr);
507                        else
508                                ue_queue_command(ue, ue_start_task,
509                                    &ue->ue_sync_task[0].hdr,
510                                    &ue->ue_sync_task[1].hdr);
511                } else {
512                        ue_queue_command(ue, ue_stop_task,
513                            &ue->ue_sync_task[0].hdr,
514                            &ue->ue_sync_task[1].hdr);
515                }
516                UE_UNLOCK(ue);
517                break;
518        case SIOCADDMULTI:
519        case SIOCDELMULTI:
520                UE_LOCK(ue);
521                ue_queue_command(ue, ue_setmulti_task,
522                    &ue->ue_multi_task[0].hdr,
523                    &ue->ue_multi_task[1].hdr);
524                UE_UNLOCK(ue);
525                break;
526        case SIOCGIFMEDIA:
527        case SIOCSIFMEDIA:
528                if (ue->ue_miibus != NULL) {
529                        mii = device_get_softc(ue->ue_miibus);
530                        error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
531                } else
532                        error = ether_ioctl(ifp, command, data);
533                break;
534        default:
535                error = ether_ioctl(ifp, command, data);
536                break;
537        }
538        return (error);
539}
540
541static int
542uether_modevent(module_t mod, int type, void *data)
543{
544
545        switch (type) {
546        case MOD_LOAD:
547                ueunit = new_unrhdr(0, INT_MAX, NULL);
548                break;
549        case MOD_UNLOAD:
550                break;
551        default:
552                return (EOPNOTSUPP);
553        }
554        return (0);
555}
556static moduledata_t uether_mod = {
557        "uether",
558        uether_modevent,
559        0
560};
561
562struct mbuf *
563uether_newbuf(void)
564{
565        struct mbuf *m_new;
566
567        m_new = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
568        if (m_new == NULL)
569                return (NULL);
570        m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
571
572        m_adj(m_new, ETHER_ALIGN);
573        return (m_new);
574}
575
576int
577uether_rxmbuf(struct usb_ether *ue, struct mbuf *m,
578    unsigned int len)
579{
580        struct ifnet *ifp = ue->ue_ifp;
581
582        UE_LOCK_ASSERT(ue, MA_OWNED);
583
584        /* finalize mbuf */
585        if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
586        m->m_pkthdr.rcvif = ifp;
587        m->m_pkthdr.len = m->m_len = len;
588
589        /* enqueue for later when the lock can be released */
590        _IF_ENQUEUE(&ue->ue_rxq, m);
591        return (0);
592}
593
594int
595uether_rxbuf(struct usb_ether *ue, struct usb_page_cache *pc,
596    unsigned int offset, unsigned int len)
597{
598        struct ifnet *ifp = ue->ue_ifp;
599        struct mbuf *m;
600
601        UE_LOCK_ASSERT(ue, MA_OWNED);
602
603        if (len < ETHER_HDR_LEN || len > MCLBYTES - ETHER_ALIGN)
604                return (1);
605
606        m = uether_newbuf();
607        if (m == NULL) {
608                if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
609                return (ENOMEM);
610        }
611
612        usbd_copy_out(pc, offset, mtod(m, uint8_t *), len);
613
614        /* finalize mbuf */
615        if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
616        m->m_pkthdr.rcvif = ifp;
617        m->m_pkthdr.len = m->m_len = len;
618
619        /* enqueue for later when the lock can be released */
620        _IF_ENQUEUE(&ue->ue_rxq, m);
621        return (0);
622}
623
624void
625uether_rxflush(struct usb_ether *ue)
626{
627        struct ifnet *ifp = ue->ue_ifp;
628        struct mbuf *m;
629
630        UE_LOCK_ASSERT(ue, MA_OWNED);
631
632        for (;;) {
633                _IF_DEQUEUE(&ue->ue_rxq, m);
634                if (m == NULL)
635                        break;
636
637                /*
638                 * The USB xfer has been resubmitted so its safe to unlock now.
639                 */
640                UE_UNLOCK(ue);
641                ifp->if_input(ifp, m);
642                UE_LOCK(ue);
643        }
644}
645
646/*
647 * USB net drivers are run by DRIVER_MODULE() thus SI_SUB_DRIVERS,
648 * SI_ORDER_MIDDLE.  Run uether after that.
649 */
650DECLARE_MODULE(uether, uether_mod, SI_SUB_DRIVERS, SI_ORDER_ANY);
651MODULE_VERSION(uether, 1);
Note: See TracBrowser for help on using the repository browser.