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