patch-2.3.47 linux/net/core/dev.c

Next file: linux/net/core/dev_mcast.c
Previous file: linux/net/bridge/sysctl_net_bridge.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.46/linux/net/core/dev.c linux/net/core/dev.c
@@ -81,7 +81,7 @@
 #include <net/slhc.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
-#include <net/br.h>
+#include <linux/if_bridge.h>
 #include <net/dst.h>
 #include <net/pkt_sched.h>
 #include <net/profile.h>
@@ -190,14 +190,11 @@
 		dev_clear_fastroute(pt->dev);
 	}
 #endif
-	if(pt->type==htons(ETH_P_ALL))
-	{
+	if (pt->type == htons(ETH_P_ALL)) {
 		netdev_nit++;
 		pt->next=ptype_all;
 		ptype_all=pt;
-	}
-	else
-	{	
+	} else {
 		hash=ntohs(pt->type)&15;
 		pt->next = ptype_base[hash];
 		ptype_base[hash] = pt;
@@ -216,19 +213,16 @@
 
 	write_lock_bh(&ptype_lock);
 
-	if(pt->type==htons(ETH_P_ALL))
-	{
+	if (pt->type == htons(ETH_P_ALL)) {
 		netdev_nit--;
 		pt1=&ptype_all;
-	}
-	else
+	} else {
 		pt1=&ptype_base[ntohs(pt->type)&15];
+	}
 
-	for(; (*pt1)!=NULL; pt1=&((*pt1)->next))
-	{
-		if(pt==(*pt1))
-		{
-			*pt1=pt->next;
+	for (; (*pt1) != NULL; pt1 = &((*pt1)->next)) {
+		if (pt == (*pt1)) {
+			*pt1 = pt->next;
 #ifdef CONFIG_NET_FASTROUTE
 			if (pt->data)
 				netdev_fastroute_obstacles--;
@@ -357,14 +351,13 @@
 {
 	int i;
 	char buf[32];
+
 	/*
 	 *	If you need over 100 please also fix the algorithm...
 	 */
-	for(i=0;i<100;i++)
-	{
+	for (i = 0; i < 100; i++) {
 		sprintf(buf,name,i);
-		if(__dev_get_by_name(buf)==NULL)
-		{
+		if (__dev_get_by_name(buf) == NULL) {
 			strcpy(dev->name, buf);
 			return i;
 		}
@@ -375,16 +368,14 @@
 struct net_device *dev_alloc(const char *name, int *err)
 {
 	struct net_device *dev=kmalloc(sizeof(struct net_device)+16, GFP_KERNEL);
-	if(dev==NULL)
-	{
-		*err=-ENOBUFS;
+	if (dev == NULL) {
+		*err = -ENOBUFS;
 		return NULL;
 	}
 	memset(dev, 0, sizeof(struct net_device));
-	dev->name=(char *)(dev+1);	/* Name string space */
-	*err=dev_alloc_name(dev,name);
-	if(*err<0)
-	{
+	dev->name = (char *)(dev + 1);	/* Name string space */
+	*err = dev_alloc_name(dev, name);
+	if (*err < 0) {
 		kfree(dev);
 		return NULL;
 	}
@@ -408,7 +399,7 @@
 
 void dev_load(const char *name)
 {
-	if(!__dev_get_by_name(name) && capable(CAP_SYS_MODULE))
+	if (!__dev_get_by_name(name) && capable(CAP_SYS_MODULE))
 		request_module(name);
 }
 
@@ -441,6 +432,12 @@
 		return 0;
 
 	/*
+	 *	Is it even present?
+	 */
+	if (!netif_device_present(dev))
+		return -ENODEV;
+
+	/*
 	 *	Call device private open method
 	 */
 	 
@@ -458,7 +455,7 @@
 		 */
 		dev->flags |= IFF_UP;
 
-		set_bit(LINK_STATE_START, &dev->state);
+		set_bit(__LINK_STATE_START, &dev->state);
 
 		/*
 		 *	Initialize multicasting status 
@@ -528,11 +525,14 @@
 
 	dev_deactivate(dev);
 
-	clear_bit(LINK_STATE_START, &dev->state);
+	clear_bit(__LINK_STATE_START, &dev->state);
 
 	/*
 	 *	Call the device specific close. This cannot fail.
 	 *	Only if device is UP
+	 *
+	 *	We allow it to be called even after a DETACH hot-plug
+	 *	event.
 	 */
 	 
 	if (dev->stop)
@@ -673,7 +673,7 @@
 			spin_lock(&dev->xmit_lock);
 			dev->xmit_lock_owner = cpu;
 
-			if (!test_bit(LINK_STATE_XOFF, &dev->state)) {
+			if (!netif_queue_stopped(dev)) {
 				if (netdev_nit)
 					dev_queue_xmit_nit(skb,dev);
 
@@ -781,7 +781,7 @@
 	struct softnet_data *queue;
 	unsigned long flags;
 
-	if(skb->stamp.tv_sec==0)
+	if (skb->stamp.tv_sec == 0)
 		get_fast_time(&skb->stamp);
 
 	/* The code is rearranged so that the path is the most
@@ -833,37 +833,6 @@
 	kfree_skb(skb);
 }
 
-#ifdef CONFIG_BRIDGE
-static inline void handle_bridge(struct sk_buff *skb, unsigned short type)
-{
-	/* 
-	 * The br_stats.flags is checked here to save the expense of a 
-	 * function call.
-	 */
-	if ((br_stats.flags & BR_UP) && br_call_bridge(skb, type))
-	{
-		/*
-		 *	We pass the bridge a complete frame. This means
-		 *	recovering the MAC header first.
-		 */
-		
-		int offset;
-
-		skb=skb_clone(skb, GFP_ATOMIC);
-		if(skb==NULL)		
-			return;
-			
-		offset=skb->data-skb->mac.raw;
-		skb_push(skb,offset);	/* Put header back on for bridge */
-
-		if(br_receive_frame(skb))
-			return;
-		kfree_skb(skb);
-	}
-	return;
-}
-#endif
-
 /* Deliver skb to an old protocol, which is not threaded well
    or which do not understand shared skbs.
  */
@@ -941,7 +910,7 @@
 			struct net_device *dev = head;
 			head = head->next_sched;
 
-			clear_bit(LINK_STATE_SCHED, &dev->state);
+			clear_bit(__LINK_STATE_SCHED, &dev->state);
 
 			if (spin_trylock(&dev->queue_lock)) {
 				qdisc_run(dev);
@@ -953,6 +922,32 @@
 	}
 }
 
+void net_call_rx_atomic(void (*fn)(void))
+{
+	write_lock_bh(&ptype_lock);
+	fn();
+	write_unlock_bh(&ptype_lock);
+}
+
+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
+void (*br_handle_frame_hook)(struct sk_buff *skb) = NULL;
+#endif
+
+#define HANDLE_BRIDGE(SKB, PT_PREV)					\
+do {									\
+	if ((SKB)->dev->br_port != NULL &&				\
+	    br_handle_frame_hook != NULL) {				\
+		if (PT_PREV)						\
+			if (!(PT_PREV->data))				\
+				deliver_to_old_ones(PT_PREV, SKB, 1);	\
+			else						\
+				pt_prev->func(SKB, SKB->dev, PT_PREV);	\
+									\
+		br_handle_frame_hook(SKB);				\
+		continue;						\
+	}								\
+} while(0)
+
 static void net_rx_action(struct softirq_action *h)
 {
 	int this_cpu = smp_processor_id();
@@ -985,9 +980,7 @@
 		{
 			struct packet_type *ptype, *pt_prev;
 			unsigned short type = skb->protocol;
-#ifdef CONFIG_BRIDGE
-			handle_bridge(skb, type);
-#endif
+
 			pt_prev = NULL;
 			for (ptype = ptype_all; ptype; ptype = ptype->next) {
 				if (!ptype->dev || ptype->dev == skb->dev) {
@@ -1004,6 +997,11 @@
 					pt_prev = ptype;
 				}
 			}
+
+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
+			HANDLE_BRIDGE(skb, pt_prev);
+#endif
+
 			for (ptype=ptype_base[ntohs(type)&15];ptype;ptype=ptype->next) {
 				if (ptype->type == type &&
 				    (!ptype->dev || ptype->dev == skb->dev)) {
@@ -1020,6 +1018,7 @@
 					pt_prev = ptype;
 				}
 			}
+
 			if (pt_prev) {
 				if (!pt_prev->data)
 					deliver_to_old_ones(pt_prev, skb, 1);
@@ -1212,11 +1211,10 @@
  
 static int dev_get_info(char *buffer, char **start, off_t offset, int length)
 {
-	int len=0;
-	off_t begin=0;
-	off_t pos=0;
+	int len = 0;
+	off_t begin = 0;
+	off_t pos = 0;
 	int size;
-	
 	struct net_device *dev;
 
 
@@ -1224,31 +1222,31 @@
 		"Inter-|   Receive                                                |  Transmit\n"
 		" face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed\n");
 	
-	pos+=size;
-	len+=size;
+	pos += size;
+	len += size;
 	
 
 	read_lock(&dev_base_lock);
 	for (dev = dev_base; dev != NULL; dev = dev->next) {
 		size = sprintf_stats(buffer+len, dev);
-		len+=size;
-		pos=begin+len;
+		len += size;
+		pos = begin + len;
 				
-		if(pos<offset) {
-			len=0;
-			begin=pos;
+		if (pos < offset) {
+			len = 0;
+			begin = pos;
 		}
-		if(pos>offset+length)
+		if (pos > offset + length)
 			break;
 	}
 	read_unlock(&dev_base_lock);
 
-	*start=buffer+(offset-begin);	/* Start of wanted data */
-	len-=(offset-begin);		/* Start slop */
-	if(len>length)
-		len=length;		/* Ending slop */
-	if (len<0)
-		len=0;
+	*start = buffer + (offset - begin);	/* Start of wanted data */
+	len -= (offset - begin);		/* Start slop */
+	if (len > length)
+		len = length;			/* Ending slop */
+	if (len < 0)
+		len = 0;
 	return len;
 }
 
@@ -1280,7 +1278,7 @@
 
 	if (len > length)
 		len = length;
-	if(len < 0)
+	if (len < 0)
 		len = 0;
 
 	*start = buffer + offset;
@@ -1307,8 +1305,7 @@
 				       (struct iw_statistics *) NULL);
 	int size;
 
-	if(stats != (struct iw_statistics *) NULL)
-	{
+	if (stats != (struct iw_statistics *) NULL) {
 		size = sprintf(buffer,
 			       "%6s: %04x  %3d%c  %3d%c  %3d%c  %6d %6d %6d\n",
 			       dev->name,
@@ -1349,30 +1346,30 @@
 		       " face | tus | link level noise |  nwid  crypt   misc\n"
 			);
 	
-	pos+=size;
-	len+=size;
+	pos += size;
+	len += size;
 
 	read_lock(&dev_base_lock);
-	for(dev = dev_base; dev != NULL; dev = dev->next) {
-		size = sprintf_wireless_stats(buffer+len, dev);
-		len+=size;
-		pos=begin+len;
-
-		if(pos < offset) {
-			len=0;
-			begin=pos;
+	for (dev = dev_base; dev != NULL; dev = dev->next) {
+		size = sprintf_wireless_stats(buffer + len, dev);
+		len += size;
+		pos = begin + len;
+
+		if (pos < offset) {
+			len = 0;
+			begin = pos;
 		}
-		if(pos > offset + length)
+		if (pos > offset + length)
 			break;
 	}
 	read_unlock(&dev_base_lock);
 
 	*start = buffer + (offset - begin);	/* Start of wanted data */
 	len -= (offset - begin);		/* Start slop */
-	if(len > length)
-		len = length;		/* Ending slop */
-	if (len<0)
-		len=0;
+	if (len > length)
+		len = length;			/* Ending slop */
+	if (len < 0)
+		len = 0;
 
 	return len;
 }
@@ -1516,7 +1513,7 @@
 		case SIOCGIFFLAGS:	/* Get interface flags */
 			ifr->ifr_flags = (dev->flags&~(IFF_PROMISC|IFF_ALLMULTI|IFF_RUNNING))
 				|(dev->gflags&(IFF_PROMISC|IFF_ALLMULTI));
-			if (!test_bit(LINK_STATE_DOWN, &dev->state))
+			if (netif_running(dev))
 				ifr->ifr_flags |= IFF_RUNNING;
 			return 0;
 
@@ -1545,6 +1542,9 @@
 			if (ifr->ifr_mtu<0)
 				return -EINVAL;
 
+			if (!netif_device_present(dev))
+				return -ENODEV;
+
 			if (dev->change_mtu)
 				err = dev->change_mtu(dev, ifr->ifr_mtu);
 			else {
@@ -1561,17 +1561,19 @@
 			return 0;
 				
 		case SIOCSIFHWADDR:
-			if(dev->set_mac_address==NULL)
+			if (dev->set_mac_address == NULL)
 				return -EOPNOTSUPP;
-			if(ifr->ifr_hwaddr.sa_family!=dev->type)
+			if (ifr->ifr_hwaddr.sa_family!=dev->type)
 				return -EINVAL;
-			err=dev->set_mac_address(dev,&ifr->ifr_hwaddr);
+			if (!netif_device_present(dev))
+				return -ENODEV;
+			err = dev->set_mac_address(dev, &ifr->ifr_hwaddr);
 			if (!err)
 				notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);
 			return err;
 			
 		case SIOCSIFHWBROADCAST:
-			if(ifr->ifr_hwaddr.sa_family!=dev->type)
+			if (ifr->ifr_hwaddr.sa_family!=dev->type)
 				return -EINVAL;
 			memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data, MAX_ADDR_LEN);
 			notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);
@@ -1587,21 +1589,28 @@
 			return 0;
 			
 		case SIOCSIFMAP:
-			if (dev->set_config)
+			if (dev->set_config) {
+				if (!netif_device_present(dev))
+					return -ENODEV;
 				return dev->set_config(dev,&ifr->ifr_map);
+			}
 			return -EOPNOTSUPP;
 			
 		case SIOCADDMULTI:
-			if(dev->set_multicast_list==NULL ||
-			   ifr->ifr_hwaddr.sa_family!=AF_UNSPEC)
+			if (dev->set_multicast_list == NULL ||
+			    ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
 				return -EINVAL;
+			if (!netif_device_present(dev))
+				return -ENODEV;
 			dev_mc_add(dev,ifr->ifr_hwaddr.sa_data, dev->addr_len, 1);
 			return 0;
 
 		case SIOCDELMULTI:
-			if(dev->set_multicast_list==NULL ||
-			   ifr->ifr_hwaddr.sa_family!=AF_UNSPEC)
+			if (dev->set_multicast_list == NULL ||
+			    ifr->ifr_hwaddr.sa_family!=AF_UNSPEC)
 				return -EINVAL;
+			if (!netif_device_present(dev))
+				return -ENODEV;
 			dev_mc_delete(dev,ifr->ifr_hwaddr.sa_data,dev->addr_len, 1);
 			return 0;
 
@@ -1614,7 +1623,7 @@
 			return 0;
 
 		case SIOCSIFTXQLEN:
-			if(ifr->ifr_qlen<0)
+			if (ifr->ifr_qlen<0)
 				return -EINVAL;
 			dev->tx_queue_len = ifr->ifr_qlen;
 			return 0;
@@ -1634,17 +1643,23 @@
 		 */
 
 		default:
-			if(cmd >= SIOCDEVPRIVATE &&
-			   cmd <= SIOCDEVPRIVATE + 15) {
-				if (dev->do_ioctl)
+			if (cmd >= SIOCDEVPRIVATE &&
+			    cmd <= SIOCDEVPRIVATE + 15) {
+				if (dev->do_ioctl) {
+					if (!netif_device_present(dev))
+						return -ENODEV;
 					return dev->do_ioctl(dev, ifr, cmd);
+				}
 				return -EOPNOTSUPP;
 			}
 
 #ifdef WIRELESS_EXT
-			if(cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
-				if (dev->do_ioctl)
+			if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
+				if (dev->do_ioctl) {
+					if (!netif_device_present(dev))
+						return -ENODEV;
 					return dev->do_ioctl(dev, ifr, cmd);
+				}
 				return -EOPNOTSUPP;
 			}
 #endif	/* WIRELESS_EXT */
@@ -1868,6 +1883,13 @@
 	if (dev->rebuild_header == NULL)
 		dev->rebuild_header = default_rebuild_header;
 
+	/*
+	 *	Default initial state at registry is that the
+	 *	device is present.
+	 */
+
+	set_bit(__LINK_STATE_PRESENT, &dev->state);
+
 	dev->next = NULL;
 	dev_init_scheduler(dev);
 	write_lock_bh(&dev_base_lock);
@@ -2048,15 +2070,6 @@
 		queue->completion_queue = NULL;
 	}
 	
-	/*
-	 *	The bridge has to be up before the devices
-	 */
-
-#ifdef CONFIG_BRIDGE	 
-	br_init();
-#endif	
-	
-
 #ifdef CONFIG_NET_PROFILE
 	net_profile_init();
 	NET_PROFILE_REGISTER(dev_queue_xmit);
@@ -2124,22 +2137,11 @@
 	dst_init();
 	dev_mcast_init();
 
-#ifdef CONFIG_BRIDGE
-	/*
-	 * Register any statically linked ethernet devices with the bridge
-	 */
-	br_spacedevice_register();
-#endif
-
 	/*
 	 *	Initialise network devices
 	 */
 	 
 	net_device_init();
-
-#ifdef CONFIG_IP_PNP
-	ip_auto_config();
-#endif
 
 	return 0;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)