diff options
author | Amit Shah <amit.shah@redhat.com> | 2009-12-21 11:27:40 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2010-02-23 22:52:56 -0500 |
commit | 431edb8a8bca71008fefceadf53b9315ef7196ec (patch) | |
tree | def6892310b7a09ecf6bfbc01dc3cd0a2819fca7 /drivers/char/virtio_console.c | |
parent | 3c7969ccb569968a79fab3729075751bc8fc2f78 (diff) |
virtio: console: Register with sysfs and create a 'name' attribute for ports
The host can set a name for ports so that they're easily discoverable
instead of going by the /dev/vportNpn naming. This attribute will be
placed in /sys/class/virtio-ports/vportNpn/name. udev scripts can then
create symlinks to the port using the name.
Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/char/virtio_console.c')
-rw-r--r-- | drivers/char/virtio_console.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 5e3503a31312..99d182b132c4 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -170,6 +170,9 @@ struct port { | |||
170 | /* A waitqueue for poll() or blocking read operations */ | 170 | /* A waitqueue for poll() or blocking read operations */ |
171 | wait_queue_head_t waitqueue; | 171 | wait_queue_head_t waitqueue; |
172 | 172 | ||
173 | /* The 'name' of the port that we expose via sysfs properties */ | ||
174 | char *name; | ||
175 | |||
173 | /* The 'id' to identify the port with the Host */ | 176 | /* The 'id' to identify the port with the Host */ |
174 | u32 id; | 177 | u32 id; |
175 | 178 | ||
@@ -732,12 +735,36 @@ int init_port_console(struct port *port) | |||
732 | return 0; | 735 | return 0; |
733 | } | 736 | } |
734 | 737 | ||
738 | static ssize_t show_port_name(struct device *dev, | ||
739 | struct device_attribute *attr, char *buffer) | ||
740 | { | ||
741 | struct port *port; | ||
742 | |||
743 | port = dev_get_drvdata(dev); | ||
744 | |||
745 | return sprintf(buffer, "%s\n", port->name); | ||
746 | } | ||
747 | |||
748 | static DEVICE_ATTR(name, S_IRUGO, show_port_name, NULL); | ||
749 | |||
750 | static struct attribute *port_sysfs_entries[] = { | ||
751 | &dev_attr_name.attr, | ||
752 | NULL | ||
753 | }; | ||
754 | |||
755 | static struct attribute_group port_attribute_group = { | ||
756 | .name = NULL, /* put in device directory */ | ||
757 | .attrs = port_sysfs_entries, | ||
758 | }; | ||
759 | |||
735 | /* Any private messages that the Host and Guest want to share */ | 760 | /* Any private messages that the Host and Guest want to share */ |
736 | static void handle_control_message(struct ports_device *portdev, | 761 | static void handle_control_message(struct ports_device *portdev, |
737 | struct port_buffer *buf) | 762 | struct port_buffer *buf) |
738 | { | 763 | { |
739 | struct virtio_console_control *cpkt; | 764 | struct virtio_console_control *cpkt; |
740 | struct port *port; | 765 | struct port *port; |
766 | size_t name_size; | ||
767 | int err; | ||
741 | 768 | ||
742 | cpkt = (struct virtio_console_control *)(buf->buf + buf->offset); | 769 | cpkt = (struct virtio_console_control *)(buf->buf + buf->offset); |
743 | 770 | ||
@@ -772,6 +799,35 @@ static void handle_control_message(struct ports_device *portdev, | |||
772 | port->host_connected = cpkt->value; | 799 | port->host_connected = cpkt->value; |
773 | wake_up_interruptible(&port->waitqueue); | 800 | wake_up_interruptible(&port->waitqueue); |
774 | break; | 801 | break; |
802 | case VIRTIO_CONSOLE_PORT_NAME: | ||
803 | /* | ||
804 | * Skip the size of the header and the cpkt to get the size | ||
805 | * of the name that was sent | ||
806 | */ | ||
807 | name_size = buf->len - buf->offset - sizeof(*cpkt) + 1; | ||
808 | |||
809 | port->name = kmalloc(name_size, GFP_KERNEL); | ||
810 | if (!port->name) { | ||
811 | dev_err(port->dev, | ||
812 | "Not enough space to store port name\n"); | ||
813 | break; | ||
814 | } | ||
815 | strncpy(port->name, buf->buf + buf->offset + sizeof(*cpkt), | ||
816 | name_size - 1); | ||
817 | port->name[name_size - 1] = 0; | ||
818 | |||
819 | /* | ||
820 | * Since we only have one sysfs attribute, 'name', | ||
821 | * create it only if we have a name for the port. | ||
822 | */ | ||
823 | err = sysfs_create_group(&port->dev->kobj, | ||
824 | &port_attribute_group); | ||
825 | if (err) | ||
826 | dev_err(port->dev, | ||
827 | "Error %d creating sysfs device attributes\n", | ||
828 | err); | ||
829 | |||
830 | break; | ||
775 | } | 831 | } |
776 | } | 832 | } |
777 | 833 | ||
@@ -869,6 +925,7 @@ static int add_port(struct ports_device *portdev, u32 id) | |||
869 | port->portdev = portdev; | 925 | port->portdev = portdev; |
870 | port->id = id; | 926 | port->id = id; |
871 | 927 | ||
928 | port->name = NULL; | ||
872 | port->inbuf = NULL; | 929 | port->inbuf = NULL; |
873 | port->cons.hvc = NULL; | 930 | port->cons.hvc = NULL; |
874 | 931 | ||