Mon Oct 23 09:27:46 2017 UTC ()
- If if_initialize() failed in the attach function, free resources and return.
- Add missing dwc_gmac_free_dma_rings() and mutex_destroy() when attach
   failed.


(msaitoh)
diff -r1.40 -r1.41 src/sys/dev/ic/dwc_gmac.c

cvs diff -r1.40 -r1.41 src/sys/dev/ic/dwc_gmac.c (expand / switch to unified diff)

--- src/sys/dev/ic/dwc_gmac.c 2017/02/20 07:43:29 1.40
+++ src/sys/dev/ic/dwc_gmac.c 2017/10/23 09:27:46 1.41
@@ -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
141void 141void
142dwc_gmac_attach(struct dwc_gmac_softc *sc, uint32_t mii_clk) 142dwc_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 283fail_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);
281fail: 289fail:
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
288static int 298static int
289dwc_gmac_reset(struct dwc_gmac_softc *sc) 299dwc_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)