| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: dwc_gmac.c,v 1.40 2017/02/20 07:43:29 ozaki-r Exp $ */ | | 1 | /* $NetBSD: dwc_gmac.c,v 1.41 2017/10/23 09:27:46 msaitoh Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2013, 2014 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2013, 2014 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Matt Thomas of 3am Software Foundry and Martin Husemann. | | 8 | * by Matt Thomas of 3am Software Foundry and Martin Husemann. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -31,27 +31,27 @@ | | | @@ -31,27 +31,27 @@ |
31 | | | 31 | |
32 | /* | | 32 | /* |
33 | * This driver supports the Synopsis Designware GMAC core, as found | | 33 | * This driver supports the Synopsis Designware GMAC core, as found |
34 | * on Allwinner A20 cores and others. | | 34 | * on Allwinner A20 cores and others. |
35 | * | | 35 | * |
36 | * Real documentation seems to not be available, the marketing product | | 36 | * Real documentation seems to not be available, the marketing product |
37 | * documents could be found here: | | 37 | * documents could be found here: |
38 | * | | 38 | * |
39 | * http://www.synopsys.com/dw/ipdir.php?ds=dwc_ether_mac10_100_1000_unive | | 39 | * http://www.synopsys.com/dw/ipdir.php?ds=dwc_ether_mac10_100_1000_unive |
40 | */ | | 40 | */ |
41 | | | 41 | |
42 | #include <sys/cdefs.h> | | 42 | #include <sys/cdefs.h> |
43 | | | 43 | |
44 | __KERNEL_RCSID(1, "$NetBSD: dwc_gmac.c,v 1.40 2017/02/20 07:43:29 ozaki-r Exp $"); | | 44 | __KERNEL_RCSID(1, "$NetBSD: dwc_gmac.c,v 1.41 2017/10/23 09:27:46 msaitoh Exp $"); |
45 | | | 45 | |
46 | /* #define DWC_GMAC_DEBUG 1 */ | | 46 | /* #define DWC_GMAC_DEBUG 1 */ |
47 | | | 47 | |
48 | #ifdef _KERNEL_OPT | | 48 | #ifdef _KERNEL_OPT |
49 | #include "opt_inet.h" | | 49 | #include "opt_inet.h" |
50 | #include "opt_net_mpsafe.h" | | 50 | #include "opt_net_mpsafe.h" |
51 | #endif | | 51 | #endif |
52 | | | 52 | |
53 | #include <sys/param.h> | | 53 | #include <sys/param.h> |
54 | #include <sys/bus.h> | | 54 | #include <sys/bus.h> |
55 | #include <sys/device.h> | | 55 | #include <sys/device.h> |
56 | #include <sys/intr.h> | | 56 | #include <sys/intr.h> |
57 | #include <sys/systm.h> | | 57 | #include <sys/systm.h> |
| @@ -136,26 +136,27 @@ static void dwc_gmac_dump_ffilt(struct d | | | @@ -136,26 +136,27 @@ static void dwc_gmac_dump_ffilt(struct d |
136 | | | 136 | |
137 | #ifdef NET_MPSAFE | | 137 | #ifdef NET_MPSAFE |
138 | #define DWCGMAC_MPSAFE 1 | | 138 | #define DWCGMAC_MPSAFE 1 |
139 | #endif | | 139 | #endif |
140 | | | 140 | |
141 | void | | 141 | void |
142 | dwc_gmac_attach(struct dwc_gmac_softc *sc, uint32_t mii_clk) | | 142 | dwc_gmac_attach(struct dwc_gmac_softc *sc, uint32_t mii_clk) |
143 | { | | 143 | { |
144 | uint8_t enaddr[ETHER_ADDR_LEN]; | | 144 | uint8_t enaddr[ETHER_ADDR_LEN]; |
145 | uint32_t maclo, machi; | | 145 | uint32_t maclo, machi; |
146 | struct mii_data * const mii = &sc->sc_mii; | | 146 | struct mii_data * const mii = &sc->sc_mii; |
147 | struct ifnet * const ifp = &sc->sc_ec.ec_if; | | 147 | struct ifnet * const ifp = &sc->sc_ec.ec_if; |
148 | prop_dictionary_t dict; | | 148 | prop_dictionary_t dict; |
| | | 149 | int rv; |
149 | | | 150 | |
150 | mutex_init(&sc->sc_mdio_lock, MUTEX_DEFAULT, IPL_NET); | | 151 | mutex_init(&sc->sc_mdio_lock, MUTEX_DEFAULT, IPL_NET); |
151 | sc->sc_mii_clk = mii_clk & 7; | | 152 | sc->sc_mii_clk = mii_clk & 7; |
152 | | | 153 | |
153 | dict = device_properties(sc->sc_dev); | | 154 | dict = device_properties(sc->sc_dev); |
154 | prop_data_t ea = dict ? prop_dictionary_get(dict, "mac-address") : NULL; | | 155 | prop_data_t ea = dict ? prop_dictionary_get(dict, "mac-address") : NULL; |
155 | if (ea != NULL) { | | 156 | if (ea != NULL) { |
156 | /* | | 157 | /* |
157 | * If the MAC address is overriden by a device property, | | 158 | * If the MAC address is overriden by a device property, |
158 | * use that. | | 159 | * use that. |
159 | */ | | 160 | */ |
160 | KASSERT(prop_object_type(ea) == PROP_TYPE_DATA); | | 161 | KASSERT(prop_object_type(ea) == PROP_TYPE_DATA); |
161 | KASSERT(prop_data_size(ea) == ETHER_ADDR_LEN); | | 162 | KASSERT(prop_data_size(ea) == ETHER_ADDR_LEN); |
| @@ -249,48 +250,57 @@ dwc_gmac_attach(struct dwc_gmac_softc *s | | | @@ -249,48 +250,57 @@ dwc_gmac_attach(struct dwc_gmac_softc *s |
249 | } else { | | 250 | } else { |
250 | ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_AUTO); | | 251 | ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_AUTO); |
251 | } | | 252 | } |
252 | | | 253 | |
253 | /* | | 254 | /* |
254 | * We can support 802.1Q VLAN-sized frames. | | 255 | * We can support 802.1Q VLAN-sized frames. |
255 | */ | | 256 | */ |
256 | sc->sc_ec.ec_capabilities |= ETHERCAP_VLAN_MTU; | | 257 | sc->sc_ec.ec_capabilities |= ETHERCAP_VLAN_MTU; |
257 | | | 258 | |
258 | /* | | 259 | /* |
259 | * Ready, attach interface | | 260 | * Ready, attach interface |
260 | */ | | 261 | */ |
261 | /* Attach the interface. */ | | 262 | /* Attach the interface. */ |
262 | if_initialize(ifp); | | 263 | rv = if_initialize(ifp); |
| | | 264 | if (rv != 0) |
| | | 265 | goto fail_2; |
263 | sc->sc_ipq = if_percpuq_create(&sc->sc_ec.ec_if); | | 266 | sc->sc_ipq = if_percpuq_create(&sc->sc_ec.ec_if); |
264 | if_deferred_start_init(ifp, NULL); | | 267 | if_deferred_start_init(ifp, NULL); |
265 | ether_ifattach(ifp, enaddr); | | 268 | ether_ifattach(ifp, enaddr); |
266 | ether_set_ifflags_cb(&sc->sc_ec, dwc_gmac_ifflags_cb); | | 269 | ether_set_ifflags_cb(&sc->sc_ec, dwc_gmac_ifflags_cb); |
267 | if_register(ifp); | | 270 | if_register(ifp); |
268 | | | 271 | |
269 | /* | | 272 | /* |
270 | * Enable interrupts | | 273 | * Enable interrupts |
271 | */ | | 274 | */ |
272 | mutex_enter(sc->sc_lock); | | 275 | mutex_enter(sc->sc_lock); |
273 | bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_INTMASK, | | 276 | bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_INTMASK, |
274 | AWIN_DEF_MAC_INTRMASK); | | 277 | AWIN_DEF_MAC_INTRMASK); |
275 | bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_INTENABLE, | | 278 | bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_INTENABLE, |
276 | GMAC_DEF_DMA_INT_MASK); | | 279 | GMAC_DEF_DMA_INT_MASK); |
277 | mutex_exit(sc->sc_lock); | | 280 | mutex_exit(sc->sc_lock); |
278 | | | 281 | |
279 | return; | | 282 | return; |
280 | | | 283 | fail_2: |
| | | 284 | ifmedia_removeall(&mii->mii_media); |
| | | 285 | mii_detach(&mii, MII_PHY_ANY, MII_OFFSET_ANY); |
| | | 286 | mutex_destroy(&sc->sc_txq.t_mtx); |
| | | 287 | mutex_destroy(&sc->sc_rxq.r_mtx); |
| | | 288 | mutex_obj_free(sc->sc_lock); |
281 | fail: | | 289 | fail: |
282 | dwc_gmac_free_rx_ring(sc, &sc->sc_rxq); | | 290 | dwc_gmac_free_rx_ring(sc, &sc->sc_rxq); |
283 | dwc_gmac_free_tx_ring(sc, &sc->sc_txq); | | 291 | dwc_gmac_free_tx_ring(sc, &sc->sc_txq); |
| | | 292 | dwc_gmac_free_dma_rings(sc); |
| | | 293 | mutex_destroy(&sc->sc_mdio_lock); |
284 | } | | 294 | } |
285 | | | 295 | |
286 | | | 296 | |
287 | | | 297 | |
288 | static int | | 298 | static int |
289 | dwc_gmac_reset(struct dwc_gmac_softc *sc) | | 299 | dwc_gmac_reset(struct dwc_gmac_softc *sc) |
290 | { | | 300 | { |
291 | size_t cnt; | | 301 | size_t cnt; |
292 | bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_BUSMODE, | | 302 | bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_BUSMODE, |
293 | bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_BUSMODE) | GMAC_BUSMODE_RESET); | | 303 | bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_BUSMODE) | GMAC_BUSMODE_RESET); |
294 | for (cnt = 0; cnt < 3000; cnt++) { | | 304 | for (cnt = 0; cnt < 3000; cnt++) { |
295 | if ((bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_BUSMODE) | | 305 | if ((bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_BUSMODE) |
296 | & GMAC_BUSMODE_RESET) == 0) | | 306 | & GMAC_BUSMODE_RESET) == 0) |