diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/agp/Kconfig | 2 | ||||
-rw-r--r-- | drivers/char/agp/amd64-agp.c | 39 | ||||
-rw-r--r-- | drivers/char/agp/generic.c | 4 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.c | 22 | ||||
-rw-r--r-- | drivers/char/virtio_console.c | 240 |
5 files changed, 247 insertions, 60 deletions
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index 4b66c69eaf57..5ddf67e76f8b 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig | |||
@@ -57,7 +57,7 @@ config AGP_AMD | |||
57 | 57 | ||
58 | config AGP_AMD64 | 58 | config AGP_AMD64 |
59 | tristate "AMD Opteron/Athlon64 on-CPU GART support" | 59 | tristate "AMD Opteron/Athlon64 on-CPU GART support" |
60 | depends on AGP && X86 && K8_NB | 60 | depends on AGP && X86 && AMD_NB |
61 | help | 61 | help |
62 | This option gives you AGP support for the GLX component of | 62 | This option gives you AGP support for the GLX component of |
63 | X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs. | 63 | X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs. |
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 70312da4c968..42396df55556 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/mmzone.h> | 15 | #include <linux/mmzone.h> |
16 | #include <asm/page.h> /* PAGE_SIZE */ | 16 | #include <asm/page.h> /* PAGE_SIZE */ |
17 | #include <asm/e820.h> | 17 | #include <asm/e820.h> |
18 | #include <asm/k8.h> | 18 | #include <asm/amd_nb.h> |
19 | #include <asm/gart.h> | 19 | #include <asm/gart.h> |
20 | #include "agp.h" | 20 | #include "agp.h" |
21 | 21 | ||
@@ -124,7 +124,7 @@ static int amd64_fetch_size(void) | |||
124 | u32 temp; | 124 | u32 temp; |
125 | struct aper_size_info_32 *values; | 125 | struct aper_size_info_32 *values; |
126 | 126 | ||
127 | dev = k8_northbridges[0]; | 127 | dev = k8_northbridges.nb_misc[0]; |
128 | if (dev==NULL) | 128 | if (dev==NULL) |
129 | return 0; | 129 | return 0; |
130 | 130 | ||
@@ -181,10 +181,14 @@ static int amd_8151_configure(void) | |||
181 | unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real); | 181 | unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real); |
182 | int i; | 182 | int i; |
183 | 183 | ||
184 | if (!k8_northbridges.gart_supported) | ||
185 | return 0; | ||
186 | |||
184 | /* Configure AGP regs in each x86-64 host bridge. */ | 187 | /* Configure AGP regs in each x86-64 host bridge. */ |
185 | for (i = 0; i < num_k8_northbridges; i++) { | 188 | for (i = 0; i < k8_northbridges.num; i++) { |
186 | agp_bridge->gart_bus_addr = | 189 | agp_bridge->gart_bus_addr = |
187 | amd64_configure(k8_northbridges[i], gatt_bus); | 190 | amd64_configure(k8_northbridges.nb_misc[i], |
191 | gatt_bus); | ||
188 | } | 192 | } |
189 | k8_flush_garts(); | 193 | k8_flush_garts(); |
190 | return 0; | 194 | return 0; |
@@ -195,11 +199,15 @@ static void amd64_cleanup(void) | |||
195 | { | 199 | { |
196 | u32 tmp; | 200 | u32 tmp; |
197 | int i; | 201 | int i; |
198 | for (i = 0; i < num_k8_northbridges; i++) { | 202 | |
199 | struct pci_dev *dev = k8_northbridges[i]; | 203 | if (!k8_northbridges.gart_supported) |
204 | return; | ||
205 | |||
206 | for (i = 0; i < k8_northbridges.num; i++) { | ||
207 | struct pci_dev *dev = k8_northbridges.nb_misc[i]; | ||
200 | /* disable gart translation */ | 208 | /* disable gart translation */ |
201 | pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &tmp); | 209 | pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &tmp); |
202 | tmp &= ~AMD64_GARTEN; | 210 | tmp &= ~GARTEN; |
203 | pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, tmp); | 211 | pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, tmp); |
204 | } | 212 | } |
205 | } | 213 | } |
@@ -313,22 +321,25 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, | |||
313 | if (order < 0 || !agp_aperture_valid(aper, (32*1024*1024)<<order)) | 321 | if (order < 0 || !agp_aperture_valid(aper, (32*1024*1024)<<order)) |
314 | return -1; | 322 | return -1; |
315 | 323 | ||
316 | pci_write_config_dword(nb, AMD64_GARTAPERTURECTL, order << 1); | 324 | gart_set_size_and_enable(nb, order); |
317 | pci_write_config_dword(nb, AMD64_GARTAPERTUREBASE, aper >> 25); | 325 | pci_write_config_dword(nb, AMD64_GARTAPERTUREBASE, aper >> 25); |
318 | 326 | ||
319 | return 0; | 327 | return 0; |
320 | } | 328 | } |
321 | 329 | ||
322 | static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) | 330 | static __devinit int cache_nbs(struct pci_dev *pdev, u32 cap_ptr) |
323 | { | 331 | { |
324 | int i; | 332 | int i; |
325 | 333 | ||
326 | if (cache_k8_northbridges() < 0) | 334 | if (cache_k8_northbridges() < 0) |
327 | return -ENODEV; | 335 | return -ENODEV; |
328 | 336 | ||
337 | if (!k8_northbridges.gart_supported) | ||
338 | return -ENODEV; | ||
339 | |||
329 | i = 0; | 340 | i = 0; |
330 | for (i = 0; i < num_k8_northbridges; i++) { | 341 | for (i = 0; i < k8_northbridges.num; i++) { |
331 | struct pci_dev *dev = k8_northbridges[i]; | 342 | struct pci_dev *dev = k8_northbridges.nb_misc[i]; |
332 | if (fix_northbridge(dev, pdev, cap_ptr) < 0) { | 343 | if (fix_northbridge(dev, pdev, cap_ptr) < 0) { |
333 | dev_err(&dev->dev, "no usable aperture found\n"); | 344 | dev_err(&dev->dev, "no usable aperture found\n"); |
334 | #ifdef __x86_64__ | 345 | #ifdef __x86_64__ |
@@ -405,7 +416,8 @@ static int __devinit uli_agp_init(struct pci_dev *pdev) | |||
405 | } | 416 | } |
406 | 417 | ||
407 | /* shadow x86-64 registers into ULi registers */ | 418 | /* shadow x86-64 registers into ULi registers */ |
408 | pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &httfea); | 419 | pci_read_config_dword (k8_northbridges.nb_misc[0], AMD64_GARTAPERTUREBASE, |
420 | &httfea); | ||
409 | 421 | ||
410 | /* if x86-64 aperture base is beyond 4G, exit here */ | 422 | /* if x86-64 aperture base is beyond 4G, exit here */ |
411 | if ((httfea & 0x7fff) >> (32 - 25)) { | 423 | if ((httfea & 0x7fff) >> (32 - 25)) { |
@@ -472,7 +484,8 @@ static int nforce3_agp_init(struct pci_dev *pdev) | |||
472 | pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp); | 484 | pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp); |
473 | 485 | ||
474 | /* shadow x86-64 registers into NVIDIA registers */ | 486 | /* shadow x86-64 registers into NVIDIA registers */ |
475 | pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &apbase); | 487 | pci_read_config_dword (k8_northbridges.nb_misc[0], AMD64_GARTAPERTUREBASE, |
488 | &apbase); | ||
476 | 489 | ||
477 | /* if x86-64 aperture base is beyond 4G, exit here */ | 490 | /* if x86-64 aperture base is beyond 4G, exit here */ |
478 | if ( (apbase & 0x7fff) >> (32 - 25) ) { | 491 | if ( (apbase & 0x7fff) >> (32 - 25) ) { |
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index d2abf5143983..64255cef8a7d 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c | |||
@@ -984,7 +984,9 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge) | |||
984 | 984 | ||
985 | bridge->driver->cache_flush(); | 985 | bridge->driver->cache_flush(); |
986 | #ifdef CONFIG_X86 | 986 | #ifdef CONFIG_X86 |
987 | set_memory_uc((unsigned long)table, 1 << page_order); | 987 | if (set_memory_uc((unsigned long)table, 1 << page_order)) |
988 | printk(KERN_WARNING "Could not set GATT table memory to UC!"); | ||
989 | |||
988 | bridge->gatt_table = (void *)table; | 990 | bridge->gatt_table = (void *)table; |
989 | #else | 991 | #else |
990 | bridge->gatt_table = ioremap_nocache(virt_to_phys(table), | 992 | bridge->gatt_table = ioremap_nocache(virt_to_phys(table), |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 05ad4a17a28f..7c4133582dba 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -47,6 +47,16 @@ enum tpm_duration { | |||
47 | #define TPM_MAX_PROTECTED_ORDINAL 12 | 47 | #define TPM_MAX_PROTECTED_ORDINAL 12 |
48 | #define TPM_PROTECTED_ORDINAL_MASK 0xFF | 48 | #define TPM_PROTECTED_ORDINAL_MASK 0xFF |
49 | 49 | ||
50 | /* | ||
51 | * Bug workaround - some TPM's don't flush the most | ||
52 | * recently changed pcr on suspend, so force the flush | ||
53 | * with an extend to the selected _unused_ non-volatile pcr. | ||
54 | */ | ||
55 | static int tpm_suspend_pcr; | ||
56 | module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644); | ||
57 | MODULE_PARM_DESC(suspend_pcr, | ||
58 | "PCR to use for dummy writes to faciltate flush on suspend."); | ||
59 | |||
50 | static LIST_HEAD(tpm_chip_list); | 60 | static LIST_HEAD(tpm_chip_list); |
51 | static DEFINE_SPINLOCK(driver_lock); | 61 | static DEFINE_SPINLOCK(driver_lock); |
52 | static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); | 62 | static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); |
@@ -1077,18 +1087,6 @@ static struct tpm_input_header savestate_header = { | |||
1077 | .ordinal = TPM_ORD_SAVESTATE | 1087 | .ordinal = TPM_ORD_SAVESTATE |
1078 | }; | 1088 | }; |
1079 | 1089 | ||
1080 | /* Bug workaround - some TPM's don't flush the most | ||
1081 | * recently changed pcr on suspend, so force the flush | ||
1082 | * with an extend to the selected _unused_ non-volatile pcr. | ||
1083 | */ | ||
1084 | static int tpm_suspend_pcr; | ||
1085 | static int __init tpm_suspend_setup(char *str) | ||
1086 | { | ||
1087 | get_option(&str, &tpm_suspend_pcr); | ||
1088 | return 1; | ||
1089 | } | ||
1090 | __setup("tpm_suspend_pcr=", tpm_suspend_setup); | ||
1091 | |||
1092 | /* | 1090 | /* |
1093 | * We are about to suspend. Save the TPM state | 1091 | * We are about to suspend. Save the TPM state |
1094 | * so that it can be restored. | 1092 | * so that it can be restored. |
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 0f69c5ec0ecd..6c1b676643a9 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -48,6 +48,9 @@ struct ports_driver_data { | |||
48 | /* Used for exporting per-port information to debugfs */ | 48 | /* Used for exporting per-port information to debugfs */ |
49 | struct dentry *debugfs_dir; | 49 | struct dentry *debugfs_dir; |
50 | 50 | ||
51 | /* List of all the devices we're handling */ | ||
52 | struct list_head portdevs; | ||
53 | |||
51 | /* Number of devices this driver is handling */ | 54 | /* Number of devices this driver is handling */ |
52 | unsigned int index; | 55 | unsigned int index; |
53 | 56 | ||
@@ -108,6 +111,9 @@ struct port_buffer { | |||
108 | * ports for that device (vdev->priv). | 111 | * ports for that device (vdev->priv). |
109 | */ | 112 | */ |
110 | struct ports_device { | 113 | struct ports_device { |
114 | /* Next portdev in the list, head is in the pdrvdata struct */ | ||
115 | struct list_head list; | ||
116 | |||
111 | /* | 117 | /* |
112 | * Workqueue handlers where we process deferred work after | 118 | * Workqueue handlers where we process deferred work after |
113 | * notification | 119 | * notification |
@@ -178,15 +184,21 @@ struct port { | |||
178 | struct console cons; | 184 | struct console cons; |
179 | 185 | ||
180 | /* Each port associates with a separate char device */ | 186 | /* Each port associates with a separate char device */ |
181 | struct cdev cdev; | 187 | struct cdev *cdev; |
182 | struct device *dev; | 188 | struct device *dev; |
183 | 189 | ||
190 | /* Reference-counting to handle port hot-unplugs and file operations */ | ||
191 | struct kref kref; | ||
192 | |||
184 | /* A waitqueue for poll() or blocking read operations */ | 193 | /* A waitqueue for poll() or blocking read operations */ |
185 | wait_queue_head_t waitqueue; | 194 | wait_queue_head_t waitqueue; |
186 | 195 | ||
187 | /* The 'name' of the port that we expose via sysfs properties */ | 196 | /* The 'name' of the port that we expose via sysfs properties */ |
188 | char *name; | 197 | char *name; |
189 | 198 | ||
199 | /* We can notify apps of host connect / disconnect events via SIGIO */ | ||
200 | struct fasync_struct *async_queue; | ||
201 | |||
190 | /* The 'id' to identify the port with the Host */ | 202 | /* The 'id' to identify the port with the Host */ |
191 | u32 id; | 203 | u32 id; |
192 | 204 | ||
@@ -221,6 +233,41 @@ out: | |||
221 | return port; | 233 | return port; |
222 | } | 234 | } |
223 | 235 | ||
236 | static struct port *find_port_by_devt_in_portdev(struct ports_device *portdev, | ||
237 | dev_t dev) | ||
238 | { | ||
239 | struct port *port; | ||
240 | unsigned long flags; | ||
241 | |||
242 | spin_lock_irqsave(&portdev->ports_lock, flags); | ||
243 | list_for_each_entry(port, &portdev->ports, list) | ||
244 | if (port->cdev->dev == dev) | ||
245 | goto out; | ||
246 | port = NULL; | ||
247 | out: | ||
248 | spin_unlock_irqrestore(&portdev->ports_lock, flags); | ||
249 | |||
250 | return port; | ||
251 | } | ||
252 | |||
253 | static struct port *find_port_by_devt(dev_t dev) | ||
254 | { | ||
255 | struct ports_device *portdev; | ||
256 | struct port *port; | ||
257 | unsigned long flags; | ||
258 | |||
259 | spin_lock_irqsave(&pdrvdata_lock, flags); | ||
260 | list_for_each_entry(portdev, &pdrvdata.portdevs, list) { | ||
261 | port = find_port_by_devt_in_portdev(portdev, dev); | ||
262 | if (port) | ||
263 | goto out; | ||
264 | } | ||
265 | port = NULL; | ||
266 | out: | ||
267 | spin_unlock_irqrestore(&pdrvdata_lock, flags); | ||
268 | return port; | ||
269 | } | ||
270 | |||
224 | static struct port *find_port_by_id(struct ports_device *portdev, u32 id) | 271 | static struct port *find_port_by_id(struct ports_device *portdev, u32 id) |
225 | { | 272 | { |
226 | struct port *port; | 273 | struct port *port; |
@@ -410,7 +457,10 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id, | |||
410 | static ssize_t send_control_msg(struct port *port, unsigned int event, | 457 | static ssize_t send_control_msg(struct port *port, unsigned int event, |
411 | unsigned int value) | 458 | unsigned int value) |
412 | { | 459 | { |
413 | return __send_control_msg(port->portdev, port->id, event, value); | 460 | /* Did the port get unplugged before userspace closed it? */ |
461 | if (port->portdev) | ||
462 | return __send_control_msg(port->portdev, port->id, event, value); | ||
463 | return 0; | ||
414 | } | 464 | } |
415 | 465 | ||
416 | /* Callers must take the port->outvq_lock */ | 466 | /* Callers must take the port->outvq_lock */ |
@@ -525,6 +575,10 @@ static ssize_t fill_readbuf(struct port *port, char *out_buf, size_t out_count, | |||
525 | /* The condition that must be true for polling to end */ | 575 | /* The condition that must be true for polling to end */ |
526 | static bool will_read_block(struct port *port) | 576 | static bool will_read_block(struct port *port) |
527 | { | 577 | { |
578 | if (!port->guest_connected) { | ||
579 | /* Port got hot-unplugged. Let's exit. */ | ||
580 | return false; | ||
581 | } | ||
528 | return !port_has_data(port) && port->host_connected; | 582 | return !port_has_data(port) && port->host_connected; |
529 | } | 583 | } |
530 | 584 | ||
@@ -575,6 +629,9 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf, | |||
575 | if (ret < 0) | 629 | if (ret < 0) |
576 | return ret; | 630 | return ret; |
577 | } | 631 | } |
632 | /* Port got hot-unplugged. */ | ||
633 | if (!port->guest_connected) | ||
634 | return -ENODEV; | ||
578 | /* | 635 | /* |
579 | * We could've received a disconnection message while we were | 636 | * We could've received a disconnection message while we were |
580 | * waiting for more data. | 637 | * waiting for more data. |
@@ -616,6 +673,9 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, | |||
616 | if (ret < 0) | 673 | if (ret < 0) |
617 | return ret; | 674 | return ret; |
618 | } | 675 | } |
676 | /* Port got hot-unplugged. */ | ||
677 | if (!port->guest_connected) | ||
678 | return -ENODEV; | ||
619 | 679 | ||
620 | count = min((size_t)(32 * 1024), count); | 680 | count = min((size_t)(32 * 1024), count); |
621 | 681 | ||
@@ -656,6 +716,10 @@ static unsigned int port_fops_poll(struct file *filp, poll_table *wait) | |||
656 | port = filp->private_data; | 716 | port = filp->private_data; |
657 | poll_wait(filp, &port->waitqueue, wait); | 717 | poll_wait(filp, &port->waitqueue, wait); |
658 | 718 | ||
719 | if (!port->guest_connected) { | ||
720 | /* Port got unplugged */ | ||
721 | return POLLHUP; | ||
722 | } | ||
659 | ret = 0; | 723 | ret = 0; |
660 | if (!will_read_block(port)) | 724 | if (!will_read_block(port)) |
661 | ret |= POLLIN | POLLRDNORM; | 725 | ret |= POLLIN | POLLRDNORM; |
@@ -667,6 +731,8 @@ static unsigned int port_fops_poll(struct file *filp, poll_table *wait) | |||
667 | return ret; | 731 | return ret; |
668 | } | 732 | } |
669 | 733 | ||
734 | static void remove_port(struct kref *kref); | ||
735 | |||
670 | static int port_fops_release(struct inode *inode, struct file *filp) | 736 | static int port_fops_release(struct inode *inode, struct file *filp) |
671 | { | 737 | { |
672 | struct port *port; | 738 | struct port *port; |
@@ -687,6 +753,16 @@ static int port_fops_release(struct inode *inode, struct file *filp) | |||
687 | reclaim_consumed_buffers(port); | 753 | reclaim_consumed_buffers(port); |
688 | spin_unlock_irq(&port->outvq_lock); | 754 | spin_unlock_irq(&port->outvq_lock); |
689 | 755 | ||
756 | /* | ||
757 | * Locks aren't necessary here as a port can't be opened after | ||
758 | * unplug, and if a port isn't unplugged, a kref would already | ||
759 | * exist for the port. Plus, taking ports_lock here would | ||
760 | * create a dependency on other locks taken by functions | ||
761 | * inside remove_port if we're the last holder of the port, | ||
762 | * creating many problems. | ||
763 | */ | ||
764 | kref_put(&port->kref, remove_port); | ||
765 | |||
690 | return 0; | 766 | return 0; |
691 | } | 767 | } |
692 | 768 | ||
@@ -694,22 +770,31 @@ static int port_fops_open(struct inode *inode, struct file *filp) | |||
694 | { | 770 | { |
695 | struct cdev *cdev = inode->i_cdev; | 771 | struct cdev *cdev = inode->i_cdev; |
696 | struct port *port; | 772 | struct port *port; |
773 | int ret; | ||
697 | 774 | ||
698 | port = container_of(cdev, struct port, cdev); | 775 | port = find_port_by_devt(cdev->dev); |
699 | filp->private_data = port; | 776 | filp->private_data = port; |
700 | 777 | ||
778 | /* Prevent against a port getting hot-unplugged at the same time */ | ||
779 | spin_lock_irq(&port->portdev->ports_lock); | ||
780 | kref_get(&port->kref); | ||
781 | spin_unlock_irq(&port->portdev->ports_lock); | ||
782 | |||
701 | /* | 783 | /* |
702 | * Don't allow opening of console port devices -- that's done | 784 | * Don't allow opening of console port devices -- that's done |
703 | * via /dev/hvc | 785 | * via /dev/hvc |
704 | */ | 786 | */ |
705 | if (is_console_port(port)) | 787 | if (is_console_port(port)) { |
706 | return -ENXIO; | 788 | ret = -ENXIO; |
789 | goto out; | ||
790 | } | ||
707 | 791 | ||
708 | /* Allow only one process to open a particular port at a time */ | 792 | /* Allow only one process to open a particular port at a time */ |
709 | spin_lock_irq(&port->inbuf_lock); | 793 | spin_lock_irq(&port->inbuf_lock); |
710 | if (port->guest_connected) { | 794 | if (port->guest_connected) { |
711 | spin_unlock_irq(&port->inbuf_lock); | 795 | spin_unlock_irq(&port->inbuf_lock); |
712 | return -EMFILE; | 796 | ret = -EMFILE; |
797 | goto out; | ||
713 | } | 798 | } |
714 | 799 | ||
715 | port->guest_connected = true; | 800 | port->guest_connected = true; |
@@ -724,10 +809,23 @@ static int port_fops_open(struct inode *inode, struct file *filp) | |||
724 | reclaim_consumed_buffers(port); | 809 | reclaim_consumed_buffers(port); |
725 | spin_unlock_irq(&port->outvq_lock); | 810 | spin_unlock_irq(&port->outvq_lock); |
726 | 811 | ||
812 | nonseekable_open(inode, filp); | ||
813 | |||
727 | /* Notify host of port being opened */ | 814 | /* Notify host of port being opened */ |
728 | send_control_msg(filp->private_data, VIRTIO_CONSOLE_PORT_OPEN, 1); | 815 | send_control_msg(filp->private_data, VIRTIO_CONSOLE_PORT_OPEN, 1); |
729 | 816 | ||
730 | return 0; | 817 | return 0; |
818 | out: | ||
819 | kref_put(&port->kref, remove_port); | ||
820 | return ret; | ||
821 | } | ||
822 | |||
823 | static int port_fops_fasync(int fd, struct file *filp, int mode) | ||
824 | { | ||
825 | struct port *port; | ||
826 | |||
827 | port = filp->private_data; | ||
828 | return fasync_helper(fd, filp, mode, &port->async_queue); | ||
731 | } | 829 | } |
732 | 830 | ||
733 | /* | 831 | /* |
@@ -743,6 +841,8 @@ static const struct file_operations port_fops = { | |||
743 | .write = port_fops_write, | 841 | .write = port_fops_write, |
744 | .poll = port_fops_poll, | 842 | .poll = port_fops_poll, |
745 | .release = port_fops_release, | 843 | .release = port_fops_release, |
844 | .fasync = port_fops_fasync, | ||
845 | .llseek = no_llseek, | ||
746 | }; | 846 | }; |
747 | 847 | ||
748 | /* | 848 | /* |
@@ -1001,6 +1101,12 @@ static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock) | |||
1001 | return nr_added_bufs; | 1101 | return nr_added_bufs; |
1002 | } | 1102 | } |
1003 | 1103 | ||
1104 | static void send_sigio_to_port(struct port *port) | ||
1105 | { | ||
1106 | if (port->async_queue && port->guest_connected) | ||
1107 | kill_fasync(&port->async_queue, SIGIO, POLL_OUT); | ||
1108 | } | ||
1109 | |||
1004 | static int add_port(struct ports_device *portdev, u32 id) | 1110 | static int add_port(struct ports_device *portdev, u32 id) |
1005 | { | 1111 | { |
1006 | char debugfs_name[16]; | 1112 | char debugfs_name[16]; |
@@ -1015,6 +1121,7 @@ static int add_port(struct ports_device *portdev, u32 id) | |||
1015 | err = -ENOMEM; | 1121 | err = -ENOMEM; |
1016 | goto fail; | 1122 | goto fail; |
1017 | } | 1123 | } |
1124 | kref_init(&port->kref); | ||
1018 | 1125 | ||
1019 | port->portdev = portdev; | 1126 | port->portdev = portdev; |
1020 | port->id = id; | 1127 | port->id = id; |
@@ -1022,6 +1129,7 @@ static int add_port(struct ports_device *portdev, u32 id) | |||
1022 | port->name = NULL; | 1129 | port->name = NULL; |
1023 | port->inbuf = NULL; | 1130 | port->inbuf = NULL; |
1024 | port->cons.hvc = NULL; | 1131 | port->cons.hvc = NULL; |
1132 | port->async_queue = NULL; | ||
1025 | 1133 | ||
1026 | port->cons.ws.ws_row = port->cons.ws.ws_col = 0; | 1134 | port->cons.ws.ws_row = port->cons.ws.ws_col = 0; |
1027 | 1135 | ||
@@ -1032,14 +1140,20 @@ static int add_port(struct ports_device *portdev, u32 id) | |||
1032 | port->in_vq = portdev->in_vqs[port->id]; | 1140 | port->in_vq = portdev->in_vqs[port->id]; |
1033 | port->out_vq = portdev->out_vqs[port->id]; | 1141 | port->out_vq = portdev->out_vqs[port->id]; |
1034 | 1142 | ||
1035 | cdev_init(&port->cdev, &port_fops); | 1143 | port->cdev = cdev_alloc(); |
1144 | if (!port->cdev) { | ||
1145 | dev_err(&port->portdev->vdev->dev, "Error allocating cdev\n"); | ||
1146 | err = -ENOMEM; | ||
1147 | goto free_port; | ||
1148 | } | ||
1149 | port->cdev->ops = &port_fops; | ||
1036 | 1150 | ||
1037 | devt = MKDEV(portdev->chr_major, id); | 1151 | devt = MKDEV(portdev->chr_major, id); |
1038 | err = cdev_add(&port->cdev, devt, 1); | 1152 | err = cdev_add(port->cdev, devt, 1); |
1039 | if (err < 0) { | 1153 | if (err < 0) { |
1040 | dev_err(&port->portdev->vdev->dev, | 1154 | dev_err(&port->portdev->vdev->dev, |
1041 | "Error %d adding cdev for port %u\n", err, id); | 1155 | "Error %d adding cdev for port %u\n", err, id); |
1042 | goto free_port; | 1156 | goto free_cdev; |
1043 | } | 1157 | } |
1044 | port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev, | 1158 | port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev, |
1045 | devt, port, "vport%up%u", | 1159 | devt, port, "vport%up%u", |
@@ -1104,7 +1218,7 @@ free_inbufs: | |||
1104 | free_device: | 1218 | free_device: |
1105 | device_destroy(pdrvdata.class, port->dev->devt); | 1219 | device_destroy(pdrvdata.class, port->dev->devt); |
1106 | free_cdev: | 1220 | free_cdev: |
1107 | cdev_del(&port->cdev); | 1221 | cdev_del(port->cdev); |
1108 | free_port: | 1222 | free_port: |
1109 | kfree(port); | 1223 | kfree(port); |
1110 | fail: | 1224 | fail: |
@@ -1113,21 +1227,45 @@ fail: | |||
1113 | return err; | 1227 | return err; |
1114 | } | 1228 | } |
1115 | 1229 | ||
1116 | /* Remove all port-specific data. */ | 1230 | /* No users remain, remove all port-specific data. */ |
1117 | static int remove_port(struct port *port) | 1231 | static void remove_port(struct kref *kref) |
1232 | { | ||
1233 | struct port *port; | ||
1234 | |||
1235 | port = container_of(kref, struct port, kref); | ||
1236 | |||
1237 | sysfs_remove_group(&port->dev->kobj, &port_attribute_group); | ||
1238 | device_destroy(pdrvdata.class, port->dev->devt); | ||
1239 | cdev_del(port->cdev); | ||
1240 | |||
1241 | kfree(port->name); | ||
1242 | |||
1243 | debugfs_remove(port->debugfs_file); | ||
1244 | |||
1245 | kfree(port); | ||
1246 | } | ||
1247 | |||
1248 | /* | ||
1249 | * Port got unplugged. Remove port from portdev's list and drop the | ||
1250 | * kref reference. If no userspace has this port opened, it will | ||
1251 | * result in immediate removal the port. | ||
1252 | */ | ||
1253 | static void unplug_port(struct port *port) | ||
1118 | { | 1254 | { |
1119 | struct port_buffer *buf; | 1255 | struct port_buffer *buf; |
1120 | 1256 | ||
1257 | spin_lock_irq(&port->portdev->ports_lock); | ||
1258 | list_del(&port->list); | ||
1259 | spin_unlock_irq(&port->portdev->ports_lock); | ||
1260 | |||
1121 | if (port->guest_connected) { | 1261 | if (port->guest_connected) { |
1122 | port->guest_connected = false; | 1262 | port->guest_connected = false; |
1123 | port->host_connected = false; | 1263 | port->host_connected = false; |
1124 | wake_up_interruptible(&port->waitqueue); | 1264 | wake_up_interruptible(&port->waitqueue); |
1125 | send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0); | ||
1126 | } | ||
1127 | 1265 | ||
1128 | spin_lock_irq(&port->portdev->ports_lock); | 1266 | /* Let the app know the port is going down. */ |
1129 | list_del(&port->list); | 1267 | send_sigio_to_port(port); |
1130 | spin_unlock_irq(&port->portdev->ports_lock); | 1268 | } |
1131 | 1269 | ||
1132 | if (is_console_port(port)) { | 1270 | if (is_console_port(port)) { |
1133 | spin_lock_irq(&pdrvdata_lock); | 1271 | spin_lock_irq(&pdrvdata_lock); |
@@ -1146,9 +1284,6 @@ static int remove_port(struct port *port) | |||
1146 | hvc_remove(port->cons.hvc); | 1284 | hvc_remove(port->cons.hvc); |
1147 | #endif | 1285 | #endif |
1148 | } | 1286 | } |
1149 | sysfs_remove_group(&port->dev->kobj, &port_attribute_group); | ||
1150 | device_destroy(pdrvdata.class, port->dev->devt); | ||
1151 | cdev_del(&port->cdev); | ||
1152 | 1287 | ||
1153 | /* Remove unused data this port might have received. */ | 1288 | /* Remove unused data this port might have received. */ |
1154 | discard_port_data(port); | 1289 | discard_port_data(port); |
@@ -1159,12 +1294,19 @@ static int remove_port(struct port *port) | |||
1159 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) | 1294 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) |
1160 | free_buf(buf); | 1295 | free_buf(buf); |
1161 | 1296 | ||
1162 | kfree(port->name); | 1297 | /* |
1163 | 1298 | * We should just assume the device itself has gone off -- | |
1164 | debugfs_remove(port->debugfs_file); | 1299 | * else a close on an open port later will try to send out a |
1300 | * control message. | ||
1301 | */ | ||
1302 | port->portdev = NULL; | ||
1165 | 1303 | ||
1166 | kfree(port); | 1304 | /* |
1167 | return 0; | 1305 | * Locks around here are not necessary - a port can't be |
1306 | * opened after we removed the port struct from ports_list | ||
1307 | * above. | ||
1308 | */ | ||
1309 | kref_put(&port->kref, remove_port); | ||
1168 | } | 1310 | } |
1169 | 1311 | ||
1170 | /* Any private messages that the Host and Guest want to share */ | 1312 | /* Any private messages that the Host and Guest want to share */ |
@@ -1203,7 +1345,7 @@ static void handle_control_message(struct ports_device *portdev, | |||
1203 | add_port(portdev, cpkt->id); | 1345 | add_port(portdev, cpkt->id); |
1204 | break; | 1346 | break; |
1205 | case VIRTIO_CONSOLE_PORT_REMOVE: | 1347 | case VIRTIO_CONSOLE_PORT_REMOVE: |
1206 | remove_port(port); | 1348 | unplug_port(port); |
1207 | break; | 1349 | break; |
1208 | case VIRTIO_CONSOLE_CONSOLE_PORT: | 1350 | case VIRTIO_CONSOLE_CONSOLE_PORT: |
1209 | if (!cpkt->value) | 1351 | if (!cpkt->value) |
@@ -1245,6 +1387,12 @@ static void handle_control_message(struct ports_device *portdev, | |||
1245 | spin_lock_irq(&port->outvq_lock); | 1387 | spin_lock_irq(&port->outvq_lock); |
1246 | reclaim_consumed_buffers(port); | 1388 | reclaim_consumed_buffers(port); |
1247 | spin_unlock_irq(&port->outvq_lock); | 1389 | spin_unlock_irq(&port->outvq_lock); |
1390 | |||
1391 | /* | ||
1392 | * If the guest is connected, it'll be interested in | ||
1393 | * knowing the host connection state changed. | ||
1394 | */ | ||
1395 | send_sigio_to_port(port); | ||
1248 | break; | 1396 | break; |
1249 | case VIRTIO_CONSOLE_PORT_NAME: | 1397 | case VIRTIO_CONSOLE_PORT_NAME: |
1250 | /* | 1398 | /* |
@@ -1341,6 +1489,9 @@ static void in_intr(struct virtqueue *vq) | |||
1341 | 1489 | ||
1342 | wake_up_interruptible(&port->waitqueue); | 1490 | wake_up_interruptible(&port->waitqueue); |
1343 | 1491 | ||
1492 | /* Send a SIGIO indicating new data in case the process asked for it */ | ||
1493 | send_sigio_to_port(port); | ||
1494 | |||
1344 | if (is_console_port(port) && hvc_poll(port->cons.hvc)) | 1495 | if (is_console_port(port) && hvc_poll(port->cons.hvc)) |
1345 | hvc_kick(); | 1496 | hvc_kick(); |
1346 | } | 1497 | } |
@@ -1577,6 +1728,10 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) | |||
1577 | add_port(portdev, 0); | 1728 | add_port(portdev, 0); |
1578 | } | 1729 | } |
1579 | 1730 | ||
1731 | spin_lock_irq(&pdrvdata_lock); | ||
1732 | list_add_tail(&portdev->list, &pdrvdata.portdevs); | ||
1733 | spin_unlock_irq(&pdrvdata_lock); | ||
1734 | |||
1580 | __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, | 1735 | __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, |
1581 | VIRTIO_CONSOLE_DEVICE_READY, 1); | 1736 | VIRTIO_CONSOLE_DEVICE_READY, 1); |
1582 | return 0; | 1737 | return 0; |
@@ -1600,23 +1755,41 @@ static void virtcons_remove(struct virtio_device *vdev) | |||
1600 | { | 1755 | { |
1601 | struct ports_device *portdev; | 1756 | struct ports_device *portdev; |
1602 | struct port *port, *port2; | 1757 | struct port *port, *port2; |
1603 | struct port_buffer *buf; | ||
1604 | unsigned int len; | ||
1605 | 1758 | ||
1606 | portdev = vdev->priv; | 1759 | portdev = vdev->priv; |
1607 | 1760 | ||
1761 | spin_lock_irq(&pdrvdata_lock); | ||
1762 | list_del(&portdev->list); | ||
1763 | spin_unlock_irq(&pdrvdata_lock); | ||
1764 | |||
1765 | /* Disable interrupts for vqs */ | ||
1766 | vdev->config->reset(vdev); | ||
1767 | /* Finish up work that's lined up */ | ||
1608 | cancel_work_sync(&portdev->control_work); | 1768 | cancel_work_sync(&portdev->control_work); |
1609 | 1769 | ||
1610 | list_for_each_entry_safe(port, port2, &portdev->ports, list) | 1770 | list_for_each_entry_safe(port, port2, &portdev->ports, list) |
1611 | remove_port(port); | 1771 | unplug_port(port); |
1612 | 1772 | ||
1613 | unregister_chrdev(portdev->chr_major, "virtio-portsdev"); | 1773 | unregister_chrdev(portdev->chr_major, "virtio-portsdev"); |
1614 | 1774 | ||
1615 | while ((buf = virtqueue_get_buf(portdev->c_ivq, &len))) | 1775 | /* |
1616 | free_buf(buf); | 1776 | * When yanking out a device, we immediately lose the |
1777 | * (device-side) queues. So there's no point in keeping the | ||
1778 | * guest side around till we drop our final reference. This | ||
1779 | * also means that any ports which are in an open state will | ||
1780 | * have to just stop using the port, as the vqs are going | ||
1781 | * away. | ||
1782 | */ | ||
1783 | if (use_multiport(portdev)) { | ||
1784 | struct port_buffer *buf; | ||
1785 | unsigned int len; | ||
1617 | 1786 | ||
1618 | while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq))) | 1787 | while ((buf = virtqueue_get_buf(portdev->c_ivq, &len))) |
1619 | free_buf(buf); | 1788 | free_buf(buf); |
1789 | |||
1790 | while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq))) | ||
1791 | free_buf(buf); | ||
1792 | } | ||
1620 | 1793 | ||
1621 | vdev->config->del_vqs(vdev); | 1794 | vdev->config->del_vqs(vdev); |
1622 | kfree(portdev->in_vqs); | 1795 | kfree(portdev->in_vqs); |
@@ -1663,6 +1836,7 @@ static int __init init(void) | |||
1663 | PTR_ERR(pdrvdata.debugfs_dir)); | 1836 | PTR_ERR(pdrvdata.debugfs_dir)); |
1664 | } | 1837 | } |
1665 | INIT_LIST_HEAD(&pdrvdata.consoles); | 1838 | INIT_LIST_HEAD(&pdrvdata.consoles); |
1839 | INIT_LIST_HEAD(&pdrvdata.portdevs); | ||
1666 | 1840 | ||
1667 | return register_virtio_driver(&virtio_console); | 1841 | return register_virtio_driver(&virtio_console); |
1668 | } | 1842 | } |