diff options
| author | Takashi Iwai <tiwai@suse.de> | 2013-04-18 16:24:31 +0200 | 
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2013-04-18 16:24:31 +0200 | 
| commit | 8dd2b66d1a961231685a3bfe5937c85d846fbf5d (patch) | |
| tree | 8117553488bf4ef09b048a4b343cf37cc16bf46d /net/ipv4/devinet.c | |
| parent | 126825e7ea271ae8e3172e10ca1fc22c908b5385 (diff) | |
| parent | 24568ea4bef5ab8106206eddf5512434421c00ed (diff) | |
| download | olio-linux-3.10-8dd2b66d1a961231685a3bfe5937c85d846fbf5d.tar.xz olio-linux-3.10-8dd2b66d1a961231685a3bfe5937c85d846fbf5d.zip  | |
Merge tag 'asoc-v3.10-2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-next
ASoC: More updates for v3.10
The main additional change here is Lars-Peter's DMA work plus the
platform conversions which have been tested - getting this in mainline
will make life easier for development after the merge window.  These
factor a large chunk of code out of the drivers for the platforms using
dmaengine, greatly simplifying development.
Diffstat (limited to 'net/ipv4/devinet.c')
| -rw-r--r-- | net/ipv4/devinet.c | 60 | 
1 files changed, 44 insertions, 16 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 96083b7a436..c6287cd978c 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -587,13 +587,16 @@ static void check_lifetime(struct work_struct *work)  {  	unsigned long now, next, next_sec, next_sched;  	struct in_ifaddr *ifa; +	struct hlist_node *n;  	int i;  	now = jiffies;  	next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY); -	rcu_read_lock();  	for (i = 0; i < IN4_ADDR_HSIZE; i++) { +		bool change_needed = false; + +		rcu_read_lock();  		hlist_for_each_entry_rcu(ifa, &inet_addr_lst[i], hash) {  			unsigned long age; @@ -606,16 +609,7 @@ static void check_lifetime(struct work_struct *work)  			if (ifa->ifa_valid_lft != INFINITY_LIFE_TIME &&  			    age >= ifa->ifa_valid_lft) { -				struct in_ifaddr **ifap ; - -				rtnl_lock(); -				for (ifap = &ifa->ifa_dev->ifa_list; -				     *ifap != NULL; ifap = &ifa->ifa_next) { -					if (*ifap == ifa) -						inet_del_ifa(ifa->ifa_dev, -							     ifap, 1); -				} -				rtnl_unlock(); +				change_needed = true;  			} else if (ifa->ifa_preferred_lft ==  				   INFINITY_LIFE_TIME) {  				continue; @@ -625,10 +619,8 @@ static void check_lifetime(struct work_struct *work)  					next = ifa->ifa_tstamp +  					       ifa->ifa_valid_lft * HZ; -				if (!(ifa->ifa_flags & IFA_F_DEPRECATED)) { -					ifa->ifa_flags |= IFA_F_DEPRECATED; -					rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0); -				} +				if (!(ifa->ifa_flags & IFA_F_DEPRECATED)) +					change_needed = true;  			} else if (time_before(ifa->ifa_tstamp +  					       ifa->ifa_preferred_lft * HZ,  					       next)) { @@ -636,8 +628,42 @@ static void check_lifetime(struct work_struct *work)  				       ifa->ifa_preferred_lft * HZ;  			}  		} +		rcu_read_unlock(); +		if (!change_needed) +			continue; +		rtnl_lock(); +		hlist_for_each_entry_safe(ifa, n, &inet_addr_lst[i], hash) { +			unsigned long age; + +			if (ifa->ifa_flags & IFA_F_PERMANENT) +				continue; + +			/* We try to batch several events at once. */ +			age = (now - ifa->ifa_tstamp + +			       ADDRCONF_TIMER_FUZZ_MINUS) / HZ; + +			if (ifa->ifa_valid_lft != INFINITY_LIFE_TIME && +			    age >= ifa->ifa_valid_lft) { +				struct in_ifaddr **ifap; + +				for (ifap = &ifa->ifa_dev->ifa_list; +				     *ifap != NULL; ifap = &(*ifap)->ifa_next) { +					if (*ifap == ifa) { +						inet_del_ifa(ifa->ifa_dev, +							     ifap, 1); +						break; +					} +				} +			} else if (ifa->ifa_preferred_lft != +				   INFINITY_LIFE_TIME && +				   age >= ifa->ifa_preferred_lft && +				   !(ifa->ifa_flags & IFA_F_DEPRECATED)) { +				ifa->ifa_flags |= IFA_F_DEPRECATED; +				rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0); +			} +		} +		rtnl_unlock();  	} -	rcu_read_unlock();  	next_sec = round_jiffies_up(next);  	next_sched = next; @@ -804,6 +830,8 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg  			return -EEXIST;  		ifa = ifa_existing;  		set_ifa_lifetime(ifa, valid_lft, prefered_lft); +		cancel_delayed_work(&check_lifetime_work); +		schedule_delayed_work(&check_lifetime_work, 0);  		rtmsg_ifa(RTM_NEWADDR, ifa, nlh, NETLINK_CB(skb).portid);  		blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);  	}  |