aboutsummaryrefslogtreecommitdiffstats
path: root/net/atm/br2684.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/atm/br2684.c')
-rw-r--r--net/atm/br2684.c66
1 files changed, 64 insertions, 2 deletions
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 6719af6a59fa..651babdfab38 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -139,6 +139,43 @@ static struct net_device *br2684_find_dev(const struct br2684_if_spec *s)
139 return NULL; 139 return NULL;
140} 140}
141 141
142static int atm_dev_event(struct notifier_block *this, unsigned long event,
143 void *arg)
144{
145 struct atm_dev *atm_dev = arg;
146 struct list_head *lh;
147 struct net_device *net_dev;
148 struct br2684_vcc *brvcc;
149 struct atm_vcc *atm_vcc;
150 unsigned long flags;
151
152 pr_debug("event=%ld dev=%p\n", event, atm_dev);
153
154 read_lock_irqsave(&devs_lock, flags);
155 list_for_each(lh, &br2684_devs) {
156 net_dev = list_entry_brdev(lh);
157
158 list_for_each_entry(brvcc, &BRPRIV(net_dev)->brvccs, brvccs) {
159 atm_vcc = brvcc->atmvcc;
160 if (atm_vcc && brvcc->atmvcc->dev == atm_dev) {
161
162 if (atm_vcc->dev->signal == ATM_PHY_SIG_LOST)
163 netif_carrier_off(net_dev);
164 else
165 netif_carrier_on(net_dev);
166
167 }
168 }
169 }
170 read_unlock_irqrestore(&devs_lock, flags);
171
172 return NOTIFY_DONE;
173}
174
175static struct notifier_block atm_dev_notifier = {
176 .notifier_call = atm_dev_event,
177};
178
142/* chained vcc->pop function. Check if we should wake the netif_queue */ 179/* chained vcc->pop function. Check if we should wake the netif_queue */
143static void br2684_pop(struct atm_vcc *vcc, struct sk_buff *skb) 180static void br2684_pop(struct atm_vcc *vcc, struct sk_buff *skb)
144{ 181{
@@ -362,6 +399,12 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
362 unregister_netdev(net_dev); 399 unregister_netdev(net_dev);
363 free_netdev(net_dev); 400 free_netdev(net_dev);
364 } 401 }
402 read_lock_irq(&devs_lock);
403 if (list_empty(&br2684_devs)) {
404 /* last br2684 device */
405 unregister_atmdevice_notifier(&atm_dev_notifier);
406 }
407 read_unlock_irq(&devs_lock);
365 return; 408 return;
366 } 409 }
367 410
@@ -530,6 +573,13 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
530 573
531 br2684_push(atmvcc, skb); 574 br2684_push(atmvcc, skb);
532 } 575 }
576
577 /* initialize netdev carrier state */
578 if (atmvcc->dev->signal == ATM_PHY_SIG_LOST)
579 netif_carrier_off(net_dev);
580 else
581 netif_carrier_on(net_dev);
582
533 __module_get(THIS_MODULE); 583 __module_get(THIS_MODULE);
534 return 0; 584 return 0;
535 585
@@ -620,9 +670,16 @@ static int br2684_create(void __user *arg)
620 } 670 }
621 671
622 write_lock_irq(&devs_lock); 672 write_lock_irq(&devs_lock);
673
623 brdev->payload = payload; 674 brdev->payload = payload;
624 brdev->number = list_empty(&br2684_devs) ? 1 : 675
625 BRPRIV(list_entry_brdev(br2684_devs.prev))->number + 1; 676 if (list_empty(&br2684_devs)) {
677 /* 1st br2684 device */
678 register_atmdevice_notifier(&atm_dev_notifier);
679 brdev->number = 1;
680 } else
681 brdev->number = BRPRIV(list_entry_brdev(br2684_devs.prev))->number + 1;
682
626 list_add_tail(&brdev->br2684_devs, &br2684_devs); 683 list_add_tail(&brdev->br2684_devs, &br2684_devs);
627 write_unlock_irq(&devs_lock); 684 write_unlock_irq(&devs_lock);
628 return 0; 685 return 0;
@@ -772,6 +829,11 @@ static void __exit br2684_exit(void)
772 remove_proc_entry("br2684", atm_proc_root); 829 remove_proc_entry("br2684", atm_proc_root);
773#endif 830#endif
774 831
832
833 /* if not already empty */
834 if (!list_empty(&br2684_devs))
835 unregister_atmdevice_notifier(&atm_dev_notifier);
836
775 while (!list_empty(&br2684_devs)) { 837 while (!list_empty(&br2684_devs)) {
776 net_dev = list_entry_brdev(br2684_devs.next); 838 net_dev = list_entry_brdev(br2684_devs.next);
777 brdev = BRPRIV(net_dev); 839 brdev = BRPRIV(net_dev);