diff options
Diffstat (limited to 'net/atm/common.c')
| -rw-r--r-- | net/atm/common.c | 66 |
1 files changed, 40 insertions, 26 deletions
diff --git a/net/atm/common.c b/net/atm/common.c index 63feea49fb13..6656b111cc05 100644 --- a/net/atm/common.c +++ b/net/atm/common.c | |||
| @@ -221,6 +221,29 @@ void vcc_release_async(struct atm_vcc *vcc, int reply) | |||
| 221 | EXPORT_SYMBOL(vcc_release_async); | 221 | EXPORT_SYMBOL(vcc_release_async); |
| 222 | 222 | ||
| 223 | 223 | ||
| 224 | void atm_dev_release_vccs(struct atm_dev *dev) | ||
| 225 | { | ||
| 226 | int i; | ||
| 227 | |||
| 228 | write_lock_irq(&vcc_sklist_lock); | ||
| 229 | for (i = 0; i < VCC_HTABLE_SIZE; i++) { | ||
| 230 | struct hlist_head *head = &vcc_hash[i]; | ||
| 231 | struct hlist_node *node, *tmp; | ||
| 232 | struct sock *s; | ||
| 233 | struct atm_vcc *vcc; | ||
| 234 | |||
| 235 | sk_for_each_safe(s, node, tmp, head) { | ||
| 236 | vcc = atm_sk(s); | ||
| 237 | if (vcc->dev == dev) { | ||
| 238 | vcc_release_async(vcc, -EPIPE); | ||
| 239 | sk_del_node_init(s); | ||
| 240 | } | ||
| 241 | } | ||
| 242 | } | ||
| 243 | write_unlock_irq(&vcc_sklist_lock); | ||
| 244 | } | ||
| 245 | |||
| 246 | |||
| 224 | static int adjust_tp(struct atm_trafprm *tp,unsigned char aal) | 247 | static int adjust_tp(struct atm_trafprm *tp,unsigned char aal) |
| 225 | { | 248 | { |
| 226 | int max_sdu; | 249 | int max_sdu; |
| @@ -332,12 +355,13 @@ static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, short vpi, | |||
| 332 | return -EINVAL; | 355 | return -EINVAL; |
| 333 | if (vci > 0 && vci < ATM_NOT_RSV_VCI && !capable(CAP_NET_BIND_SERVICE)) | 356 | if (vci > 0 && vci < ATM_NOT_RSV_VCI && !capable(CAP_NET_BIND_SERVICE)) |
| 334 | return -EPERM; | 357 | return -EPERM; |
| 335 | error = 0; | 358 | error = -ENODEV; |
| 336 | if (!try_module_get(dev->ops->owner)) | 359 | if (!try_module_get(dev->ops->owner)) |
| 337 | return -ENODEV; | 360 | return error; |
| 338 | vcc->dev = dev; | 361 | vcc->dev = dev; |
| 339 | write_lock_irq(&vcc_sklist_lock); | 362 | write_lock_irq(&vcc_sklist_lock); |
| 340 | if ((error = find_ci(vcc, &vpi, &vci))) { | 363 | if (test_bit(ATM_DF_REMOVED, &dev->flags) || |
| 364 | (error = find_ci(vcc, &vpi, &vci))) { | ||
| 341 | write_unlock_irq(&vcc_sklist_lock); | 365 | write_unlock_irq(&vcc_sklist_lock); |
| 342 | goto fail_module_put; | 366 | goto fail_module_put; |
| 343 | } | 367 | } |
| @@ -423,33 +447,23 @@ int vcc_connect(struct socket *sock, int itf, short vpi, int vci) | |||
| 423 | if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS || | 447 | if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS || |
| 424 | vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) | 448 | vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) |
| 425 | return -EINVAL; | 449 | return -EINVAL; |
| 426 | if (itf != ATM_ITF_ANY) { | 450 | if (likely(itf != ATM_ITF_ANY)) { |
| 427 | dev = atm_dev_lookup(itf); | 451 | dev = try_then_request_module(atm_dev_lookup(itf), "atm-device-%d", itf); |
| 428 | if (!dev) | ||
| 429 | return -ENODEV; | ||
| 430 | error = __vcc_connect(vcc, dev, vpi, vci); | ||
| 431 | if (error) { | ||
| 432 | atm_dev_put(dev); | ||
| 433 | return error; | ||
| 434 | } | ||
| 435 | } else { | 452 | } else { |
| 436 | struct list_head *p, *next; | ||
| 437 | |||
| 438 | dev = NULL; | 453 | dev = NULL; |
| 439 | spin_lock(&atm_dev_lock); | 454 | down(&atm_dev_mutex); |
| 440 | list_for_each_safe(p, next, &atm_devs) { | 455 | if (!list_empty(&atm_devs)) { |
| 441 | dev = list_entry(p, struct atm_dev, dev_list); | 456 | dev = list_entry(atm_devs.next, struct atm_dev, dev_list); |
| 442 | atm_dev_hold(dev); | 457 | atm_dev_hold(dev); |
| 443 | spin_unlock(&atm_dev_lock); | ||
| 444 | if (!__vcc_connect(vcc, dev, vpi, vci)) | ||
| 445 | break; | ||
| 446 | atm_dev_put(dev); | ||
| 447 | dev = NULL; | ||
| 448 | spin_lock(&atm_dev_lock); | ||
| 449 | } | 458 | } |
| 450 | spin_unlock(&atm_dev_lock); | 459 | up(&atm_dev_mutex); |
| 451 | if (!dev) | 460 | } |
| 452 | return -ENODEV; | 461 | if (!dev) |
| 462 | return -ENODEV; | ||
| 463 | error = __vcc_connect(vcc, dev, vpi, vci); | ||
| 464 | if (error) { | ||
| 465 | atm_dev_put(dev); | ||
| 466 | return error; | ||
| 453 | } | 467 | } |
| 454 | if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) | 468 | if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) |
| 455 | set_bit(ATM_VF_PARTIAL,&vcc->flags); | 469 | set_bit(ATM_VF_PARTIAL,&vcc->flags); |
