diff options
author | Linas Vepstas <linas@austin.ibm.com> | 2006-12-06 23:38:07 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-07 11:39:38 -0500 |
commit | c15bb296403f1ce448384d58742e0dc04f49d664 (patch) | |
tree | 911efea27934319e4b35e6c389901ad495b3198f /drivers/char/hvcs.c | |
parent | 940cc2df935d00e704c7b8366bdaedda379abf85 (diff) |
[PATCH] HVCS char driver janitoring: move block of code
Move a block of code from the bottom of the file to the top, which is needed
to enable the cleanup.
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
Cc: Ryan S. Arnold <rsa@us.ibm.com>
Cc: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/char/hvcs.c')
-rw-r--r-- | drivers/char/hvcs.c | 426 |
1 files changed, 210 insertions, 216 deletions
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 8728255c9463..d090622f1dea 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c | |||
@@ -337,11 +337,6 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp); | |||
337 | static void hvcs_close(struct tty_struct *tty, struct file *filp); | 337 | static void hvcs_close(struct tty_struct *tty, struct file *filp); |
338 | static void hvcs_hangup(struct tty_struct * tty); | 338 | static void hvcs_hangup(struct tty_struct * tty); |
339 | 339 | ||
340 | static void hvcs_create_device_attrs(struct hvcs_struct *hvcsd); | ||
341 | static void hvcs_remove_device_attrs(struct vio_dev *vdev); | ||
342 | static void hvcs_create_driver_attrs(void); | ||
343 | static void hvcs_remove_driver_attrs(void); | ||
344 | |||
345 | static int __devinit hvcs_probe(struct vio_dev *dev, | 340 | static int __devinit hvcs_probe(struct vio_dev *dev, |
346 | const struct vio_device_id *id); | 341 | const struct vio_device_id *id); |
347 | static int __devexit hvcs_remove(struct vio_dev *dev); | 342 | static int __devexit hvcs_remove(struct vio_dev *dev); |
@@ -353,6 +348,172 @@ static void __exit hvcs_module_exit(void); | |||
353 | #define HVCS_TRY_WRITE 0x00000004 | 348 | #define HVCS_TRY_WRITE 0x00000004 |
354 | #define HVCS_READ_MASK (HVCS_SCHED_READ | HVCS_QUICK_READ) | 349 | #define HVCS_READ_MASK (HVCS_SCHED_READ | HVCS_QUICK_READ) |
355 | 350 | ||
351 | static inline struct hvcs_struct *from_vio_dev(struct vio_dev *viod) | ||
352 | { | ||
353 | return viod->dev.driver_data; | ||
354 | } | ||
355 | /* The sysfs interface for the driver and devices */ | ||
356 | |||
357 | static ssize_t hvcs_partner_vtys_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
358 | { | ||
359 | struct vio_dev *viod = to_vio_dev(dev); | ||
360 | struct hvcs_struct *hvcsd = from_vio_dev(viod); | ||
361 | unsigned long flags; | ||
362 | int retval; | ||
363 | |||
364 | spin_lock_irqsave(&hvcsd->lock, flags); | ||
365 | retval = sprintf(buf, "%X\n", hvcsd->p_unit_address); | ||
366 | spin_unlock_irqrestore(&hvcsd->lock, flags); | ||
367 | return retval; | ||
368 | } | ||
369 | static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL); | ||
370 | |||
371 | static ssize_t hvcs_partner_clcs_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
372 | { | ||
373 | struct vio_dev *viod = to_vio_dev(dev); | ||
374 | struct hvcs_struct *hvcsd = from_vio_dev(viod); | ||
375 | unsigned long flags; | ||
376 | int retval; | ||
377 | |||
378 | spin_lock_irqsave(&hvcsd->lock, flags); | ||
379 | retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]); | ||
380 | spin_unlock_irqrestore(&hvcsd->lock, flags); | ||
381 | return retval; | ||
382 | } | ||
383 | static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL); | ||
384 | |||
385 | static ssize_t hvcs_current_vty_store(struct device *dev, struct device_attribute *attr, const char * buf, | ||
386 | size_t count) | ||
387 | { | ||
388 | /* | ||
389 | * Don't need this feature at the present time because firmware doesn't | ||
390 | * yet support multiple partners. | ||
391 | */ | ||
392 | printk(KERN_INFO "HVCS: Denied current_vty change: -EPERM.\n"); | ||
393 | return -EPERM; | ||
394 | } | ||
395 | |||
396 | static ssize_t hvcs_current_vty_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
397 | { | ||
398 | struct vio_dev *viod = to_vio_dev(dev); | ||
399 | struct hvcs_struct *hvcsd = from_vio_dev(viod); | ||
400 | unsigned long flags; | ||
401 | int retval; | ||
402 | |||
403 | spin_lock_irqsave(&hvcsd->lock, flags); | ||
404 | retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]); | ||
405 | spin_unlock_irqrestore(&hvcsd->lock, flags); | ||
406 | return retval; | ||
407 | } | ||
408 | |||
409 | static DEVICE_ATTR(current_vty, | ||
410 | S_IRUGO | S_IWUSR, hvcs_current_vty_show, hvcs_current_vty_store); | ||
411 | |||
412 | static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribute *attr, const char *buf, | ||
413 | size_t count) | ||
414 | { | ||
415 | struct vio_dev *viod = to_vio_dev(dev); | ||
416 | struct hvcs_struct *hvcsd = from_vio_dev(viod); | ||
417 | unsigned long flags; | ||
418 | |||
419 | /* writing a '0' to this sysfs entry will result in the disconnect. */ | ||
420 | if (simple_strtol(buf, NULL, 0) != 0) | ||
421 | return -EINVAL; | ||
422 | |||
423 | spin_lock_irqsave(&hvcsd->lock, flags); | ||
424 | |||
425 | if (hvcsd->open_count > 0) { | ||
426 | spin_unlock_irqrestore(&hvcsd->lock, flags); | ||
427 | printk(KERN_INFO "HVCS: vterm state unchanged. " | ||
428 | "The hvcs device node is still in use.\n"); | ||
429 | return -EPERM; | ||
430 | } | ||
431 | |||
432 | if (hvcsd->connected == 0) { | ||
433 | spin_unlock_irqrestore(&hvcsd->lock, flags); | ||
434 | printk(KERN_INFO "HVCS: vterm state unchanged. The" | ||
435 | " vty-server is not connected to a vty.\n"); | ||
436 | return -EPERM; | ||
437 | } | ||
438 | |||
439 | hvcs_partner_free(hvcsd); | ||
440 | printk(KERN_INFO "HVCS: Closed vty-server@%X and" | ||
441 | " partner vty@%X:%d connection.\n", | ||
442 | hvcsd->vdev->unit_address, | ||
443 | hvcsd->p_unit_address, | ||
444 | (uint32_t)hvcsd->p_partition_ID); | ||
445 | |||
446 | spin_unlock_irqrestore(&hvcsd->lock, flags); | ||
447 | return count; | ||
448 | } | ||
449 | |||
450 | static ssize_t hvcs_vterm_state_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
451 | { | ||
452 | struct vio_dev *viod = to_vio_dev(dev); | ||
453 | struct hvcs_struct *hvcsd = from_vio_dev(viod); | ||
454 | unsigned long flags; | ||
455 | int retval; | ||
456 | |||
457 | spin_lock_irqsave(&hvcsd->lock, flags); | ||
458 | retval = sprintf(buf, "%d\n", hvcsd->connected); | ||
459 | spin_unlock_irqrestore(&hvcsd->lock, flags); | ||
460 | return retval; | ||
461 | } | ||
462 | static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR, | ||
463 | hvcs_vterm_state_show, hvcs_vterm_state_store); | ||
464 | |||
465 | static ssize_t hvcs_index_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
466 | { | ||
467 | struct vio_dev *viod = to_vio_dev(dev); | ||
468 | struct hvcs_struct *hvcsd = from_vio_dev(viod); | ||
469 | unsigned long flags; | ||
470 | int retval; | ||
471 | |||
472 | spin_lock_irqsave(&hvcsd->lock, flags); | ||
473 | retval = sprintf(buf, "%d\n", hvcsd->index); | ||
474 | spin_unlock_irqrestore(&hvcsd->lock, flags); | ||
475 | return retval; | ||
476 | } | ||
477 | |||
478 | static DEVICE_ATTR(index, S_IRUGO, hvcs_index_show, NULL); | ||
479 | |||
480 | static struct attribute *hvcs_attrs[] = { | ||
481 | &dev_attr_partner_vtys.attr, | ||
482 | &dev_attr_partner_clcs.attr, | ||
483 | &dev_attr_current_vty.attr, | ||
484 | &dev_attr_vterm_state.attr, | ||
485 | &dev_attr_index.attr, | ||
486 | NULL, | ||
487 | }; | ||
488 | |||
489 | static struct attribute_group hvcs_attr_group = { | ||
490 | .attrs = hvcs_attrs, | ||
491 | }; | ||
492 | |||
493 | static ssize_t hvcs_rescan_show(struct device_driver *ddp, char *buf) | ||
494 | { | ||
495 | /* A 1 means it is updating, a 0 means it is done updating */ | ||
496 | return snprintf(buf, PAGE_SIZE, "%d\n", hvcs_rescan_status); | ||
497 | } | ||
498 | |||
499 | static ssize_t hvcs_rescan_store(struct device_driver *ddp, const char * buf, | ||
500 | size_t count) | ||
501 | { | ||
502 | if ((simple_strtol(buf, NULL, 0) != 1) | ||
503 | && (hvcs_rescan_status != 0)) | ||
504 | return -EINVAL; | ||
505 | |||
506 | hvcs_rescan_status = 1; | ||
507 | printk(KERN_INFO "HVCS: rescanning partner info for all" | ||
508 | " vty-servers.\n"); | ||
509 | hvcs_rescan_devices_list(); | ||
510 | hvcs_rescan_status = 0; | ||
511 | return count; | ||
512 | } | ||
513 | |||
514 | static DRIVER_ATTR(rescan, | ||
515 | S_IRUGO | S_IWUSR, hvcs_rescan_show, hvcs_rescan_store); | ||
516 | |||
356 | static void hvcs_kick(void) | 517 | static void hvcs_kick(void) |
357 | { | 518 | { |
358 | hvcs_kicked = 1; | 519 | hvcs_kicked = 1; |
@@ -575,7 +736,7 @@ static void destroy_hvcs_struct(struct kobject *kobj) | |||
575 | spin_unlock_irqrestore(&hvcsd->lock, flags); | 736 | spin_unlock_irqrestore(&hvcsd->lock, flags); |
576 | spin_unlock(&hvcs_structs_lock); | 737 | spin_unlock(&hvcs_structs_lock); |
577 | 738 | ||
578 | hvcs_remove_device_attrs(vdev); | 739 | sysfs_remove_group(&vdev->dev.kobj, &hvcs_attr_group); |
579 | 740 | ||
580 | kfree(hvcsd); | 741 | kfree(hvcsd); |
581 | } | 742 | } |
@@ -608,6 +769,7 @@ static int __devinit hvcs_probe( | |||
608 | { | 769 | { |
609 | struct hvcs_struct *hvcsd; | 770 | struct hvcs_struct *hvcsd; |
610 | int index; | 771 | int index; |
772 | int retval; | ||
611 | 773 | ||
612 | if (!dev || !id) { | 774 | if (!dev || !id) { |
613 | printk(KERN_ERR "HVCS: probed with invalid parameter.\n"); | 775 | printk(KERN_ERR "HVCS: probed with invalid parameter.\n"); |
@@ -658,14 +820,16 @@ static int __devinit hvcs_probe( | |||
658 | * the hvcs_struct has been added to the devices list then the user app | 820 | * the hvcs_struct has been added to the devices list then the user app |
659 | * will get -ENODEV. | 821 | * will get -ENODEV. |
660 | */ | 822 | */ |
661 | |||
662 | spin_lock(&hvcs_structs_lock); | 823 | spin_lock(&hvcs_structs_lock); |
663 | |||
664 | list_add_tail(&(hvcsd->next), &hvcs_structs); | 824 | list_add_tail(&(hvcsd->next), &hvcs_structs); |
665 | |||
666 | spin_unlock(&hvcs_structs_lock); | 825 | spin_unlock(&hvcs_structs_lock); |
667 | 826 | ||
668 | hvcs_create_device_attrs(hvcsd); | 827 | retval = sysfs_create_group(&dev->dev.kobj, &hvcs_attr_group); |
828 | if (retval) { | ||
829 | printk(KERN_ERR "HVCS: Can't create sysfs attrs for vty-server@%X\n", | ||
830 | hvcsd->vdev->unit_address); | ||
831 | return retval; | ||
832 | } | ||
669 | 833 | ||
670 | printk(KERN_INFO "HVCS: vty-server@%X added to the vio bus.\n", dev->unit_address); | 834 | printk(KERN_INFO "HVCS: vty-server@%X added to the vio bus.\n", dev->unit_address); |
671 | 835 | ||
@@ -1354,8 +1518,10 @@ static int __init hvcs_module_init(void) | |||
1354 | if (!hvcs_tty_driver) | 1518 | if (!hvcs_tty_driver) |
1355 | return -ENOMEM; | 1519 | return -ENOMEM; |
1356 | 1520 | ||
1357 | if (hvcs_alloc_index_list(num_ttys_to_alloc)) | 1521 | if (hvcs_alloc_index_list(num_ttys_to_alloc)) { |
1358 | return -ENOMEM; | 1522 | rc = -ENOMEM; |
1523 | goto index_fail; | ||
1524 | } | ||
1359 | 1525 | ||
1360 | hvcs_tty_driver->owner = THIS_MODULE; | 1526 | hvcs_tty_driver->owner = THIS_MODULE; |
1361 | 1527 | ||
@@ -1385,41 +1551,57 @@ static int __init hvcs_module_init(void) | |||
1385 | * dynamically assigned major and minor numbers for our devices. | 1551 | * dynamically assigned major and minor numbers for our devices. |
1386 | */ | 1552 | */ |
1387 | if (tty_register_driver(hvcs_tty_driver)) { | 1553 | if (tty_register_driver(hvcs_tty_driver)) { |
1388 | printk(KERN_ERR "HVCS: registration " | 1554 | printk(KERN_ERR "HVCS: registration as a tty driver failed.\n"); |
1389 | " as a tty driver failed.\n"); | 1555 | rc = -EIO; |
1390 | hvcs_free_index_list(); | 1556 | goto register_fail; |
1391 | put_tty_driver(hvcs_tty_driver); | ||
1392 | return -EIO; | ||
1393 | } | 1557 | } |
1394 | 1558 | ||
1395 | hvcs_pi_buff = kmalloc(PAGE_SIZE, GFP_KERNEL); | 1559 | hvcs_pi_buff = kmalloc(PAGE_SIZE, GFP_KERNEL); |
1396 | if (!hvcs_pi_buff) { | 1560 | if (!hvcs_pi_buff) { |
1397 | tty_unregister_driver(hvcs_tty_driver); | 1561 | rc = -ENOMEM; |
1398 | hvcs_free_index_list(); | 1562 | goto buff_alloc_fail; |
1399 | put_tty_driver(hvcs_tty_driver); | ||
1400 | return -ENOMEM; | ||
1401 | } | 1563 | } |
1402 | 1564 | ||
1403 | hvcs_task = kthread_run(khvcsd, NULL, "khvcsd"); | 1565 | hvcs_task = kthread_run(khvcsd, NULL, "khvcsd"); |
1404 | if (IS_ERR(hvcs_task)) { | 1566 | if (IS_ERR(hvcs_task)) { |
1405 | printk(KERN_ERR "HVCS: khvcsd creation failed. Driver not loaded.\n"); | 1567 | printk(KERN_ERR "HVCS: khvcsd creation failed. Driver not loaded.\n"); |
1406 | kfree(hvcs_pi_buff); | 1568 | rc = -EIO; |
1407 | tty_unregister_driver(hvcs_tty_driver); | 1569 | goto kthread_fail; |
1408 | hvcs_free_index_list(); | ||
1409 | put_tty_driver(hvcs_tty_driver); | ||
1410 | return -EIO; | ||
1411 | } | 1570 | } |
1412 | 1571 | ||
1413 | rc = vio_register_driver(&hvcs_vio_driver); | 1572 | rc = vio_register_driver(&hvcs_vio_driver); |
1573 | if (rc) { | ||
1574 | printk(KERN_ERR "HVCS: can't register vio driver\n"); | ||
1575 | goto vio_fail; | ||
1576 | } | ||
1414 | 1577 | ||
1415 | /* | 1578 | /* |
1416 | * This needs to be done AFTER the vio_register_driver() call or else | 1579 | * This needs to be done AFTER the vio_register_driver() call or else |
1417 | * the kobjects won't be initialized properly. | 1580 | * the kobjects won't be initialized properly. |
1418 | */ | 1581 | */ |
1419 | hvcs_create_driver_attrs(); | 1582 | rc = driver_create_file(&(hvcs_vio_driver.driver), &driver_attr_rescan); |
1583 | if (rc) { | ||
1584 | printk(KERN_ERR "HVCS: sysfs attr create failed\n"); | ||
1585 | goto attr_fail; | ||
1586 | } | ||
1420 | 1587 | ||
1421 | printk(KERN_INFO "HVCS: driver module inserted.\n"); | 1588 | printk(KERN_INFO "HVCS: driver module inserted.\n"); |
1422 | 1589 | ||
1590 | return 0; | ||
1591 | |||
1592 | attr_fail: | ||
1593 | vio_unregister_driver(&hvcs_vio_driver); | ||
1594 | vio_fail: | ||
1595 | kthread_stop(hvcs_task); | ||
1596 | kthread_fail: | ||
1597 | kfree(hvcs_pi_buff); | ||
1598 | buff_alloc_fail: | ||
1599 | tty_unregister_driver(hvcs_tty_driver); | ||
1600 | register_fail: | ||
1601 | hvcs_free_index_list(); | ||
1602 | index_fail: | ||
1603 | put_tty_driver(hvcs_tty_driver); | ||
1604 | hvcs_tty_driver = NULL; | ||
1423 | return rc; | 1605 | return rc; |
1424 | } | 1606 | } |
1425 | 1607 | ||
@@ -1441,7 +1623,7 @@ static void __exit hvcs_module_exit(void) | |||
1441 | hvcs_pi_buff = NULL; | 1623 | hvcs_pi_buff = NULL; |
1442 | spin_unlock(&hvcs_pi_lock); | 1624 | spin_unlock(&hvcs_pi_lock); |
1443 | 1625 | ||
1444 | hvcs_remove_driver_attrs(); | 1626 | driver_remove_file(&hvcs_vio_driver.driver, &driver_attr_rescan); |
1445 | 1627 | ||
1446 | vio_unregister_driver(&hvcs_vio_driver); | 1628 | vio_unregister_driver(&hvcs_vio_driver); |
1447 | 1629 | ||
@@ -1456,191 +1638,3 @@ static void __exit hvcs_module_exit(void) | |||
1456 | 1638 | ||
1457 | module_init(hvcs_module_init); | 1639 | module_init(hvcs_module_init); |
1458 | module_exit(hvcs_module_exit); | 1640 | module_exit(hvcs_module_exit); |
1459 | |||
1460 | static inline struct hvcs_struct *from_vio_dev(struct vio_dev *viod) | ||
1461 | { | ||
1462 | return viod->dev.driver_data; | ||
1463 | } | ||
1464 | /* The sysfs interface for the driver and devices */ | ||
1465 | |||
1466 | static ssize_t hvcs_partner_vtys_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
1467 | { | ||
1468 | struct vio_dev *viod = to_vio_dev(dev); | ||
1469 | struct hvcs_struct *hvcsd = from_vio_dev(viod); | ||
1470 | unsigned long flags; | ||
1471 | int retval; | ||
1472 | |||
1473 | spin_lock_irqsave(&hvcsd->lock, flags); | ||
1474 | retval = sprintf(buf, "%X\n", hvcsd->p_unit_address); | ||
1475 | spin_unlock_irqrestore(&hvcsd->lock, flags); | ||
1476 | return retval; | ||
1477 | } | ||
1478 | static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL); | ||
1479 | |||
1480 | static ssize_t hvcs_partner_clcs_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
1481 | { | ||
1482 | struct vio_dev *viod = to_vio_dev(dev); | ||
1483 | struct hvcs_struct *hvcsd = from_vio_dev(viod); | ||
1484 | unsigned long flags; | ||
1485 | int retval; | ||
1486 | |||
1487 | spin_lock_irqsave(&hvcsd->lock, flags); | ||
1488 | retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]); | ||
1489 | spin_unlock_irqrestore(&hvcsd->lock, flags); | ||
1490 | return retval; | ||
1491 | } | ||
1492 | static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL); | ||
1493 | |||
1494 | static ssize_t hvcs_current_vty_store(struct device *dev, struct device_attribute *attr, const char * buf, | ||
1495 | size_t count) | ||
1496 | { | ||
1497 | /* | ||
1498 | * Don't need this feature at the present time because firmware doesn't | ||
1499 | * yet support multiple partners. | ||
1500 | */ | ||
1501 | printk(KERN_INFO "HVCS: Denied current_vty change: -EPERM.\n"); | ||
1502 | return -EPERM; | ||
1503 | } | ||
1504 | |||
1505 | static ssize_t hvcs_current_vty_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
1506 | { | ||
1507 | struct vio_dev *viod = to_vio_dev(dev); | ||
1508 | struct hvcs_struct *hvcsd = from_vio_dev(viod); | ||
1509 | unsigned long flags; | ||
1510 | int retval; | ||
1511 | |||
1512 | spin_lock_irqsave(&hvcsd->lock, flags); | ||
1513 | retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]); | ||
1514 | spin_unlock_irqrestore(&hvcsd->lock, flags); | ||
1515 | return retval; | ||
1516 | } | ||
1517 | |||
1518 | static DEVICE_ATTR(current_vty, | ||
1519 | S_IRUGO | S_IWUSR, hvcs_current_vty_show, hvcs_current_vty_store); | ||
1520 | |||
1521 | static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribute *attr, const char *buf, | ||
1522 | size_t count) | ||
1523 | { | ||
1524 | struct vio_dev *viod = to_vio_dev(dev); | ||
1525 | struct hvcs_struct *hvcsd = from_vio_dev(viod); | ||
1526 | unsigned long flags; | ||
1527 | |||
1528 | /* writing a '0' to this sysfs entry will result in the disconnect. */ | ||
1529 | if (simple_strtol(buf, NULL, 0) != 0) | ||
1530 | return -EINVAL; | ||
1531 | |||
1532 | spin_lock_irqsave(&hvcsd->lock, flags); | ||
1533 | |||
1534 | if (hvcsd->open_count > 0) { | ||
1535 | spin_unlock_irqrestore(&hvcsd->lock, flags); | ||
1536 | printk(KERN_INFO "HVCS: vterm state unchanged. " | ||
1537 | "The hvcs device node is still in use.\n"); | ||
1538 | return -EPERM; | ||
1539 | } | ||
1540 | |||
1541 | if (hvcsd->connected == 0) { | ||
1542 | spin_unlock_irqrestore(&hvcsd->lock, flags); | ||
1543 | printk(KERN_INFO "HVCS: vterm state unchanged. The" | ||
1544 | " vty-server is not connected to a vty.\n"); | ||
1545 | return -EPERM; | ||
1546 | } | ||
1547 | |||
1548 | hvcs_partner_free(hvcsd); | ||
1549 | printk(KERN_INFO "HVCS: Closed vty-server@%X and" | ||
1550 | " partner vty@%X:%d connection.\n", | ||
1551 | hvcsd->vdev->unit_address, | ||
1552 | hvcsd->p_unit_address, | ||
1553 | (uint32_t)hvcsd->p_partition_ID); | ||
1554 | |||
1555 | spin_unlock_irqrestore(&hvcsd->lock, flags); | ||
1556 | return count; | ||
1557 | } | ||
1558 | |||
1559 | static ssize_t hvcs_vterm_state_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
1560 | { | ||
1561 | struct vio_dev *viod = to_vio_dev(dev); | ||
1562 | struct hvcs_struct *hvcsd = from_vio_dev(viod); | ||
1563 | unsigned long flags; | ||
1564 | int retval; | ||
1565 | |||
1566 | spin_lock_irqsave(&hvcsd->lock, flags); | ||
1567 | retval = sprintf(buf, "%d\n", hvcsd->connected); | ||
1568 | spin_unlock_irqrestore(&hvcsd->lock, flags); | ||
1569 | return retval; | ||
1570 | } | ||
1571 | static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR, | ||
1572 | hvcs_vterm_state_show, hvcs_vterm_state_store); | ||
1573 | |||
1574 | static ssize_t hvcs_index_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
1575 | { | ||
1576 | struct vio_dev *viod = to_vio_dev(dev); | ||
1577 | struct hvcs_struct *hvcsd = from_vio_dev(viod); | ||
1578 | unsigned long flags; | ||
1579 | int retval; | ||
1580 | |||
1581 | spin_lock_irqsave(&hvcsd->lock, flags); | ||
1582 | retval = sprintf(buf, "%d\n", hvcsd->index); | ||
1583 | spin_unlock_irqrestore(&hvcsd->lock, flags); | ||
1584 | return retval; | ||
1585 | } | ||
1586 | |||
1587 | static DEVICE_ATTR(index, S_IRUGO, hvcs_index_show, NULL); | ||
1588 | |||
1589 | static struct attribute *hvcs_attrs[] = { | ||
1590 | &dev_attr_partner_vtys.attr, | ||
1591 | &dev_attr_partner_clcs.attr, | ||
1592 | &dev_attr_current_vty.attr, | ||
1593 | &dev_attr_vterm_state.attr, | ||
1594 | &dev_attr_index.attr, | ||
1595 | NULL, | ||
1596 | }; | ||
1597 | |||
1598 | static struct attribute_group hvcs_attr_group = { | ||
1599 | .attrs = hvcs_attrs, | ||
1600 | }; | ||
1601 | |||
1602 | static void hvcs_create_device_attrs(struct hvcs_struct *hvcsd) | ||
1603 | { | ||
1604 | struct vio_dev *vdev = hvcsd->vdev; | ||
1605 | sysfs_create_group(&vdev->dev.kobj, &hvcs_attr_group); | ||
1606 | } | ||
1607 | |||
1608 | static void hvcs_remove_device_attrs(struct vio_dev *vdev) | ||
1609 | { | ||
1610 | sysfs_remove_group(&vdev->dev.kobj, &hvcs_attr_group); | ||
1611 | } | ||
1612 | |||
1613 | static ssize_t hvcs_rescan_show(struct device_driver *ddp, char *buf) | ||
1614 | { | ||
1615 | /* A 1 means it is updating, a 0 means it is done updating */ | ||
1616 | return snprintf(buf, PAGE_SIZE, "%d\n", hvcs_rescan_status); | ||
1617 | } | ||
1618 | |||
1619 | static ssize_t hvcs_rescan_store(struct device_driver *ddp, const char * buf, | ||
1620 | size_t count) | ||
1621 | { | ||
1622 | if ((simple_strtol(buf, NULL, 0) != 1) | ||
1623 | && (hvcs_rescan_status != 0)) | ||
1624 | return -EINVAL; | ||
1625 | |||
1626 | hvcs_rescan_status = 1; | ||
1627 | printk(KERN_INFO "HVCS: rescanning partner info for all" | ||
1628 | " vty-servers.\n"); | ||
1629 | hvcs_rescan_devices_list(); | ||
1630 | hvcs_rescan_status = 0; | ||
1631 | return count; | ||
1632 | } | ||
1633 | static DRIVER_ATTR(rescan, | ||
1634 | S_IRUGO | S_IWUSR, hvcs_rescan_show, hvcs_rescan_store); | ||
1635 | |||
1636 | static void hvcs_create_driver_attrs(void) | ||
1637 | { | ||
1638 | struct device_driver *driverfs = &(hvcs_vio_driver.driver); | ||
1639 | driver_create_file(driverfs, &driver_attr_rescan); | ||
1640 | } | ||
1641 | |||
1642 | static void hvcs_remove_driver_attrs(void) | ||
1643 | { | ||
1644 | struct device_driver *driverfs = &(hvcs_vio_driver.driver); | ||
1645 | driver_remove_file(driverfs, &driver_attr_rescan); | ||
1646 | } | ||