aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/hvcs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/hvcs.c')
-rw-r--r--drivers/char/hvcs.c432
1 files changed, 214 insertions, 218 deletions
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index 8728255c9463..207f7343ba60 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -192,11 +192,13 @@ MODULE_VERSION(HVCS_DRIVER_VERSION);
192 * that will cause echoing or we'll go into recursive loop echoing chars back 192 * that will cause echoing or we'll go into recursive loop echoing chars back
193 * and forth with the console drivers. 193 * and forth with the console drivers.
194 */ 194 */
195static struct termios hvcs_tty_termios = { 195static struct ktermios hvcs_tty_termios = {
196 .c_iflag = IGNBRK | IGNPAR, 196 .c_iflag = IGNBRK | IGNPAR,
197 .c_oflag = OPOST, 197 .c_oflag = OPOST,
198 .c_cflag = B38400 | CS8 | CREAD | HUPCL, 198 .c_cflag = B38400 | CS8 | CREAD | HUPCL,
199 .c_cc = INIT_C_CC 199 .c_cc = INIT_C_CC,
200 .c_ispeed = 38400,
201 .c_ospeed = 38400
200}; 202};
201 203
202/* 204/*
@@ -337,11 +339,6 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp);
337static void hvcs_close(struct tty_struct *tty, struct file *filp); 339static void hvcs_close(struct tty_struct *tty, struct file *filp);
338static void hvcs_hangup(struct tty_struct * tty); 340static void hvcs_hangup(struct tty_struct * tty);
339 341
340static void hvcs_create_device_attrs(struct hvcs_struct *hvcsd);
341static void hvcs_remove_device_attrs(struct vio_dev *vdev);
342static void hvcs_create_driver_attrs(void);
343static void hvcs_remove_driver_attrs(void);
344
345static int __devinit hvcs_probe(struct vio_dev *dev, 342static int __devinit hvcs_probe(struct vio_dev *dev,
346 const struct vio_device_id *id); 343 const struct vio_device_id *id);
347static int __devexit hvcs_remove(struct vio_dev *dev); 344static int __devexit hvcs_remove(struct vio_dev *dev);
@@ -353,6 +350,172 @@ static void __exit hvcs_module_exit(void);
353#define HVCS_TRY_WRITE 0x00000004 350#define HVCS_TRY_WRITE 0x00000004
354#define HVCS_READ_MASK (HVCS_SCHED_READ | HVCS_QUICK_READ) 351#define HVCS_READ_MASK (HVCS_SCHED_READ | HVCS_QUICK_READ)
355 352
353static inline struct hvcs_struct *from_vio_dev(struct vio_dev *viod)
354{
355 return viod->dev.driver_data;
356}
357/* The sysfs interface for the driver and devices */
358
359static ssize_t hvcs_partner_vtys_show(struct device *dev, struct device_attribute *attr, char *buf)
360{
361 struct vio_dev *viod = to_vio_dev(dev);
362 struct hvcs_struct *hvcsd = from_vio_dev(viod);
363 unsigned long flags;
364 int retval;
365
366 spin_lock_irqsave(&hvcsd->lock, flags);
367 retval = sprintf(buf, "%X\n", hvcsd->p_unit_address);
368 spin_unlock_irqrestore(&hvcsd->lock, flags);
369 return retval;
370}
371static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL);
372
373static ssize_t hvcs_partner_clcs_show(struct device *dev, struct device_attribute *attr, char *buf)
374{
375 struct vio_dev *viod = to_vio_dev(dev);
376 struct hvcs_struct *hvcsd = from_vio_dev(viod);
377 unsigned long flags;
378 int retval;
379
380 spin_lock_irqsave(&hvcsd->lock, flags);
381 retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]);
382 spin_unlock_irqrestore(&hvcsd->lock, flags);
383 return retval;
384}
385static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL);
386
387static ssize_t hvcs_current_vty_store(struct device *dev, struct device_attribute *attr, const char * buf,
388 size_t count)
389{
390 /*
391 * Don't need this feature at the present time because firmware doesn't
392 * yet support multiple partners.
393 */
394 printk(KERN_INFO "HVCS: Denied current_vty change: -EPERM.\n");
395 return -EPERM;
396}
397
398static ssize_t hvcs_current_vty_show(struct device *dev, struct device_attribute *attr, char *buf)
399{
400 struct vio_dev *viod = to_vio_dev(dev);
401 struct hvcs_struct *hvcsd = from_vio_dev(viod);
402 unsigned long flags;
403 int retval;
404
405 spin_lock_irqsave(&hvcsd->lock, flags);
406 retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]);
407 spin_unlock_irqrestore(&hvcsd->lock, flags);
408 return retval;
409}
410
411static DEVICE_ATTR(current_vty,
412 S_IRUGO | S_IWUSR, hvcs_current_vty_show, hvcs_current_vty_store);
413
414static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribute *attr, const char *buf,
415 size_t count)
416{
417 struct vio_dev *viod = to_vio_dev(dev);
418 struct hvcs_struct *hvcsd = from_vio_dev(viod);
419 unsigned long flags;
420
421 /* writing a '0' to this sysfs entry will result in the disconnect. */
422 if (simple_strtol(buf, NULL, 0) != 0)
423 return -EINVAL;
424
425 spin_lock_irqsave(&hvcsd->lock, flags);
426
427 if (hvcsd->open_count > 0) {
428 spin_unlock_irqrestore(&hvcsd->lock, flags);
429 printk(KERN_INFO "HVCS: vterm state unchanged. "
430 "The hvcs device node is still in use.\n");
431 return -EPERM;
432 }
433
434 if (hvcsd->connected == 0) {
435 spin_unlock_irqrestore(&hvcsd->lock, flags);
436 printk(KERN_INFO "HVCS: vterm state unchanged. The"
437 " vty-server is not connected to a vty.\n");
438 return -EPERM;
439 }
440
441 hvcs_partner_free(hvcsd);
442 printk(KERN_INFO "HVCS: Closed vty-server@%X and"
443 " partner vty@%X:%d connection.\n",
444 hvcsd->vdev->unit_address,
445 hvcsd->p_unit_address,
446 (uint32_t)hvcsd->p_partition_ID);
447
448 spin_unlock_irqrestore(&hvcsd->lock, flags);
449 return count;
450}
451
452static ssize_t hvcs_vterm_state_show(struct device *dev, struct device_attribute *attr, char *buf)
453{
454 struct vio_dev *viod = to_vio_dev(dev);
455 struct hvcs_struct *hvcsd = from_vio_dev(viod);
456 unsigned long flags;
457 int retval;
458
459 spin_lock_irqsave(&hvcsd->lock, flags);
460 retval = sprintf(buf, "%d\n", hvcsd->connected);
461 spin_unlock_irqrestore(&hvcsd->lock, flags);
462 return retval;
463}
464static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR,
465 hvcs_vterm_state_show, hvcs_vterm_state_store);
466
467static ssize_t hvcs_index_show(struct device *dev, struct device_attribute *attr, char *buf)
468{
469 struct vio_dev *viod = to_vio_dev(dev);
470 struct hvcs_struct *hvcsd = from_vio_dev(viod);
471 unsigned long flags;
472 int retval;
473
474 spin_lock_irqsave(&hvcsd->lock, flags);
475 retval = sprintf(buf, "%d\n", hvcsd->index);
476 spin_unlock_irqrestore(&hvcsd->lock, flags);
477 return retval;
478}
479
480static DEVICE_ATTR(index, S_IRUGO, hvcs_index_show, NULL);
481
482static struct attribute *hvcs_attrs[] = {
483 &dev_attr_partner_vtys.attr,
484 &dev_attr_partner_clcs.attr,
485 &dev_attr_current_vty.attr,
486 &dev_attr_vterm_state.attr,
487 &dev_attr_index.attr,
488 NULL,
489};
490
491static struct attribute_group hvcs_attr_group = {
492 .attrs = hvcs_attrs,
493};
494
495static ssize_t hvcs_rescan_show(struct device_driver *ddp, char *buf)
496{
497 /* A 1 means it is updating, a 0 means it is done updating */
498 return snprintf(buf, PAGE_SIZE, "%d\n", hvcs_rescan_status);
499}
500
501static ssize_t hvcs_rescan_store(struct device_driver *ddp, const char * buf,
502 size_t count)
503{
504 if ((simple_strtol(buf, NULL, 0) != 1)
505 && (hvcs_rescan_status != 0))
506 return -EINVAL;
507
508 hvcs_rescan_status = 1;
509 printk(KERN_INFO "HVCS: rescanning partner info for all"
510 " vty-servers.\n");
511 hvcs_rescan_devices_list();
512 hvcs_rescan_status = 0;
513 return count;
514}
515
516static DRIVER_ATTR(rescan,
517 S_IRUGO | S_IWUSR, hvcs_rescan_show, hvcs_rescan_store);
518
356static void hvcs_kick(void) 519static void hvcs_kick(void)
357{ 520{
358 hvcs_kicked = 1; 521 hvcs_kicked = 1;
@@ -575,7 +738,7 @@ static void destroy_hvcs_struct(struct kobject *kobj)
575 spin_unlock_irqrestore(&hvcsd->lock, flags); 738 spin_unlock_irqrestore(&hvcsd->lock, flags);
576 spin_unlock(&hvcs_structs_lock); 739 spin_unlock(&hvcs_structs_lock);
577 740
578 hvcs_remove_device_attrs(vdev); 741 sysfs_remove_group(&vdev->dev.kobj, &hvcs_attr_group);
579 742
580 kfree(hvcsd); 743 kfree(hvcsd);
581} 744}
@@ -608,6 +771,7 @@ static int __devinit hvcs_probe(
608{ 771{
609 struct hvcs_struct *hvcsd; 772 struct hvcs_struct *hvcsd;
610 int index; 773 int index;
774 int retval;
611 775
612 if (!dev || !id) { 776 if (!dev || !id) {
613 printk(KERN_ERR "HVCS: probed with invalid parameter.\n"); 777 printk(KERN_ERR "HVCS: probed with invalid parameter.\n");
@@ -658,14 +822,16 @@ static int __devinit hvcs_probe(
658 * the hvcs_struct has been added to the devices list then the user app 822 * the hvcs_struct has been added to the devices list then the user app
659 * will get -ENODEV. 823 * will get -ENODEV.
660 */ 824 */
661
662 spin_lock(&hvcs_structs_lock); 825 spin_lock(&hvcs_structs_lock);
663
664 list_add_tail(&(hvcsd->next), &hvcs_structs); 826 list_add_tail(&(hvcsd->next), &hvcs_structs);
665
666 spin_unlock(&hvcs_structs_lock); 827 spin_unlock(&hvcs_structs_lock);
667 828
668 hvcs_create_device_attrs(hvcsd); 829 retval = sysfs_create_group(&dev->dev.kobj, &hvcs_attr_group);
830 if (retval) {
831 printk(KERN_ERR "HVCS: Can't create sysfs attrs for vty-server@%X\n",
832 hvcsd->vdev->unit_address);
833 return retval;
834 }
669 835
670 printk(KERN_INFO "HVCS: vty-server@%X added to the vio bus.\n", dev->unit_address); 836 printk(KERN_INFO "HVCS: vty-server@%X added to the vio bus.\n", dev->unit_address);
671 837
@@ -1354,8 +1520,10 @@ static int __init hvcs_module_init(void)
1354 if (!hvcs_tty_driver) 1520 if (!hvcs_tty_driver)
1355 return -ENOMEM; 1521 return -ENOMEM;
1356 1522
1357 if (hvcs_alloc_index_list(num_ttys_to_alloc)) 1523 if (hvcs_alloc_index_list(num_ttys_to_alloc)) {
1358 return -ENOMEM; 1524 rc = -ENOMEM;
1525 goto index_fail;
1526 }
1359 1527
1360 hvcs_tty_driver->owner = THIS_MODULE; 1528 hvcs_tty_driver->owner = THIS_MODULE;
1361 1529
@@ -1385,41 +1553,57 @@ static int __init hvcs_module_init(void)
1385 * dynamically assigned major and minor numbers for our devices. 1553 * dynamically assigned major and minor numbers for our devices.
1386 */ 1554 */
1387 if (tty_register_driver(hvcs_tty_driver)) { 1555 if (tty_register_driver(hvcs_tty_driver)) {
1388 printk(KERN_ERR "HVCS: registration " 1556 printk(KERN_ERR "HVCS: registration as a tty driver failed.\n");
1389 " as a tty driver failed.\n"); 1557 rc = -EIO;
1390 hvcs_free_index_list(); 1558 goto register_fail;
1391 put_tty_driver(hvcs_tty_driver);
1392 return -EIO;
1393 } 1559 }
1394 1560
1395 hvcs_pi_buff = kmalloc(PAGE_SIZE, GFP_KERNEL); 1561 hvcs_pi_buff = kmalloc(PAGE_SIZE, GFP_KERNEL);
1396 if (!hvcs_pi_buff) { 1562 if (!hvcs_pi_buff) {
1397 tty_unregister_driver(hvcs_tty_driver); 1563 rc = -ENOMEM;
1398 hvcs_free_index_list(); 1564 goto buff_alloc_fail;
1399 put_tty_driver(hvcs_tty_driver);
1400 return -ENOMEM;
1401 } 1565 }
1402 1566
1403 hvcs_task = kthread_run(khvcsd, NULL, "khvcsd"); 1567 hvcs_task = kthread_run(khvcsd, NULL, "khvcsd");
1404 if (IS_ERR(hvcs_task)) { 1568 if (IS_ERR(hvcs_task)) {
1405 printk(KERN_ERR "HVCS: khvcsd creation failed. Driver not loaded.\n"); 1569 printk(KERN_ERR "HVCS: khvcsd creation failed. Driver not loaded.\n");
1406 kfree(hvcs_pi_buff); 1570 rc = -EIO;
1407 tty_unregister_driver(hvcs_tty_driver); 1571 goto kthread_fail;
1408 hvcs_free_index_list();
1409 put_tty_driver(hvcs_tty_driver);
1410 return -EIO;
1411 } 1572 }
1412 1573
1413 rc = vio_register_driver(&hvcs_vio_driver); 1574 rc = vio_register_driver(&hvcs_vio_driver);
1575 if (rc) {
1576 printk(KERN_ERR "HVCS: can't register vio driver\n");
1577 goto vio_fail;
1578 }
1414 1579
1415 /* 1580 /*
1416 * This needs to be done AFTER the vio_register_driver() call or else 1581 * This needs to be done AFTER the vio_register_driver() call or else
1417 * the kobjects won't be initialized properly. 1582 * the kobjects won't be initialized properly.
1418 */ 1583 */
1419 hvcs_create_driver_attrs(); 1584 rc = driver_create_file(&(hvcs_vio_driver.driver), &driver_attr_rescan);
1585 if (rc) {
1586 printk(KERN_ERR "HVCS: sysfs attr create failed\n");
1587 goto attr_fail;
1588 }
1420 1589
1421 printk(KERN_INFO "HVCS: driver module inserted.\n"); 1590 printk(KERN_INFO "HVCS: driver module inserted.\n");
1422 1591
1592 return 0;
1593
1594attr_fail:
1595 vio_unregister_driver(&hvcs_vio_driver);
1596vio_fail:
1597 kthread_stop(hvcs_task);
1598kthread_fail:
1599 kfree(hvcs_pi_buff);
1600buff_alloc_fail:
1601 tty_unregister_driver(hvcs_tty_driver);
1602register_fail:
1603 hvcs_free_index_list();
1604index_fail:
1605 put_tty_driver(hvcs_tty_driver);
1606 hvcs_tty_driver = NULL;
1423 return rc; 1607 return rc;
1424} 1608}
1425 1609
@@ -1441,7 +1625,7 @@ static void __exit hvcs_module_exit(void)
1441 hvcs_pi_buff = NULL; 1625 hvcs_pi_buff = NULL;
1442 spin_unlock(&hvcs_pi_lock); 1626 spin_unlock(&hvcs_pi_lock);
1443 1627
1444 hvcs_remove_driver_attrs(); 1628 driver_remove_file(&hvcs_vio_driver.driver, &driver_attr_rescan);
1445 1629
1446 vio_unregister_driver(&hvcs_vio_driver); 1630 vio_unregister_driver(&hvcs_vio_driver);
1447 1631
@@ -1456,191 +1640,3 @@ static void __exit hvcs_module_exit(void)
1456 1640
1457module_init(hvcs_module_init); 1641module_init(hvcs_module_init);
1458module_exit(hvcs_module_exit); 1642module_exit(hvcs_module_exit);
1459
1460static 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
1466static 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}
1478static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL);
1479
1480static 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}
1492static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL);
1493
1494static 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
1505static 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
1518static DEVICE_ATTR(current_vty,
1519 S_IRUGO | S_IWUSR, hvcs_current_vty_show, hvcs_current_vty_store);
1520
1521static 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
1559static 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}
1571static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR,
1572 hvcs_vterm_state_show, hvcs_vterm_state_store);
1573
1574static 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
1587static DEVICE_ATTR(index, S_IRUGO, hvcs_index_show, NULL);
1588
1589static 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
1598static struct attribute_group hvcs_attr_group = {
1599 .attrs = hvcs_attrs,
1600};
1601
1602static 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
1608static void hvcs_remove_device_attrs(struct vio_dev *vdev)
1609{
1610 sysfs_remove_group(&vdev->dev.kobj, &hvcs_attr_group);
1611}
1612
1613static 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
1619static 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}
1633static DRIVER_ATTR(rescan,
1634 S_IRUGO | S_IWUSR, hvcs_rescan_show, hvcs_rescan_store);
1635
1636static 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
1642static 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}