1/*-
2 * Copyright (c) 2010-2011 Solarflare Communications, Inc.
3 * All rights reserved.
4 *
5 * This software was developed in part by Philip Paeps under contract for
6 * Solarflare Communications, Inc.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD$");
32
33#include <sys/param.h>
34#include <sys/kernel.h>
35#include <sys/bus.h>
36#include <sys/rman.h>
37#include <sys/lock.h>
38#include <sys/module.h>
39#include <sys/mutex.h>
40#include <sys/smp.h>
41#include <sys/socket.h>
42#include <sys/taskqueue.h>
43#include <sys/sockio.h>
44#include <sys/sysctl.h>
45
46#include <dev/pci/pcireg.h>
47#include <dev/pci/pcivar.h>
48
49#include <net/ethernet.h>
50#include <net/if.h>
51#include <net/if_media.h>
52#include <net/if_types.h>
53
54#include "common/efx.h"
55
56#include "sfxge.h"
57#include "sfxge_rx.h"
58
59#define SFXGE_CAP (IFCAP_VLAN_MTU | \
60		   IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM | IFCAP_TSO |	\
61		   IFCAP_JUMBO_MTU | IFCAP_LRO |			\
62		   IFCAP_VLAN_HWTSO | IFCAP_LINKSTATE)
63#define SFXGE_CAP_ENABLE SFXGE_CAP
64#define SFXGE_CAP_FIXED (IFCAP_VLAN_MTU | IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM | \
65			 IFCAP_JUMBO_MTU | IFCAP_LINKSTATE)
66
67MALLOC_DEFINE(M_SFXGE, "sfxge", "Solarflare 10GigE driver");
68
69static void
70sfxge_reset(void *arg, int npending);
71
72static int
73sfxge_start(struct sfxge_softc *sc)
74{
75	int rc;
76
77	sx_assert(&sc->softc_lock, LA_XLOCKED);
78
79	if (sc->init_state == SFXGE_STARTED)
80		return 0;
81
82	if (sc->init_state != SFXGE_REGISTERED) {
83		rc = EINVAL;
84		goto fail;
85	}
86
87	if ((rc = efx_nic_init(sc->enp)) != 0)
88		goto fail;
89
90	/* Start processing interrupts. */
91	if ((rc = sfxge_intr_start(sc)) != 0)
92		goto fail2;
93
94	/* Start processing events. */
95	if ((rc = sfxge_ev_start(sc)) != 0)
96		goto fail3;
97
98	/* Start the receiver side. */
99	if ((rc = sfxge_rx_start(sc)) != 0)
100		goto fail4;
101
102	/* Start the transmitter side. */
103	if ((rc = sfxge_tx_start(sc)) != 0)
104		goto fail5;
105
106	/* Fire up the port. */
107	if ((rc = sfxge_port_start(sc)) != 0)
108		goto fail6;
109
110	sc->init_state = SFXGE_STARTED;
111
112	/* Tell the stack we're running. */
113	sc->ifnet->if_drv_flags |= IFF_DRV_RUNNING;
114	sc->ifnet->if_drv_flags &= ~IFF_DRV_OACTIVE;
115
116	return (0);
117
118fail6:
119	sfxge_tx_stop(sc);
120
121fail5:
122	sfxge_rx_stop(sc);
123
124fail4:
125	sfxge_ev_stop(sc);
126
127fail3:
128	sfxge_intr_stop(sc);
129
130fail2:
131	efx_nic_fini(sc->enp);
132
133fail:
134	device_printf(sc->dev, "sfxge_start: %d\n", rc);
135
136	return (rc);
137}
138
139static void
140sfxge_if_init(void *arg)
141{
142	struct sfxge_softc *sc;
143
144	sc = (struct sfxge_softc *)arg;
145
146	sx_xlock(&sc->softc_lock);
147	(void)sfxge_start(sc);
148	sx_xunlock(&sc->softc_lock);
149}
150
151static void
152sfxge_stop(struct sfxge_softc *sc)
153{
154	sx_assert(&sc->softc_lock, LA_XLOCKED);
155
156	if (sc->init_state != SFXGE_STARTED)
157		return;
158
159	sc->init_state = SFXGE_REGISTERED;
160
161	/* Stop the port. */
162	sfxge_port_stop(sc);
163
164	/* Stop the transmitter. */
165	sfxge_tx_stop(sc);
166
167	/* Stop the receiver. */
168	sfxge_rx_stop(sc);
169
170	/* Stop processing events. */
171	sfxge_ev_stop(sc);
172
173	/* Stop processing interrupts. */
174	sfxge_intr_stop(sc);
175
176	efx_nic_fini(sc->enp);
177
178	sc->ifnet->if_drv_flags &= ~IFF_DRV_RUNNING;
179}
180
181static int
182sfxge_if_ioctl(struct ifnet *ifp, unsigned long command, caddr_t data)
183{
184	struct sfxge_softc *sc;
185	struct ifreq *ifr;
186	int error;
187
188	ifr = (struct ifreq *)data;
189	sc = ifp->if_softc;
190	error = 0;
191
192	switch (command) {
193	case SIOCSIFFLAGS:
194		sx_xlock(&sc->softc_lock);
195		if (ifp->if_flags & IFF_UP) {
196			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
197				if ((ifp->if_flags ^ sc->if_flags) &
198				    (IFF_PROMISC | IFF_ALLMULTI)) {
199					sfxge_mac_filter_set(sc);
200				}
201			} else
202				sfxge_start(sc);
203		} else
204			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
205				sfxge_stop(sc);
206		sc->if_flags = ifp->if_flags;
207		sx_xunlock(&sc->softc_lock);
208		break;
209	case SIOCSIFMTU:
210		if (ifr->ifr_mtu == ifp->if_mtu) {
211			/* Nothing to do */
212			error = 0;
213		} else if (ifr->ifr_mtu > SFXGE_MAX_MTU) {
214			error = EINVAL;
215		} else if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
216			ifp->if_mtu = ifr->ifr_mtu;
217			error = 0;
218		} else {
219			/* Restart required */
220			sx_xlock(&sc->softc_lock);
221			sfxge_stop(sc);
222			ifp->if_mtu = ifr->ifr_mtu;
223			error = sfxge_start(sc);
224			sx_xunlock(&sc->softc_lock);
225			if (error) {
226				ifp->if_flags &= ~IFF_UP;
227				ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
228				if_down(ifp);
229			}
230		}
231		break;
232	case SIOCADDMULTI:
233	case SIOCDELMULTI:
234		if (ifp->if_drv_flags & IFF_DRV_RUNNING)
235			sfxge_mac_filter_set(sc);
236		break;
237	case SIOCSIFCAP:
238		sx_xlock(&sc->softc_lock);
239
240		/*
241		 * The networking core already rejects attempts to
242		 * enable capabilities we don't have.  We still have
243		 * to reject attempts to disable capabilities that we
244		 * can't (yet) disable.
245		 */
246		if (~ifr->ifr_reqcap & SFXGE_CAP_FIXED) {
247			error = EINVAL;
248			sx_xunlock(&sc->softc_lock);
249			break;
250		}
251
252		ifp->if_capenable = ifr->ifr_reqcap;
253		if (ifp->if_capenable & IFCAP_TXCSUM)
254			ifp->if_hwassist |= (CSUM_IP | CSUM_TCP | CSUM_UDP);
255		else
256			ifp->if_hwassist &= ~(CSUM_IP | CSUM_TCP | CSUM_UDP);
257		if (ifp->if_capenable & IFCAP_TSO)
258			ifp->if_hwassist |= CSUM_TSO;
259		else
260			ifp->if_hwassist &= ~CSUM_TSO;
261
262		sx_xunlock(&sc->softc_lock);
263		break;
264	case SIOCSIFMEDIA:
265	case SIOCGIFMEDIA:
266		error = ifmedia_ioctl(ifp, ifr, &sc->media, command);
267		break;
268	default:
269		error = ether_ioctl(ifp, command, data);
270	}
271
272	return (error);
273}
274
275static void
276sfxge_ifnet_fini(struct ifnet *ifp)
277{
278	struct sfxge_softc *sc = ifp->if_softc;
279
280	sx_xlock(&sc->softc_lock);
281	sfxge_stop(sc);
282	sx_xunlock(&sc->softc_lock);
283
284	ifmedia_removeall(&sc->media);
285	ether_ifdetach(ifp);
286	if_free(ifp);
287}
288
289static int
290sfxge_ifnet_init(struct ifnet *ifp, struct sfxge_softc *sc)
291{
292	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sc->enp);
293	device_t dev;
294	int rc;
295
296	dev = sc->dev;
297	sc->ifnet = ifp;
298
299	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
300	ifp->if_init = sfxge_if_init;
301	ifp->if_softc = sc;
302	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
303	ifp->if_ioctl = sfxge_if_ioctl;
304
305	ifp->if_capabilities = SFXGE_CAP;
306	ifp->if_capenable = SFXGE_CAP_ENABLE;
307	ifp->if_hwassist = CSUM_TCP | CSUM_UDP | CSUM_IP | CSUM_TSO;
308
309	ether_ifattach(ifp, encp->enc_mac_addr);
310
311#ifdef SFXGE_HAVE_MQ
312	ifp->if_transmit = sfxge_if_transmit;
313	ifp->if_qflush = sfxge_if_qflush;
314#else
315	ifp->if_start = sfxge_if_start;
316	IFQ_SET_MAXLEN(&ifp->if_snd, SFXGE_NDESCS - 1);
317	ifp->if_snd.ifq_drv_maxlen = SFXGE_NDESCS - 1;
318	IFQ_SET_READY(&ifp->if_snd);
319
320	mtx_init(&sc->tx_lock, "txq", NULL, MTX_DEF);
321#endif
322
323	if ((rc = sfxge_port_ifmedia_init(sc)) != 0)
324		goto fail;
325
326	return 0;
327
328fail:
329	ether_ifdetach(sc->ifnet);
330	return rc;
331}
332
333void
334sfxge_sram_buf_tbl_alloc(struct sfxge_softc *sc, size_t n, uint32_t *idp)
335{
336	KASSERT(sc->buffer_table_next + n <=
337		efx_nic_cfg_get(sc->enp)->enc_buftbl_limit,
338		("buffer table full"));
339
340	*idp = sc->buffer_table_next;
341	sc->buffer_table_next += n;
342}
343
344static int
345sfxge_bar_init(struct sfxge_softc *sc)
346{
347	efsys_bar_t *esbp = &sc->bar;
348
349	esbp->esb_rid = PCIR_BAR(EFX_MEM_BAR);
350	if ((esbp->esb_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY,
351	    &esbp->esb_rid, RF_ACTIVE)) == NULL) {
352		device_printf(sc->dev, "Cannot allocate BAR region %d\n",
353		    EFX_MEM_BAR);
354		return (ENXIO);
355	}
356	esbp->esb_tag = rman_get_bustag(esbp->esb_res);
357	esbp->esb_handle = rman_get_bushandle(esbp->esb_res);
358	mtx_init(&esbp->esb_lock, "sfxge_efsys_bar", NULL, MTX_DEF);
359
360	return (0);
361}
362
363static void
364sfxge_bar_fini(struct sfxge_softc *sc)
365{
366	efsys_bar_t *esbp = &sc->bar;
367
368	bus_release_resource(sc->dev, SYS_RES_MEMORY, esbp->esb_rid,
369	    esbp->esb_res);
370	mtx_destroy(&esbp->esb_lock);
371}
372
373static int
374sfxge_create(struct sfxge_softc *sc)
375{
376	device_t dev;
377	efx_nic_t *enp;
378	int error;
379
380	dev = sc->dev;
381
382	sx_init(&sc->softc_lock, "sfxge_softc");
383
384	sc->stats_node = SYSCTL_ADD_NODE(
385		device_get_sysctl_ctx(dev),
386		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
387		OID_AUTO, "stats", CTLFLAG_RD, NULL, "Statistics");
388	if (!sc->stats_node) {
389		error = ENOMEM;
390		goto fail;
391	}
392
393	TASK_INIT(&sc->task_reset, 0, sfxge_reset, sc);
394
395	(void) pci_enable_busmaster(dev);
396
397	/* Initialize DMA mappings. */
398	if ((error = sfxge_dma_init(sc)) != 0)
399		goto fail;
400
401	/* Map the device registers. */
402	if ((error = sfxge_bar_init(sc)) != 0)
403		goto fail;
404
405	error = efx_family(pci_get_vendor(dev), pci_get_device(dev),
406	    &sc->family);
407	KASSERT(error == 0, ("Family should be filtered by sfxge_probe()"));
408
409	/* Create the common code nic object. */
410	mtx_init(&sc->enp_lock, "sfxge_nic", NULL, MTX_DEF);
411	if ((error = efx_nic_create(sc->family, (efsys_identifier_t *)sc,
412	    &sc->bar, &sc->enp_lock, &enp)) != 0)
413		goto fail3;
414	sc->enp = enp;
415
416	/* Initialize MCDI to talk to the microcontroller. */
417	if ((error = sfxge_mcdi_init(sc)) != 0)
418		goto fail4;
419
420	/* Probe the NIC and build the configuration data area. */
421	if ((error = efx_nic_probe(enp)) != 0)
422		goto fail5;
423
424	/* Initialize the NVRAM. */
425	if ((error = efx_nvram_init(enp)) != 0)
426		goto fail6;
427
428	/* Initialize the VPD. */
429	if ((error = efx_vpd_init(enp)) != 0)
430		goto fail7;
431
432	/* Reset the NIC. */
433	if ((error = efx_nic_reset(enp)) != 0)
434		goto fail8;
435
436	/* Initialize buffer table allocation. */
437	sc->buffer_table_next = 0;
438
439	/* Set up interrupts. */
440	if ((error = sfxge_intr_init(sc)) != 0)
441		goto fail8;
442
443	/* Initialize event processing state. */
444	if ((error = sfxge_ev_init(sc)) != 0)
445		goto fail11;
446
447	/* Initialize receive state. */
448	if ((error = sfxge_rx_init(sc)) != 0)
449		goto fail12;
450
451	/* Initialize transmit state. */
452	if ((error = sfxge_tx_init(sc)) != 0)
453		goto fail13;
454
455	/* Initialize port state. */
456	if ((error = sfxge_port_init(sc)) != 0)
457		goto fail14;
458
459	sc->init_state = SFXGE_INITIALIZED;
460
461	return (0);
462
463fail14:
464	sfxge_tx_fini(sc);
465
466fail13:
467	sfxge_rx_fini(sc);
468
469fail12:
470	sfxge_ev_fini(sc);
471
472fail11:
473	sfxge_intr_fini(sc);
474
475fail8:
476	efx_vpd_fini(enp);
477
478fail7:
479	efx_nvram_fini(enp);
480
481fail6:
482	efx_nic_unprobe(enp);
483
484fail5:
485	sfxge_mcdi_fini(sc);
486
487fail4:
488	sc->enp = NULL;
489	efx_nic_destroy(enp);
490	mtx_destroy(&sc->enp_lock);
491
492fail3:
493	sfxge_bar_fini(sc);
494	(void) pci_disable_busmaster(sc->dev);
495
496fail:
497	sc->dev = NULL;
498	sx_destroy(&sc->softc_lock);
499	return (error);
500}
501
502static void
503sfxge_destroy(struct sfxge_softc *sc)
504{
505	efx_nic_t *enp;
506
507	/* Clean up port state. */
508	sfxge_port_fini(sc);
509
510	/* Clean up transmit state. */
511	sfxge_tx_fini(sc);
512
513	/* Clean up receive state. */
514	sfxge_rx_fini(sc);
515
516	/* Clean up event processing state. */
517	sfxge_ev_fini(sc);
518
519	/* Clean up interrupts. */
520	sfxge_intr_fini(sc);
521
522	/* Tear down common code subsystems. */
523	efx_nic_reset(sc->enp);
524	efx_vpd_fini(sc->enp);
525	efx_nvram_fini(sc->enp);
526	efx_nic_unprobe(sc->enp);
527
528	/* Tear down MCDI. */
529	sfxge_mcdi_fini(sc);
530
531	/* Destroy common code context. */
532	enp = sc->enp;
533	sc->enp = NULL;
534	efx_nic_destroy(enp);
535
536	/* Free DMA memory. */
537	sfxge_dma_fini(sc);
538
539	/* Free mapped BARs. */
540	sfxge_bar_fini(sc);
541
542	(void) pci_disable_busmaster(sc->dev);
543
544	taskqueue_drain(taskqueue_thread, &sc->task_reset);
545
546	/* Destroy the softc lock. */
547	sx_destroy(&sc->softc_lock);
548}
549
550static int
551sfxge_vpd_handler(SYSCTL_HANDLER_ARGS)
552{
553	struct sfxge_softc *sc = arg1;
554	efx_vpd_value_t value;
555	int rc;
556
557	value.evv_tag = arg2 >> 16;
558	value.evv_keyword = arg2 & 0xffff;
559	if ((rc = efx_vpd_get(sc->enp, sc->vpd_data, sc->vpd_size, &value))
560	    != 0)
561		return rc;
562
563	return SYSCTL_OUT(req, value.evv_value, value.evv_length);
564}
565
566static void
567sfxge_vpd_try_add(struct sfxge_softc *sc, struct sysctl_oid_list *list,
568		  efx_vpd_tag_t tag, const char *keyword)
569{
570	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev);
571	efx_vpd_value_t value;
572
573	/* Check whether VPD tag/keyword is present */
574	value.evv_tag = tag;
575	value.evv_keyword = EFX_VPD_KEYWORD(keyword[0], keyword[1]);
576	if (efx_vpd_get(sc->enp, sc->vpd_data, sc->vpd_size, &value) != 0)
577		return;
578
579	SYSCTL_ADD_PROC(
580		ctx, list, OID_AUTO, keyword, CTLTYPE_STRING|CTLFLAG_RD,
581		sc, tag << 16 | EFX_VPD_KEYWORD(keyword[0], keyword[1]),
582		sfxge_vpd_handler, "A", "");
583}
584
585static int
586sfxge_vpd_init(struct sfxge_softc *sc)
587{
588	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev);
589	struct sysctl_oid *vpd_node;
590	struct sysctl_oid_list *vpd_list;
591	char keyword[3];
592	efx_vpd_value_t value;
593	int rc;
594
595	if ((rc = efx_vpd_size(sc->enp, &sc->vpd_size)) != 0)
596		goto fail;
597	sc->vpd_data = malloc(sc->vpd_size, M_SFXGE, M_WAITOK);
598	if ((rc = efx_vpd_read(sc->enp, sc->vpd_data, sc->vpd_size)) != 0)
599		goto fail2;
600
601	/* Copy ID (product name) into device description, and log it. */
602	value.evv_tag = EFX_VPD_ID;
603	if (efx_vpd_get(sc->enp, sc->vpd_data, sc->vpd_size, &value) == 0) {
604		value.evv_value[value.evv_length] = 0;
605		device_set_desc_copy(sc->dev, value.evv_value);
606		device_printf(sc->dev, "%s\n", value.evv_value);
607	}
608
609	vpd_node = SYSCTL_ADD_NODE(
610		ctx, SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)),
611		OID_AUTO, "vpd", CTLFLAG_RD, NULL, "Vital Product Data");
612	vpd_list = SYSCTL_CHILDREN(vpd_node);
613
614	/* Add sysctls for all expected and any vendor-defined keywords. */
615	sfxge_vpd_try_add(sc, vpd_list, EFX_VPD_RO, "PN");
616	sfxge_vpd_try_add(sc, vpd_list, EFX_VPD_RO, "EC");
617	sfxge_vpd_try_add(sc, vpd_list, EFX_VPD_RO, "SN");
618	keyword[0] = 'V';
619	keyword[2] = 0;
620	for (keyword[1] = '0'; keyword[1] <= '9'; keyword[1]++)
621		sfxge_vpd_try_add(sc, vpd_list, EFX_VPD_RO, keyword);
622	for (keyword[1] = 'A'; keyword[1] <= 'Z'; keyword[1]++)
623		sfxge_vpd_try_add(sc, vpd_list, EFX_VPD_RO, keyword);
624
625	return 0;
626
627fail2:
628	free(sc->vpd_data, M_SFXGE);
629fail:
630	return rc;
631}
632
633static void
634sfxge_vpd_fini(struct sfxge_softc *sc)
635{
636	free(sc->vpd_data, M_SFXGE);
637}
638
639static void
640sfxge_reset(void *arg, int npending)
641{
642	struct sfxge_softc *sc;
643	int rc;
644
645	(void)npending;
646
647	sc = (struct sfxge_softc *)arg;
648
649	sx_xlock(&sc->softc_lock);
650
651	if (sc->init_state != SFXGE_STARTED)
652		goto done;
653
654	sfxge_stop(sc);
655	efx_nic_reset(sc->enp);
656	if ((rc = sfxge_start(sc)) != 0)
657		device_printf(sc->dev,
658			      "reset failed (%d); interface is now stopped\n",
659			      rc);
660
661done:
662	sx_xunlock(&sc->softc_lock);
663}
664
665void
666sfxge_schedule_reset(struct sfxge_softc *sc)
667{
668	taskqueue_enqueue(taskqueue_thread, &sc->task_reset);
669}
670
671static int
672sfxge_attach(device_t dev)
673{
674	struct sfxge_softc *sc;
675	struct ifnet *ifp;
676	int error;
677
678	sc = device_get_softc(dev);
679	sc->dev = dev;
680
681	/* Allocate ifnet. */
682	ifp = if_alloc(IFT_ETHER);
683	if (ifp == NULL) {
684		device_printf(dev, "Couldn't allocate ifnet\n");
685		error = ENOMEM;
686		goto fail;
687	}
688	sc->ifnet = ifp;
689
690	/* Initialize hardware. */
691	if ((error = sfxge_create(sc)) != 0)
692		goto fail2;
693
694	/* Create the ifnet for the port. */
695	if ((error = sfxge_ifnet_init(ifp, sc)) != 0)
696		goto fail3;
697
698	if ((error = sfxge_vpd_init(sc)) != 0)
699		goto fail4;
700
701	sc->init_state = SFXGE_REGISTERED;
702
703	return (0);
704
705fail4:
706	sfxge_ifnet_fini(ifp);
707fail3:
708	sfxge_destroy(sc);
709
710fail2:
711	if_free(sc->ifnet);
712
713fail:
714	return (error);
715}
716
717static int
718sfxge_detach(device_t dev)
719{
720	struct sfxge_softc *sc;
721
722	sc = device_get_softc(dev);
723
724	sfxge_vpd_fini(sc);
725
726	/* Destroy the ifnet. */
727	sfxge_ifnet_fini(sc->ifnet);
728
729	/* Tear down hardware. */
730	sfxge_destroy(sc);
731
732	return (0);
733}
734
735static int
736sfxge_probe(device_t dev)
737{
738	uint16_t pci_vendor_id;
739	uint16_t pci_device_id;
740	efx_family_t family;
741	int rc;
742
743	pci_vendor_id = pci_get_vendor(dev);
744	pci_device_id = pci_get_device(dev);
745
746	rc = efx_family(pci_vendor_id, pci_device_id, &family);
747	if (rc)
748		return ENXIO;
749
750	KASSERT(family == EFX_FAMILY_SIENA, ("impossible controller family"));
751	device_set_desc(dev, "Solarflare SFC9000 family");
752	return 0;
753}
754
755static device_method_t sfxge_methods[] = {
756	DEVMETHOD(device_probe,		sfxge_probe),
757	DEVMETHOD(device_attach,	sfxge_attach),
758	DEVMETHOD(device_detach,	sfxge_detach),
759
760	DEVMETHOD_END
761};
762
763static devclass_t sfxge_devclass;
764
765static driver_t sfxge_driver = {
766	"sfxge",
767	sfxge_methods,
768	sizeof(struct sfxge_softc)
769};
770
771DRIVER_MODULE(sfxge, pci, sfxge_driver, sfxge_devclass, 0, 0);
772