提交 56d7a964 编写于 作者: A Anthony Liguori

Merge remote branch 'amit/for-anthony' into staging

...@@ -351,8 +351,13 @@ static int parse_chr(DeviceState *dev, Property *prop, const char *str) ...@@ -351,8 +351,13 @@ static int parse_chr(DeviceState *dev, Property *prop, const char *str)
CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
*ptr = qemu_chr_find(str); *ptr = qemu_chr_find(str);
if (*ptr == NULL) if (*ptr == NULL) {
return -ENOENT; return -ENOENT;
}
if ((*ptr)->assigned) {
return -EEXIST;
}
(*ptr)->assigned = 1;
return 0; return 0;
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
*/ */
#include "qemu-char.h" #include "qemu-char.h"
#include "qemu-error.h"
#include "virtio-serial.h" #include "virtio-serial.h"
typedef struct VirtConsole { typedef struct VirtConsole {
...@@ -81,8 +82,11 @@ static int virtconsole_exitfn(VirtIOSerialPort *port) ...@@ -81,8 +82,11 @@ static int virtconsole_exitfn(VirtIOSerialPort *port)
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
if (vcon->chr) { if (vcon->chr) {
port->info->have_data = NULL; /*
qemu_chr_close(vcon->chr); * Instead of closing the chardev, free it so it can be used
* for other purposes.
*/
qemu_chr_add_handlers(vcon->chr, NULL, NULL, NULL, NULL);
} }
return 0; return 0;
...@@ -113,6 +117,14 @@ static int virtserialport_initfn(VirtIOSerialPort *port) ...@@ -113,6 +117,14 @@ static int virtserialport_initfn(VirtIOSerialPort *port)
{ {
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
if (port->id == 0) {
/*
* Disallow a generic port at id 0, that's reserved for
* console ports.
*/
error_report("Port number 0 on virtio-serial devices reserved for virtconsole devices for backward compatibility.");
return -1;
}
return generic_port_init(vcon, port); return generic_port_init(vcon, port);
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "virtio.h" #include "virtio.h"
#include "virtio-blk.h" #include "virtio-blk.h"
#include "virtio-net.h" #include "virtio-net.h"
#include "virtio-serial.h"
#include "pci.h" #include "pci.h"
#include "qemu-error.h" #include "qemu-error.h"
#include "msix.h" #include "msix.h"
...@@ -109,8 +110,7 @@ typedef struct { ...@@ -109,8 +110,7 @@ typedef struct {
#ifdef CONFIG_LINUX #ifdef CONFIG_LINUX
V9fsConf fsconf; V9fsConf fsconf;
#endif #endif
/* Max. number of ports we can have for a the virtio-serial device */ virtio_serial_conf serial;
uint32_t max_virtserial_ports;
virtio_net_conf net; virtio_net_conf net;
bool ioeventfd_disabled; bool ioeventfd_disabled;
bool ioeventfd_started; bool ioeventfd_started;
...@@ -770,12 +770,12 @@ static int virtio_serial_init_pci(PCIDevice *pci_dev) ...@@ -770,12 +770,12 @@ static int virtio_serial_init_pci(PCIDevice *pci_dev)
proxy->class_code != PCI_CLASS_OTHERS) /* qemu-kvm */ proxy->class_code != PCI_CLASS_OTHERS) /* qemu-kvm */
proxy->class_code = PCI_CLASS_COMMUNICATION_OTHER; proxy->class_code = PCI_CLASS_COMMUNICATION_OTHER;
vdev = virtio_serial_init(&pci_dev->qdev, proxy->max_virtserial_ports); vdev = virtio_serial_init(&pci_dev->qdev, &proxy->serial);
if (!vdev) { if (!vdev) {
return -1; return -1;
} }
vdev->nvectors = proxy->nvectors == DEV_NVECTORS_UNSPECIFIED vdev->nvectors = proxy->nvectors == DEV_NVECTORS_UNSPECIFIED
? proxy->max_virtserial_ports + 1 ? proxy->serial.max_virtserial_ports + 1
: proxy->nvectors; : proxy->nvectors;
virtio_init_pci(proxy, vdev, virtio_init_pci(proxy, vdev,
PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_VENDOR_ID_REDHAT_QUMRANET,
...@@ -789,6 +789,7 @@ static int virtio_serial_exit_pci(PCIDevice *pci_dev) ...@@ -789,6 +789,7 @@ static int virtio_serial_exit_pci(PCIDevice *pci_dev)
{ {
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
virtio_pci_stop_ioeventfd(proxy);
virtio_serial_exit(proxy->vdev); virtio_serial_exit(proxy->vdev);
return virtio_exit_pci(pci_dev); return virtio_exit_pci(pci_dev);
} }
...@@ -898,12 +899,14 @@ static PCIDeviceInfo virtio_info[] = { ...@@ -898,12 +899,14 @@ static PCIDeviceInfo virtio_info[] = {
.init = virtio_serial_init_pci, .init = virtio_serial_init_pci,
.exit = virtio_serial_exit_pci, .exit = virtio_serial_exit_pci,
.qdev.props = (Property[]) { .qdev.props = (Property[]) {
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
DEV_NVECTORS_UNSPECIFIED), DEV_NVECTORS_UNSPECIFIED),
DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0), DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features), DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy, max_virtserial_ports, DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy,
31), serial.max_virtserial_ports, 31),
DEFINE_PROP_END_OF_LIST(), DEFINE_PROP_END_OF_LIST(),
}, },
.qdev.reset = virtio_pci_reset, .qdev.reset = virtio_pci_reset,
......
...@@ -442,25 +442,19 @@ static void handle_output(VirtIODevice *vdev, VirtQueue *vq) ...@@ -442,25 +442,19 @@ static void handle_output(VirtIODevice *vdev, VirtQueue *vq)
{ {
VirtIOSerial *vser; VirtIOSerial *vser;
VirtIOSerialPort *port; VirtIOSerialPort *port;
bool discard;
vser = DO_UPCAST(VirtIOSerial, vdev, vdev); vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
port = find_port_by_vq(vser, vq); port = find_port_by_vq(vser, vq);
discard = false;
if (!port || !port->host_connected || !port->info->have_data) { if (!port || !port->host_connected || !port->info->have_data) {
discard = true;
}
if (discard) {
discard_vq_data(vq, vdev); discard_vq_data(vq, vdev);
return; return;
} }
if (port->throttled) {
return;
}
if (!port->throttled) {
do_flush_queued_data(port, vq, vdev); do_flush_queued_data(port, vq, vdev);
return;
}
} }
static void handle_input(VirtIODevice *vdev, VirtQueue *vq) static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
...@@ -811,19 +805,19 @@ void virtio_serial_port_qdev_register(VirtIOSerialPortInfo *info) ...@@ -811,19 +805,19 @@ void virtio_serial_port_qdev_register(VirtIOSerialPortInfo *info)
qdev_register(&info->qdev); qdev_register(&info->qdev);
} }
VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports) VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf)
{ {
VirtIOSerial *vser; VirtIOSerial *vser;
VirtIODevice *vdev; VirtIODevice *vdev;
uint32_t i, max_supported_ports; uint32_t i, max_supported_ports;
if (!max_nr_ports) if (!conf->max_virtserial_ports)
return NULL; return NULL;
/* Each port takes 2 queues, and one pair is for the control queue */ /* Each port takes 2 queues, and one pair is for the control queue */
max_supported_ports = VIRTIO_PCI_QUEUE_MAX / 2 - 1; max_supported_ports = VIRTIO_PCI_QUEUE_MAX / 2 - 1;
if (max_nr_ports > max_supported_ports) { if (conf->max_virtserial_ports > max_supported_ports) {
error_report("maximum ports supported: %u", max_supported_ports); error_report("maximum ports supported: %u", max_supported_ports);
return NULL; return NULL;
} }
...@@ -839,9 +833,9 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports) ...@@ -839,9 +833,9 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
vser->bus->vser = vser; vser->bus->vser = vser;
QTAILQ_INIT(&vser->ports); QTAILQ_INIT(&vser->ports);
vser->bus->max_nr_ports = max_nr_ports; vser->bus->max_nr_ports = conf->max_virtserial_ports;
vser->ivqs = qemu_malloc(max_nr_ports * sizeof(VirtQueue *)); vser->ivqs = qemu_malloc(conf->max_virtserial_ports * sizeof(VirtQueue *));
vser->ovqs = qemu_malloc(max_nr_ports * sizeof(VirtQueue *)); vser->ovqs = qemu_malloc(conf->max_virtserial_ports * sizeof(VirtQueue *));
/* Add a queue for host to guest transfers for port 0 (backward compat) */ /* Add a queue for host to guest transfers for port 0 (backward compat) */
vser->ivqs[0] = virtio_add_queue(vdev, 128, handle_input); vser->ivqs[0] = virtio_add_queue(vdev, 128, handle_input);
...@@ -866,8 +860,8 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports) ...@@ -866,8 +860,8 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
vser->ovqs[i] = virtio_add_queue(vdev, 128, handle_output); vser->ovqs[i] = virtio_add_queue(vdev, 128, handle_output);
} }
vser->config.max_nr_ports = max_nr_ports; vser->config.max_nr_ports = conf->max_virtserial_ports;
vser->ports_map = qemu_mallocz(((max_nr_ports + 31) / 32) vser->ports_map = qemu_mallocz(((conf->max_virtserial_ports + 31) / 32)
* sizeof(vser->ports_map[0])); * sizeof(vser->ports_map[0]));
/* /*
* Reserve location 0 for a console port for backward compat * Reserve location 0 for a console port for backward compat
......
...@@ -45,6 +45,11 @@ struct virtio_console_control { ...@@ -45,6 +45,11 @@ struct virtio_console_control {
uint16_t value; /* Extra information for the key */ uint16_t value; /* Extra information for the key */
}; };
struct virtio_serial_conf {
/* Max. number of ports we can have for a virtio-serial device */
uint32_t max_virtserial_ports;
};
/* Some events for the internal messages (control packets) */ /* Some events for the internal messages (control packets) */
#define VIRTIO_CONSOLE_DEVICE_READY 0 #define VIRTIO_CONSOLE_DEVICE_READY 0
#define VIRTIO_CONSOLE_PORT_ADD 1 #define VIRTIO_CONSOLE_PORT_ADD 1
......
...@@ -195,7 +195,8 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf); ...@@ -195,7 +195,8 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf);
struct virtio_net_conf; struct virtio_net_conf;
VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf, VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
struct virtio_net_conf *net); struct virtio_net_conf *net);
VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports); typedef struct virtio_serial_conf virtio_serial_conf;
VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *serial);
VirtIODevice *virtio_balloon_init(DeviceState *dev); VirtIODevice *virtio_balloon_init(DeviceState *dev);
#ifdef CONFIG_LINUX #ifdef CONFIG_LINUX
VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf); VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
......
...@@ -197,6 +197,10 @@ void qemu_chr_add_handlers(CharDriverState *s, ...@@ -197,6 +197,10 @@ void qemu_chr_add_handlers(CharDriverState *s,
IOEventHandler *fd_event, IOEventHandler *fd_event,
void *opaque) void *opaque)
{ {
if (!opaque) {
/* chr driver being released. */
s->assigned = 0;
}
s->chr_can_read = fd_can_read; s->chr_can_read = fd_can_read;
s->chr_read = fd_read; s->chr_read = fd_read;
s->chr_event = fd_event; s->chr_event = fd_event;
......
...@@ -70,6 +70,7 @@ struct CharDriverState { ...@@ -70,6 +70,7 @@ struct CharDriverState {
char *label; char *label;
char *filename; char *filename;
int opened; int opened;
int assigned; /* chardev assigned to a device */
QTAILQ_ENTRY(CharDriverState) next; QTAILQ_ENTRY(CharDriverState) next;
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册