aboutsummaryrefslogtreecommitdiffstats
path: root/net/atm/resources.c
diff options
context:
space:
mode:
authorStanislaw Gruszka <stf_xl@wp.pl>2005-11-29 19:16:41 -0500
committerDavid S. Miller <davem@davemloft.net>2005-11-29 19:16:41 -0500
commit64bf69ddff7637b7ed7acf9b2a823cc0ee519439 (patch)
treefb3a746e36bcfa307979bef2a20ce5f1d32ec537 /net/atm/resources.c
parentaaaaaadbe7a663d110814db50fcbe7d320eb4c32 (diff)
[ATM]: deregistration removes device from atm_devs list immediately
atm_dev_deregister() removes device from atm_dev list immediately to prevent operations on a phantom device. Decision to free device based only on ->refcnt now. Remove shutdown_atm_dev() use atm_dev_deregister() instead. atm_dev_deregister() also asynchronously releases all vccs related to device. Signed-off-by: Stanislaw Gruszka <stf_xl@wp.pl> Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/atm/resources.c')
-rw-r--r--net/atm/resources.c39
1 files changed, 12 insertions, 27 deletions
diff --git a/net/atm/resources.c b/net/atm/resources.c
index ad533b02b84..c8c459fcb03 100644
--- a/net/atm/resources.c
+++ b/net/atm/resources.c
@@ -70,6 +70,7 @@ struct atm_dev *atm_dev_lookup(int number)
70 return dev; 70 return dev;
71} 71}
72 72
73
73struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, 74struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
74 int number, unsigned long *flags) 75 int number, unsigned long *flags)
75{ 76{
@@ -123,37 +124,22 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
123 124
124void atm_dev_deregister(struct atm_dev *dev) 125void atm_dev_deregister(struct atm_dev *dev)
125{ 126{
126 unsigned long warning_time; 127 BUG_ON(test_bit(ATM_DF_REMOVED, &dev->flags));
127 128 set_bit(ATM_DF_REMOVED, &dev->flags);
128 atm_proc_dev_deregister(dev); 129
129 130 /*
131 * if we remove current device from atm_devs list, new device
132 * with same number can appear, such we need deregister proc,
133 * release async all vccs and remove them from vccs list too
134 */
130 down(&atm_dev_mutex); 135 down(&atm_dev_mutex);
131 list_del(&dev->dev_list); 136 list_del(&dev->dev_list);
132 up(&atm_dev_mutex); 137 up(&atm_dev_mutex);
133 138
134 warning_time = jiffies; 139 atm_dev_release_vccs(dev);
135 while (atomic_read(&dev->refcnt) != 1) { 140 atm_proc_dev_deregister(dev);
136 msleep(250);
137 if ((jiffies - warning_time) > 10 * HZ) {
138 printk(KERN_EMERG "atm_dev_deregister: waiting for "
139 "dev %d to become free. Usage count = %d\n",
140 dev->number, atomic_read(&dev->refcnt));
141 warning_time = jiffies;
142 }
143 }
144
145 kfree(dev);
146}
147 141
148void shutdown_atm_dev(struct atm_dev *dev) 142 atm_dev_put(dev);
149{
150 if (atomic_read(&dev->refcnt) > 1) {
151 set_bit(ATM_DF_CLOSE, &dev->flags);
152 return;
153 }
154 if (dev->ops->dev_close)
155 dev->ops->dev_close(dev);
156 atm_dev_deregister(dev);
157} 143}
158 144
159 145
@@ -433,4 +419,3 @@ void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
433EXPORT_SYMBOL(atm_dev_register); 419EXPORT_SYMBOL(atm_dev_register);
434EXPORT_SYMBOL(atm_dev_deregister); 420EXPORT_SYMBOL(atm_dev_deregister);
435EXPORT_SYMBOL(atm_dev_lookup); 421EXPORT_SYMBOL(atm_dev_lookup);
436EXPORT_SYMBOL(shutdown_atm_dev);