diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/virtio_console.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index fae2dbbf5745..72d7028f779b 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -142,6 +142,7 @@ struct ports_device { | |||
142 | * notification | 142 | * notification |
143 | */ | 143 | */ |
144 | struct work_struct control_work; | 144 | struct work_struct control_work; |
145 | struct work_struct config_work; | ||
145 | 146 | ||
146 | struct list_head ports; | 147 | struct list_head ports; |
147 | 148 | ||
@@ -1837,10 +1838,21 @@ static void config_intr(struct virtio_device *vdev) | |||
1837 | 1838 | ||
1838 | portdev = vdev->priv; | 1839 | portdev = vdev->priv; |
1839 | 1840 | ||
1841 | if (!use_multiport(portdev)) | ||
1842 | schedule_work(&portdev->config_work); | ||
1843 | } | ||
1844 | |||
1845 | static void config_work_handler(struct work_struct *work) | ||
1846 | { | ||
1847 | struct ports_device *portdev; | ||
1848 | |||
1849 | portdev = container_of(work, struct ports_device, control_work); | ||
1840 | if (!use_multiport(portdev)) { | 1850 | if (!use_multiport(portdev)) { |
1851 | struct virtio_device *vdev; | ||
1841 | struct port *port; | 1852 | struct port *port; |
1842 | u16 rows, cols; | 1853 | u16 rows, cols; |
1843 | 1854 | ||
1855 | vdev = portdev->vdev; | ||
1844 | virtio_cread(vdev, struct virtio_console_config, cols, &cols); | 1856 | virtio_cread(vdev, struct virtio_console_config, cols, &cols); |
1845 | virtio_cread(vdev, struct virtio_console_config, rows, &rows); | 1857 | virtio_cread(vdev, struct virtio_console_config, rows, &rows); |
1846 | 1858 | ||
@@ -2040,12 +2052,14 @@ static int virtcons_probe(struct virtio_device *vdev) | |||
2040 | 2052 | ||
2041 | virtio_device_ready(portdev->vdev); | 2053 | virtio_device_ready(portdev->vdev); |
2042 | 2054 | ||
2055 | INIT_WORK(&portdev->config_work, &config_work_handler); | ||
2056 | INIT_WORK(&portdev->control_work, &control_work_handler); | ||
2057 | |||
2043 | if (multiport) { | 2058 | if (multiport) { |
2044 | unsigned int nr_added_bufs; | 2059 | unsigned int nr_added_bufs; |
2045 | 2060 | ||
2046 | spin_lock_init(&portdev->c_ivq_lock); | 2061 | spin_lock_init(&portdev->c_ivq_lock); |
2047 | spin_lock_init(&portdev->c_ovq_lock); | 2062 | spin_lock_init(&portdev->c_ovq_lock); |
2048 | INIT_WORK(&portdev->control_work, &control_work_handler); | ||
2049 | 2063 | ||
2050 | nr_added_bufs = fill_queue(portdev->c_ivq, | 2064 | nr_added_bufs = fill_queue(portdev->c_ivq, |
2051 | &portdev->c_ivq_lock); | 2065 | &portdev->c_ivq_lock); |
@@ -2113,6 +2127,8 @@ static void virtcons_remove(struct virtio_device *vdev) | |||
2113 | /* Finish up work that's lined up */ | 2127 | /* Finish up work that's lined up */ |
2114 | if (use_multiport(portdev)) | 2128 | if (use_multiport(portdev)) |
2115 | cancel_work_sync(&portdev->control_work); | 2129 | cancel_work_sync(&portdev->control_work); |
2130 | else | ||
2131 | cancel_work_sync(&portdev->config_work); | ||
2116 | 2132 | ||
2117 | list_for_each_entry_safe(port, port2, &portdev->ports, list) | 2133 | list_for_each_entry_safe(port, port2, &portdev->ports, list) |
2118 | unplug_port(port); | 2134 | unplug_port(port); |
@@ -2164,6 +2180,7 @@ static int virtcons_freeze(struct virtio_device *vdev) | |||
2164 | 2180 | ||
2165 | virtqueue_disable_cb(portdev->c_ivq); | 2181 | virtqueue_disable_cb(portdev->c_ivq); |
2166 | cancel_work_sync(&portdev->control_work); | 2182 | cancel_work_sync(&portdev->control_work); |
2183 | cancel_work_sync(&portdev->config_work); | ||
2167 | /* | 2184 | /* |
2168 | * Once more: if control_work_handler() was running, it would | 2185 | * Once more: if control_work_handler() was running, it would |
2169 | * enable the cb as the last step. | 2186 | * enable the cb as the last step. |