usb_ethernet.c revision 192984
1/* $FreeBSD: head/sys/dev/usb/net/usb_ethernet.c 192984 2009-05-28 17:36:36Z thompsa $ */
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 <dev/usb/usb_mfunc.h>
28#include <dev/usb/usb_error.h>
29#include <dev/usb/usb_endian.h>
30#include <dev/usb/usb.h>
31
32#include <dev/usb/usb_core.h>
33#include <dev/usb/usb_process.h>
34#include <dev/usb/usb_busdma.h>
35#include <dev/usb/usb_request.h>
36#include <dev/usb/usb_util.h>
37
38#include <dev/usb/net/usb_ethernet.h>
39
40SYSCTL_NODE(_net, OID_AUTO, ue, CTLFLAG_RD, 0, "USB Ethernet parameters");
41
42#define	UE_LOCK(_ue)		mtx_lock((_ue)->ue_mtx)
43#define	UE_UNLOCK(_ue)		mtx_unlock((_ue)->ue_mtx)
44#define	UE_LOCK_ASSERT(_ue, t)	mtx_assert((_ue)->ue_mtx, t)
45
46MODULE_DEPEND(uether, usb, 1, 1, 1);
47MODULE_DEPEND(uether, miibus, 1, 1, 1);
48
49static struct unrhdr *ueunit;
50
51static usb2_proc_callback_t ue_attach_post_task;
52static usb2_proc_callback_t ue_promisc_task;
53static usb2_proc_callback_t ue_setmulti_task;
54static usb2_proc_callback_t ue_ifmedia_task;
55static usb2_proc_callback_t ue_tick_task;
56static usb2_proc_callback_t ue_start_task;
57static usb2_proc_callback_t ue_stop_task;
58
59static void	ue_init(void *);
60static void	ue_start(struct ifnet *);
61static int	ue_ifmedia_upd(struct ifnet *);
62static void	ue_watchdog(void *);
63
64/*
65 * Return values:
66 *    0: success
67 * Else: device has been detached
68 */
69uint8_t
70usb2_ether_pause(struct usb_ether *ue, unsigned int _ticks)
71{
72	if (usb2_proc_is_gone(&ue->ue_tq)) {
73		/* nothing to do */
74		return (1);
75	}
76	usb2_pause_mtx(ue->ue_mtx, _ticks);
77	return (0);
78}
79
80static void
81ue_queue_command(struct usb_ether *ue,
82    usb2_proc_callback_t *fn,
83    struct usb_proc_msg *t0, struct usb_proc_msg *t1)
84{
85	struct usb_ether_cfg_task *task;
86
87	UE_LOCK_ASSERT(ue, MA_OWNED);
88
89	if (usb2_proc_is_gone(&ue->ue_tq)) {
90		return;         /* nothing to do */
91	}
92	/*
93	 * NOTE: The task cannot get executed before we drop the
94	 * "sc_mtx" mutex. It is safe to update fields in the message
95	 * structure after that the message got queued.
96	 */
97	task = (struct usb_ether_cfg_task *)
98	  usb2_proc_msignal(&ue->ue_tq, t0, t1);
99
100	/* Setup callback and self pointers */
101	task->hdr.pm_callback = fn;
102	task->ue = ue;
103
104	/*
105	 * Start and stop must be synchronous!
106	 */
107	if ((fn == ue_start_task) || (fn == ue_stop_task))
108		usb2_proc_mwait(&ue->ue_tq, t0, t1);
109}
110
111struct ifnet *
112usb2_ether_getifp(struct usb_ether *ue)
113{
114	return (ue->ue_ifp);
115}
116
117struct mii_data *
118usb2_ether_getmii(struct usb_ether *ue)
119{
120	return (device_get_softc(ue->ue_miibus));
121}
122
123void *
124usb2_ether_getsc(struct usb_ether *ue)
125{
126	return (ue->ue_sc);
127}
128
129static int
130ue_sysctl_parent(SYSCTL_HANDLER_ARGS)
131{
132	struct usb_ether *ue = arg1;
133	const char *name;
134
135	name = device_get_nameunit(ue->ue_dev);
136	return SYSCTL_OUT(req, name, strlen(name));
137}
138
139int
140usb2_ether_ifattach(struct usb_ether *ue)
141{
142	int error;
143
144	/* check some critical parameters */
145	if ((ue->ue_dev == NULL) ||
146	    (ue->ue_udev == NULL) ||
147	    (ue->ue_mtx == NULL) ||
148	    (ue->ue_methods == NULL))
149		return (EINVAL);
150
151	error = usb2_proc_create(&ue->ue_tq, ue->ue_mtx,
152	    device_get_nameunit(ue->ue_dev), USB_PRI_MED);
153	if (error) {
154		device_printf(ue->ue_dev, "could not setup taskqueue\n");
155		goto error;
156	}
157
158	/* fork rest of the attach code */
159	UE_LOCK(ue);
160	ue_queue_command(ue, ue_attach_post_task,
161	    &ue->ue_sync_task[0].hdr,
162	    &ue->ue_sync_task[1].hdr);
163	UE_UNLOCK(ue);
164
165error:
166	return (error);
167}
168
169static void
170ue_attach_post_task(struct usb_proc_msg *_task)
171{
172	struct usb_ether_cfg_task *task =
173	    (struct usb_ether_cfg_task *)_task;
174	struct usb_ether *ue = task->ue;
175	struct ifnet *ifp;
176	int error;
177	char num[14];			/* sufficient for 32 bits */
178
179	/* first call driver's post attach routine */
180	ue->ue_methods->ue_attach_post(ue);
181
182	UE_UNLOCK(ue);
183
184	ue->ue_unit = alloc_unr(ueunit);
185	usb2_callout_init_mtx(&ue->ue_watchdog, ue->ue_mtx, 0);
186	sysctl_ctx_init(&ue->ue_sysctl_ctx);
187
188	ifp = if_alloc(IFT_ETHER);
189	if (ifp == NULL) {
190		device_printf(ue->ue_dev, "could not allocate ifnet\n");
191		goto error;
192	}
193
194	ifp->if_softc = ue;
195	if_initname(ifp, "ue", ue->ue_unit);
196	ifp->if_mtu = ETHERMTU;
197	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
198	if (ue->ue_methods->ue_ioctl != NULL)
199		ifp->if_ioctl = ue->ue_methods->ue_ioctl;
200	else
201		ifp->if_ioctl = usb2_ether_ioctl;
202	ifp->if_start = ue_start;
203	ifp->if_init = ue_init;
204	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
205	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
206	IFQ_SET_READY(&ifp->if_snd);
207	ue->ue_ifp = ifp;
208
209	if (ue->ue_methods->ue_mii_upd != NULL &&
210	    ue->ue_methods->ue_mii_sts != NULL) {
211		mtx_lock(&Giant);	/* device_xxx() depends on this */
212		error = mii_phy_probe(ue->ue_dev, &ue->ue_miibus,
213		    ue_ifmedia_upd, ue->ue_methods->ue_mii_sts);
214		mtx_unlock(&Giant);
215		if (error) {
216			device_printf(ue->ue_dev, "MII without any PHY\n");
217			goto error;
218		}
219	}
220
221	if_printf(ifp, "<USB Ethernet> on %s\n", device_get_nameunit(ue->ue_dev));
222	ether_ifattach(ifp, ue->ue_eaddr);
223
224	snprintf(num, sizeof(num), "%u", ue->ue_unit);
225	ue->ue_sysctl_oid = SYSCTL_ADD_NODE(&ue->ue_sysctl_ctx,
226	    &SYSCTL_NODE_CHILDREN(_net, ue),
227	    OID_AUTO, num, CTLFLAG_RD, NULL, "");
228	SYSCTL_ADD_PROC(&ue->ue_sysctl_ctx,
229	    SYSCTL_CHILDREN(ue->ue_sysctl_oid), OID_AUTO,
230	    "%parent", CTLFLAG_RD, ue, 0,
231	    ue_sysctl_parent, "A", "parent device");
232
233	UE_LOCK(ue);
234	return;
235
236error:
237	free_unr(ueunit, ue->ue_unit);
238	if (ue->ue_ifp != NULL) {
239		if_free(ue->ue_ifp);
240		ue->ue_ifp = NULL;
241	}
242	UE_LOCK(ue);
243	return;
244}
245
246void
247usb2_ether_ifdetach(struct usb_ether *ue)
248{
249	struct ifnet *ifp;
250
251	/* wait for any post attach or other command to complete */
252	usb2_proc_drain(&ue->ue_tq);
253
254	/* read "ifnet" pointer after taskqueue drain */
255	ifp = ue->ue_ifp;
256
257	if (ifp != NULL) {
258
259		/* we are not running any more */
260		UE_LOCK(ue);
261		ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
262		UE_UNLOCK(ue);
263
264		/* drain any callouts */
265		usb2_callout_drain(&ue->ue_watchdog);
266
267		/* detach miibus */
268		if (ue->ue_miibus != NULL) {
269			mtx_lock(&Giant);	/* device_xxx() depends on this */
270			device_delete_child(ue->ue_dev, ue->ue_miibus);
271			mtx_unlock(&Giant);
272		}
273
274		/* detach ethernet */
275		ether_ifdetach(ifp);
276
277		/* free interface instance */
278		if_free(ifp);
279
280		/* free sysctl */
281		sysctl_ctx_free(&ue->ue_sysctl_ctx);
282
283		/* free unit */
284		free_unr(ueunit, ue->ue_unit);
285	}
286
287	/* free taskqueue, if any */
288	usb2_proc_free(&ue->ue_tq);
289}
290
291uint8_t
292usb2_ether_is_gone(struct usb_ether *ue)
293{
294	return (usb2_proc_is_gone(&ue->ue_tq));
295}
296
297static void
298ue_init(void *arg)
299{
300	struct usb_ether *ue = arg;
301
302	UE_LOCK(ue);
303	ue_queue_command(ue, ue_start_task,
304	    &ue->ue_sync_task[0].hdr,
305	    &ue->ue_sync_task[1].hdr);
306	UE_UNLOCK(ue);
307}
308
309static void
310ue_start_task(struct usb_proc_msg *_task)
311{
312	struct usb_ether_cfg_task *task =
313	    (struct usb_ether_cfg_task *)_task;
314	struct usb_ether *ue = task->ue;
315	struct ifnet *ifp = ue->ue_ifp;
316
317	UE_LOCK_ASSERT(ue, MA_OWNED);
318
319	ue->ue_methods->ue_init(ue);
320
321	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
322		return;
323
324	if (ue->ue_methods->ue_tick != NULL)
325		usb2_callout_reset(&ue->ue_watchdog, hz, ue_watchdog, ue);
326}
327
328static void
329ue_stop_task(struct usb_proc_msg *_task)
330{
331	struct usb_ether_cfg_task *task =
332	    (struct usb_ether_cfg_task *)_task;
333	struct usb_ether *ue = task->ue;
334
335	UE_LOCK_ASSERT(ue, MA_OWNED);
336
337	usb2_callout_stop(&ue->ue_watchdog);
338
339	ue->ue_methods->ue_stop(ue);
340}
341
342static void
343ue_start(struct ifnet *ifp)
344{
345	struct usb_ether *ue = ifp->if_softc;
346
347	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
348		return;
349
350	UE_LOCK(ue);
351	ue->ue_methods->ue_start(ue);
352	UE_UNLOCK(ue);
353}
354
355static void
356ue_promisc_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
362	ue->ue_methods->ue_setpromisc(ue);
363}
364
365static void
366ue_setmulti_task(struct usb_proc_msg *_task)
367{
368	struct usb_ether_cfg_task *task =
369	    (struct usb_ether_cfg_task *)_task;
370	struct usb_ether *ue = task->ue;
371
372	ue->ue_methods->ue_setmulti(ue);
373}
374
375static int
376ue_ifmedia_upd(struct ifnet *ifp)
377{
378	struct usb_ether *ue = ifp->if_softc;
379
380	/* Defer to process context */
381	UE_LOCK(ue);
382	ue_queue_command(ue, ue_ifmedia_task,
383	    &ue->ue_media_task[0].hdr,
384	    &ue->ue_media_task[1].hdr);
385	UE_UNLOCK(ue);
386
387	return (0);
388}
389
390static void
391ue_ifmedia_task(struct usb_proc_msg *_task)
392{
393	struct usb_ether_cfg_task *task =
394	    (struct usb_ether_cfg_task *)_task;
395	struct usb_ether *ue = task->ue;
396	struct ifnet *ifp = ue->ue_ifp;
397
398	ue->ue_methods->ue_mii_upd(ifp);
399}
400
401static void
402ue_watchdog(void *arg)
403{
404	struct usb_ether *ue = arg;
405	struct ifnet *ifp = ue->ue_ifp;
406
407	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
408		return;
409
410	ue_queue_command(ue, ue_tick_task,
411	    &ue->ue_tick_task[0].hdr,
412	    &ue->ue_tick_task[1].hdr);
413
414	usb2_callout_reset(&ue->ue_watchdog, hz, ue_watchdog, ue);
415}
416
417static void
418ue_tick_task(struct usb_proc_msg *_task)
419{
420	struct usb_ether_cfg_task *task =
421	    (struct usb_ether_cfg_task *)_task;
422	struct usb_ether *ue = task->ue;
423	struct ifnet *ifp = ue->ue_ifp;
424
425	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
426		return;
427
428	ue->ue_methods->ue_tick(ue);
429}
430
431int
432usb2_ether_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
433{
434	struct usb_ether *ue = ifp->if_softc;
435	struct ifreq *ifr = (struct ifreq *)data;
436	struct mii_data *mii;
437	int error = 0;
438
439	switch (command) {
440	case SIOCSIFFLAGS:
441		UE_LOCK(ue);
442		if (ifp->if_flags & IFF_UP) {
443			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
444				ue_queue_command(ue, ue_promisc_task,
445				    &ue->ue_promisc_task[0].hdr,
446				    &ue->ue_promisc_task[1].hdr);
447			else
448				ue_queue_command(ue, ue_start_task,
449				    &ue->ue_sync_task[0].hdr,
450				    &ue->ue_sync_task[1].hdr);
451		} else {
452			ue_queue_command(ue, ue_stop_task,
453			    &ue->ue_sync_task[0].hdr,
454			    &ue->ue_sync_task[1].hdr);
455		}
456		UE_UNLOCK(ue);
457		break;
458	case SIOCADDMULTI:
459	case SIOCDELMULTI:
460		UE_LOCK(ue);
461		ue_queue_command(ue, ue_setmulti_task,
462		    &ue->ue_multi_task[0].hdr,
463		    &ue->ue_multi_task[1].hdr);
464		UE_UNLOCK(ue);
465		break;
466	case SIOCGIFMEDIA:
467	case SIOCSIFMEDIA:
468		if (ue->ue_miibus != NULL) {
469			mii = device_get_softc(ue->ue_miibus);
470			error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
471		} else
472			error = ether_ioctl(ifp, command, data);
473		break;
474	default:
475		error = ether_ioctl(ifp, command, data);
476		break;
477	}
478	return (error);
479}
480
481static int
482usb2_ether_modevent(module_t mod, int type, void *data)
483{
484
485	switch (type) {
486	case MOD_LOAD:
487		ueunit = new_unrhdr(0, INT_MAX, NULL);
488		break;
489	case MOD_UNLOAD:
490		break;
491	default:
492		return (EOPNOTSUPP);
493	}
494	return (0);
495}
496static moduledata_t usb2_ether_mod = {
497	"uether",
498	usb2_ether_modevent,
499	0
500};
501
502struct mbuf *
503usb2_ether_newbuf(void)
504{
505	struct mbuf *m_new;
506
507	m_new = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
508	if (m_new == NULL)
509		return (NULL);
510	m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
511
512	m_adj(m_new, ETHER_ALIGN);
513	return (m_new);
514}
515
516int
517usb2_ether_rxmbuf(struct usb_ether *ue, struct mbuf *m,
518    unsigned int len)
519{
520	struct ifnet *ifp = ue->ue_ifp;
521
522	UE_LOCK_ASSERT(ue, MA_OWNED);
523
524	/* finalize mbuf */
525	ifp->if_ipackets++;
526	m->m_pkthdr.rcvif = ifp;
527	m->m_pkthdr.len = m->m_len = len;
528
529	/* enqueue for later when the lock can be released */
530	_IF_ENQUEUE(&ue->ue_rxq, m);
531	return (0);
532}
533
534int
535usb2_ether_rxbuf(struct usb_ether *ue, struct usb_page_cache *pc,
536    unsigned int offset, unsigned int len)
537{
538	struct ifnet *ifp = ue->ue_ifp;
539	struct mbuf *m;
540
541	UE_LOCK_ASSERT(ue, MA_OWNED);
542
543	if (len < ETHER_HDR_LEN || len > MCLBYTES - ETHER_ALIGN)
544		return (1);
545
546	m = usb2_ether_newbuf();
547	if (m == NULL) {
548		ifp->if_ierrors++;
549		return (ENOMEM);
550	}
551
552	usb2_copy_out(pc, offset, mtod(m, uint8_t *), len);
553
554	/* finalize mbuf */
555	ifp->if_ipackets++;
556	m->m_pkthdr.rcvif = ifp;
557	m->m_pkthdr.len = m->m_len = len;
558
559	/* enqueue for later when the lock can be released */
560	_IF_ENQUEUE(&ue->ue_rxq, m);
561	return (0);
562}
563
564void
565usb2_ether_rxflush(struct usb_ether *ue)
566{
567	struct ifnet *ifp = ue->ue_ifp;
568	struct mbuf *m;
569
570	UE_LOCK_ASSERT(ue, MA_OWNED);
571
572	for (;;) {
573		_IF_DEQUEUE(&ue->ue_rxq, m);
574		if (m == NULL)
575			break;
576
577		/*
578		 * The USB xfer has been resubmitted so its safe to unlock now.
579		 */
580		UE_UNLOCK(ue);
581		ifp->if_input(ifp, m);
582		UE_LOCK(ue);
583	}
584}
585
586DECLARE_MODULE(uether, usb2_ether_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
587MODULE_VERSION(uether, 1);
588