diff options
Diffstat (limited to 'net/core/dev.c')
-rw-r--r-- | net/core/dev.c | 79 |
1 files changed, 75 insertions, 4 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 8301e2ac747f..5a7f20f78574 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -116,6 +116,7 @@ | |||
116 | #include <linux/dmaengine.h> | 116 | #include <linux/dmaengine.h> |
117 | #include <linux/err.h> | 117 | #include <linux/err.h> |
118 | #include <linux/ctype.h> | 118 | #include <linux/ctype.h> |
119 | #include <linux/if_arp.h> | ||
119 | 120 | ||
120 | /* | 121 | /* |
121 | * The list of packet types we will receive (as opposed to discard) | 122 | * The list of packet types we will receive (as opposed to discard) |
@@ -217,6 +218,73 @@ extern void netdev_unregister_sysfs(struct net_device *); | |||
217 | #define netdev_unregister_sysfs(dev) do { } while(0) | 218 | #define netdev_unregister_sysfs(dev) do { } while(0) |
218 | #endif | 219 | #endif |
219 | 220 | ||
221 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
222 | /* | ||
223 | * register_netdevice() inits dev->_xmit_lock and sets lockdep class | ||
224 | * according to dev->type | ||
225 | */ | ||
226 | static const unsigned short netdev_lock_type[] = | ||
227 | {ARPHRD_NETROM, ARPHRD_ETHER, ARPHRD_EETHER, ARPHRD_AX25, | ||
228 | ARPHRD_PRONET, ARPHRD_CHAOS, ARPHRD_IEEE802, ARPHRD_ARCNET, | ||
229 | ARPHRD_APPLETLK, ARPHRD_DLCI, ARPHRD_ATM, ARPHRD_METRICOM, | ||
230 | ARPHRD_IEEE1394, ARPHRD_EUI64, ARPHRD_INFINIBAND, ARPHRD_SLIP, | ||
231 | ARPHRD_CSLIP, ARPHRD_SLIP6, ARPHRD_CSLIP6, ARPHRD_RSRVD, | ||
232 | ARPHRD_ADAPT, ARPHRD_ROSE, ARPHRD_X25, ARPHRD_HWX25, | ||
233 | ARPHRD_PPP, ARPHRD_CISCO, ARPHRD_LAPB, ARPHRD_DDCMP, | ||
234 | ARPHRD_RAWHDLC, ARPHRD_TUNNEL, ARPHRD_TUNNEL6, ARPHRD_FRAD, | ||
235 | ARPHRD_SKIP, ARPHRD_LOOPBACK, ARPHRD_LOCALTLK, ARPHRD_FDDI, | ||
236 | ARPHRD_BIF, ARPHRD_SIT, ARPHRD_IPDDP, ARPHRD_IPGRE, | ||
237 | ARPHRD_PIMREG, ARPHRD_HIPPI, ARPHRD_ASH, ARPHRD_ECONET, | ||
238 | ARPHRD_IRDA, ARPHRD_FCPP, ARPHRD_FCAL, ARPHRD_FCPL, | ||
239 | ARPHRD_FCFABRIC, ARPHRD_IEEE802_TR, ARPHRD_IEEE80211, | ||
240 | ARPHRD_IEEE80211_PRISM, ARPHRD_IEEE80211_RADIOTAP, ARPHRD_VOID, | ||
241 | ARPHRD_NONE}; | ||
242 | |||
243 | static const char *netdev_lock_name[] = | ||
244 | {"_xmit_NETROM", "_xmit_ETHER", "_xmit_EETHER", "_xmit_AX25", | ||
245 | "_xmit_PRONET", "_xmit_CHAOS", "_xmit_IEEE802", "_xmit_ARCNET", | ||
246 | "_xmit_APPLETLK", "_xmit_DLCI", "_xmit_ATM", "_xmit_METRICOM", | ||
247 | "_xmit_IEEE1394", "_xmit_EUI64", "_xmit_INFINIBAND", "_xmit_SLIP", | ||
248 | "_xmit_CSLIP", "_xmit_SLIP6", "_xmit_CSLIP6", "_xmit_RSRVD", | ||
249 | "_xmit_ADAPT", "_xmit_ROSE", "_xmit_X25", "_xmit_HWX25", | ||
250 | "_xmit_PPP", "_xmit_CISCO", "_xmit_LAPB", "_xmit_DDCMP", | ||
251 | "_xmit_RAWHDLC", "_xmit_TUNNEL", "_xmit_TUNNEL6", "_xmit_FRAD", | ||
252 | "_xmit_SKIP", "_xmit_LOOPBACK", "_xmit_LOCALTLK", "_xmit_FDDI", | ||
253 | "_xmit_BIF", "_xmit_SIT", "_xmit_IPDDP", "_xmit_IPGRE", | ||
254 | "_xmit_PIMREG", "_xmit_HIPPI", "_xmit_ASH", "_xmit_ECONET", | ||
255 | "_xmit_IRDA", "_xmit_FCPP", "_xmit_FCAL", "_xmit_FCPL", | ||
256 | "_xmit_FCFABRIC", "_xmit_IEEE802_TR", "_xmit_IEEE80211", | ||
257 | "_xmit_IEEE80211_PRISM", "_xmit_IEEE80211_RADIOTAP", "_xmit_VOID", | ||
258 | "_xmit_NONE"}; | ||
259 | |||
260 | static struct lock_class_key netdev_xmit_lock_key[ARRAY_SIZE(netdev_lock_type)]; | ||
261 | |||
262 | static inline unsigned short netdev_lock_pos(unsigned short dev_type) | ||
263 | { | ||
264 | int i; | ||
265 | |||
266 | for (i = 0; i < ARRAY_SIZE(netdev_lock_type); i++) | ||
267 | if (netdev_lock_type[i] == dev_type) | ||
268 | return i; | ||
269 | /* the last key is used by default */ | ||
270 | return ARRAY_SIZE(netdev_lock_type) - 1; | ||
271 | } | ||
272 | |||
273 | static inline void netdev_set_lockdep_class(spinlock_t *lock, | ||
274 | unsigned short dev_type) | ||
275 | { | ||
276 | int i; | ||
277 | |||
278 | i = netdev_lock_pos(dev_type); | ||
279 | lockdep_set_class_and_name(lock, &netdev_xmit_lock_key[i], | ||
280 | netdev_lock_name[i]); | ||
281 | } | ||
282 | #else | ||
283 | static inline void netdev_set_lockdep_class(spinlock_t *lock, | ||
284 | unsigned short dev_type) | ||
285 | { | ||
286 | } | ||
287 | #endif | ||
220 | 288 | ||
221 | /******************************************************************************* | 289 | /******************************************************************************* |
222 | 290 | ||
@@ -3001,6 +3069,7 @@ int register_netdevice(struct net_device *dev) | |||
3001 | 3069 | ||
3002 | spin_lock_init(&dev->queue_lock); | 3070 | spin_lock_init(&dev->queue_lock); |
3003 | spin_lock_init(&dev->_xmit_lock); | 3071 | spin_lock_init(&dev->_xmit_lock); |
3072 | netdev_set_lockdep_class(&dev->_xmit_lock, dev->type); | ||
3004 | dev->xmit_lock_owner = -1; | 3073 | dev->xmit_lock_owner = -1; |
3005 | spin_lock_init(&dev->ingress_lock); | 3074 | spin_lock_init(&dev->ingress_lock); |
3006 | 3075 | ||
@@ -3245,7 +3314,6 @@ void netdev_run_todo(void) | |||
3245 | continue; | 3314 | continue; |
3246 | } | 3315 | } |
3247 | 3316 | ||
3248 | netdev_unregister_sysfs(dev); | ||
3249 | dev->reg_state = NETREG_UNREGISTERED; | 3317 | dev->reg_state = NETREG_UNREGISTERED; |
3250 | 3318 | ||
3251 | netdev_wait_allrefs(dev); | 3319 | netdev_wait_allrefs(dev); |
@@ -3256,11 +3324,11 @@ void netdev_run_todo(void) | |||
3256 | BUG_TRAP(!dev->ip6_ptr); | 3324 | BUG_TRAP(!dev->ip6_ptr); |
3257 | BUG_TRAP(!dev->dn_ptr); | 3325 | BUG_TRAP(!dev->dn_ptr); |
3258 | 3326 | ||
3259 | /* It must be the very last action, | ||
3260 | * after this 'dev' may point to freed up memory. | ||
3261 | */ | ||
3262 | if (dev->destructor) | 3327 | if (dev->destructor) |
3263 | dev->destructor(dev); | 3328 | dev->destructor(dev); |
3329 | |||
3330 | /* Free network device */ | ||
3331 | kobject_put(&dev->dev.kobj); | ||
3264 | } | 3332 | } |
3265 | 3333 | ||
3266 | out: | 3334 | out: |
@@ -3411,6 +3479,9 @@ void unregister_netdevice(struct net_device *dev) | |||
3411 | /* Notifier chain MUST detach us from master device. */ | 3479 | /* Notifier chain MUST detach us from master device. */ |
3412 | BUG_TRAP(!dev->master); | 3480 | BUG_TRAP(!dev->master); |
3413 | 3481 | ||
3482 | /* Remove entries from sysfs */ | ||
3483 | netdev_unregister_sysfs(dev); | ||
3484 | |||
3414 | /* Finish processing unregister after unlock */ | 3485 | /* Finish processing unregister after unlock */ |
3415 | net_set_todo(dev); | 3486 | net_set_todo(dev); |
3416 | 3487 | ||