[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>
diff --git a/net/atm/common.c b/net/atm/common.c
index 9e016f4..6656b11 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -221,6 +221,29 @@
 EXPORT_SYMBOL(vcc_release_async);
 
 
+void atm_dev_release_vccs(struct atm_dev *dev)
+{
+	int i;
+
+	write_lock_irq(&vcc_sklist_lock);
+	for (i = 0; i < VCC_HTABLE_SIZE; i++) {
+		struct hlist_head *head = &vcc_hash[i];
+		struct hlist_node *node, *tmp;
+		struct sock *s;
+		struct atm_vcc *vcc;
+
+		sk_for_each_safe(s, node, tmp, head) {
+			vcc = atm_sk(s);
+			if (vcc->dev == dev) {
+				vcc_release_async(vcc, -EPIPE);
+				sk_del_node_init(s);
+			}
+		}
+	}
+	write_unlock_irq(&vcc_sklist_lock);
+}
+
+
 static int adjust_tp(struct atm_trafprm *tp,unsigned char aal)
 {
 	int max_sdu;
@@ -332,12 +355,13 @@
 		return -EINVAL;
 	if (vci > 0 && vci < ATM_NOT_RSV_VCI && !capable(CAP_NET_BIND_SERVICE))
 		return -EPERM;
-	error = 0;
+	error = -ENODEV;
 	if (!try_module_get(dev->ops->owner))
-		return -ENODEV;
+		return error;
 	vcc->dev = dev;
 	write_lock_irq(&vcc_sklist_lock);
-	if ((error = find_ci(vcc, &vpi, &vci))) {
+	if (test_bit(ATM_DF_REMOVED, &dev->flags) || 
+	    (error = find_ci(vcc, &vpi, &vci))) {
 		write_unlock_irq(&vcc_sklist_lock);
 		goto fail_module_put;
 	}