* [Qemu-devel] [PATCH 0/6] usb patch queue
@ 2011-09-15 11:17 Gerd Hoffmann
2011-09-15 11:17 ` [Qemu-devel] [PATCH 1/6] usb-storage: fix NULL pointer dereference Gerd Hoffmann
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Gerd Hoffmann @ 2011-09-15 11:17 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Hi,
Here comes the USB patch queue with a few bugfixes.
please pull,
Gerd
The following changes since commit 44520db10b1b92f272348ab7028e7afc68ac3edf:
Gdbstub: Fix back-trace on SPARC32 (2011-09-10 18:12:35 +0000)
are available in the git repository at:
git://git.kraxel.org/qemu usb.27
Gerd Hoffmann (5):
usb-storage: fix NULL pointer dereference.
usb-hub: need to check dev->attached
usb: fix port reset
usb-host: factor out code
usb-host: handle USBDEVFS_SETCONFIGURATION returning EBUSY
Peter Maydell (1):
hw/usb-ohci: Fix OHCI_TD_T1 bit position definition
hw/usb-ehci.c | 4 +-
hw/usb-hub.c | 4 +-
hw/usb-msd.c | 5 +-
hw/usb-ohci.c | 4 +-
hw/usb-uhci.c | 2 +-
hw/usb.c | 12 ++++
hw/usb.h | 1 +
usb-linux.c | 176 ++++++++++++++++++++++++++++++++++++---------------------
8 files changed, 136 insertions(+), 72 deletions(-)
^ permalink raw reply [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 1/6] usb-storage: fix NULL pointer dereference.
2011-09-15 11:17 [Qemu-devel] [PATCH 0/6] usb patch queue Gerd Hoffmann
@ 2011-09-15 11:17 ` Gerd Hoffmann
2011-09-15 11:17 ` [Qemu-devel] [PATCH 2/6] usb-hub: need to check dev->attached Gerd Hoffmann
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Gerd Hoffmann @ 2011-09-15 11:17 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
When a usb packet is canceled we need to check whenever we actually have
a scsi request in flight before we try to cancel it.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-msd.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index e92434c..08d2d2a 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -325,7 +325,10 @@ static int usb_msd_handle_control(USBDevice *dev, USBPacket *p,
static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p)
{
MSDState *s = DO_UPCAST(MSDState, dev, dev);
- scsi_req_cancel(s->req);
+
+ if (s->req) {
+ scsi_req_cancel(s->req);
+ }
}
static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
--
1.7.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 2/6] usb-hub: need to check dev->attached
2011-09-15 11:17 [Qemu-devel] [PATCH 0/6] usb patch queue Gerd Hoffmann
2011-09-15 11:17 ` [Qemu-devel] [PATCH 1/6] usb-storage: fix NULL pointer dereference Gerd Hoffmann
@ 2011-09-15 11:17 ` Gerd Hoffmann
2011-09-15 11:17 ` [Qemu-devel] [PATCH 3/6] usb: fix port reset Gerd Hoffmann
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Gerd Hoffmann @ 2011-09-15 11:17 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
commit 891fb2cd4592b6fe76106a69e0ca40efbf82726a did that for all host
controllers, the usb hub was left out by accident.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-hub.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 286e3ad..39382c7 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -289,7 +289,7 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
port->wPortStatus |= PORT_STAT_SUSPEND;
break;
case PORT_RESET:
- if (dev) {
+ if (dev && dev->attached) {
usb_send_msg(dev, USB_MSG_RESET);
port->wPortChange |= PORT_STAT_C_RESET;
/* set enable bit */
@@ -429,7 +429,7 @@ static int usb_hub_broadcast_packet(USBHubState *s, USBPacket *p)
for(i = 0; i < NUM_PORTS; i++) {
port = &s->ports[i];
dev = port->port.dev;
- if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) {
+ if (dev && dev->attached && (port->wPortStatus & PORT_STAT_ENABLE)) {
ret = usb_handle_packet(dev, p);
if (ret != USB_RET_NODEV) {
return ret;
--
1.7.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 3/6] usb: fix port reset
2011-09-15 11:17 [Qemu-devel] [PATCH 0/6] usb patch queue Gerd Hoffmann
2011-09-15 11:17 ` [Qemu-devel] [PATCH 1/6] usb-storage: fix NULL pointer dereference Gerd Hoffmann
2011-09-15 11:17 ` [Qemu-devel] [PATCH 2/6] usb-hub: need to check dev->attached Gerd Hoffmann
@ 2011-09-15 11:17 ` Gerd Hoffmann
2011-09-15 11:18 ` [Qemu-devel] [PATCH 4/6] usb-host: factor out code Gerd Hoffmann
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Gerd Hoffmann @ 2011-09-15 11:17 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
commit 891fb2cd4592b6fe76106a69e0ca40efbf82726a removed the implicit
detach before (re-)attaching in usb_attach(). Some usb host controllers
used that behavior though to do a port reset by a detach+attach
sequence.
This patch establishes old behavior by adding a new usb_reset() function
for port resets and putting it into use, thereby also unifying port
reset behavior of all host controllers. The patch also adds asserts to
usb_attach() and usb_detach() to make sure the calls are symmetrical.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-ehci.c | 4 ++--
hw/usb-ohci.c | 2 +-
hw/usb-uhci.c | 2 +-
hw/usb.c | 12 ++++++++++++
hw/usb.h | 1 +
5 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index e9e0789..0b21c9b 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -880,6 +880,7 @@ static void ehci_reset(void *opaque)
}
if (devs[i] && devs[i]->attached) {
usb_attach(&s->ports[i]);
+ usb_send_msg(devs[i], USB_MSG_RESET);
}
}
ehci_queues_rip_all(s);
@@ -978,8 +979,7 @@ static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
if (!(val & PORTSC_PRESET) &&(*portsc & PORTSC_PRESET)) {
trace_usb_ehci_port_reset(port, 0);
if (dev && dev->attached) {
- usb_attach(&s->ports[port]);
- usb_send_msg(dev, USB_MSG_RESET);
+ usb_reset(&s->ports[port]);
*portsc &= ~PORTSC_CSC;
}
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 503ca2d..34243c8 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -449,7 +449,7 @@ static void ohci_reset(void *opaque)
port = &ohci->rhport[i];
port->ctrl = 0;
if (port->port.dev && port->port.dev->attached) {
- usb_attach(&port->port);
+ usb_reset(&port->port);
}
}
if (ohci->async_td) {
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 64f7b36..6aa2091 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -341,7 +341,7 @@ static void uhci_reset(void *opaque)
port = &s->ports[i];
port->ctrl = 0x0080;
if (port->port.dev && port->port.dev->attached) {
- usb_attach(&port->port);
+ usb_reset(&port->port);
}
}
diff --git a/hw/usb.c b/hw/usb.c
index fa90204..2216efe 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -33,6 +33,7 @@ void usb_attach(USBPort *port)
assert(dev != NULL);
assert(dev->attached);
+ assert(dev->state == USB_STATE_NOTATTACHED);
port->ops->attach(port);
usb_send_msg(dev, USB_MSG_ATTACH);
}
@@ -42,10 +43,21 @@ void usb_detach(USBPort *port)
USBDevice *dev = port->dev;
assert(dev != NULL);
+ assert(dev->state != USB_STATE_NOTATTACHED);
port->ops->detach(port);
usb_send_msg(dev, USB_MSG_DETACH);
}
+void usb_reset(USBPort *port)
+{
+ USBDevice *dev = port->dev;
+
+ assert(dev != NULL);
+ usb_detach(port);
+ usb_attach(port);
+ usb_send_msg(dev, USB_MSG_RESET);
+}
+
void usb_wakeup(USBDevice *dev)
{
if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) {
diff --git a/hw/usb.h b/hw/usb.h
index c08d469..c6e1870 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -306,6 +306,7 @@ void usb_cancel_packet(USBPacket * p);
void usb_attach(USBPort *port);
void usb_detach(USBPort *port);
+void usb_reset(USBPort *port);
void usb_wakeup(USBDevice *dev);
int usb_generic_handle_packet(USBDevice *s, USBPacket *p);
void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p);
--
1.7.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 4/6] usb-host: factor out code
2011-09-15 11:17 [Qemu-devel] [PATCH 0/6] usb patch queue Gerd Hoffmann
` (2 preceding siblings ...)
2011-09-15 11:17 ` [Qemu-devel] [PATCH 3/6] usb: fix port reset Gerd Hoffmann
@ 2011-09-15 11:18 ` Gerd Hoffmann
2011-09-15 11:18 ` [Qemu-devel] [PATCH 5/6] usb-host: handle USBDEVFS_SETCONFIGURATION returning EBUSY Gerd Hoffmann
2011-09-15 11:18 ` [Qemu-devel] [PATCH 6/6] hw/usb-ohci: Fix OHCI_TD_T1 bit position definition Gerd Hoffmann
5 siblings, 0 replies; 7+ messages in thread
From: Gerd Hoffmann @ 2011-09-15 11:18 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Move code to claim usb ports and to disconnect usb interfaces into
usb_host_claim_port and usb_host_disconnect_ifaces functions. No
functional change.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
usb-linux.c | 140 ++++++++++++++++++++++++++++++++--------------------------
1 files changed, 77 insertions(+), 63 deletions(-)
diff --git a/usb-linux.c b/usb-linux.c
index 2075c4c..ff1a29c 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -411,6 +411,80 @@ static void usb_host_async_cancel(USBDevice *dev, USBPacket *p)
}
}
+static int usb_host_claim_port(USBHostDevice *s)
+{
+#ifdef USBDEVFS_CLAIM_PORT
+ char *h, hub_name[64], line[1024];
+ int hub_addr, portnr, ret;
+
+ snprintf(hub_name, sizeof(hub_name), "%d-%s",
+ s->match.bus_num, s->match.port);
+
+ /* try strip off last ".$portnr" to get hub */
+ h = strrchr(hub_name, '.');
+ if (h != NULL) {
+ portnr = atoi(h+1);
+ *h = '\0';
+ } else {
+ /* no dot in there -> it is the root hub */
+ snprintf(hub_name, sizeof(hub_name), "usb%d",
+ s->match.bus_num);
+ portnr = atoi(s->match.port);
+ }
+
+ if (!usb_host_read_file(line, sizeof(line), "devnum",
+ hub_name)) {
+ return -1;
+ }
+ if (sscanf(line, "%d", &hub_addr) != 1) {
+ return -1;
+ }
+
+ if (!usb_host_device_path) {
+ return -1;
+ }
+ snprintf(line, sizeof(line), "%s/%03d/%03d",
+ usb_host_device_path, s->match.bus_num, hub_addr);
+ s->hub_fd = open(line, O_RDWR | O_NONBLOCK);
+ if (s->hub_fd < 0) {
+ return -1;
+ }
+
+ ret = ioctl(s->hub_fd, USBDEVFS_CLAIM_PORT, &portnr);
+ if (ret < 0) {
+ close(s->hub_fd);
+ s->hub_fd = -1;
+ return -1;
+ }
+
+ trace_usb_host_claim_port(s->match.bus_num, hub_addr, portnr);
+ return 0;
+#else
+ return -1;
+#endif
+}
+
+static int usb_host_disconnect_ifaces(USBHostDevice *dev, int nb_interfaces)
+{
+ /* earlier Linux 2.4 do not support that */
+#ifdef USBDEVFS_DISCONNECT
+ struct usbdevfs_ioctl ctrl;
+ int ret, interface;
+
+ for (interface = 0; interface < nb_interfaces; interface++) {
+ ctrl.ioctl_code = USBDEVFS_DISCONNECT;
+ ctrl.ifno = interface;
+ ctrl.data = 0;
+ ret = ioctl(dev->fd, USBDEVFS_IOCTL, &ctrl);
+ if (ret < 0 && errno != ENODATA) {
+ perror("USBDEVFS_DISCONNECT");
+ return -1;
+ }
+ }
+#endif
+ return 0;
+}
+
static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
{
const char *op = NULL;
@@ -462,22 +536,9 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
}
nb_interfaces = dev->descr[i + 4];
-#ifdef USBDEVFS_DISCONNECT
- /* earlier Linux 2.4 do not support that */
- {
- struct usbdevfs_ioctl ctrl;
- for (interface = 0; interface < nb_interfaces; interface++) {
- ctrl.ioctl_code = USBDEVFS_DISCONNECT;
- ctrl.ifno = interface;
- ctrl.data = 0;
- op = "USBDEVFS_DISCONNECT";
- ret = ioctl(dev->fd, USBDEVFS_IOCTL, &ctrl);
- if (ret < 0 && errno != ENODATA) {
- goto fail;
- }
- }
+ if (usb_host_disconnect_ifaces(dev, nb_interfaces) < 0) {
+ goto fail;
}
-#endif
/* XXX: only grab if all interfaces are free */
for (interface = 0; interface < nb_interfaces; interface++) {
@@ -1301,56 +1362,9 @@ static int usb_host_initfn(USBDevice *dev)
qemu_add_exit_notifier(&s->exit);
usb_host_auto_check(NULL);
-#ifdef USBDEVFS_CLAIM_PORT
if (s->match.bus_num != 0 && s->match.port != NULL) {
- char *h, hub_name[64], line[1024];
- int hub_addr, portnr, ret;
-
- snprintf(hub_name, sizeof(hub_name), "%d-%s",
- s->match.bus_num, s->match.port);
-
- /* try strip off last ".$portnr" to get hub */
- h = strrchr(hub_name, '.');
- if (h != NULL) {
- portnr = atoi(h+1);
- *h = '\0';
- } else {
- /* no dot in there -> it is the root hub */
- snprintf(hub_name, sizeof(hub_name), "usb%d",
- s->match.bus_num);
- portnr = atoi(s->match.port);
- }
-
- if (!usb_host_read_file(line, sizeof(line), "devnum",
- hub_name)) {
- goto out;
- }
- if (sscanf(line, "%d", &hub_addr) != 1) {
- goto out;
- }
-
- if (!usb_host_device_path) {
- goto out;
- }
- snprintf(line, sizeof(line), "%s/%03d/%03d",
- usb_host_device_path, s->match.bus_num, hub_addr);
- s->hub_fd = open(line, O_RDWR | O_NONBLOCK);
- if (s->hub_fd < 0) {
- goto out;
- }
-
- ret = ioctl(s->hub_fd, USBDEVFS_CLAIM_PORT, &portnr);
- if (ret < 0) {
- close(s->hub_fd);
- s->hub_fd = -1;
- goto out;
- }
-
- trace_usb_host_claim_port(s->match.bus_num, hub_addr, portnr);
+ usb_host_claim_port(s);
}
-out:
-#endif
-
return 0;
}
--
1.7.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 5/6] usb-host: handle USBDEVFS_SETCONFIGURATION returning EBUSY
2011-09-15 11:17 [Qemu-devel] [PATCH 0/6] usb patch queue Gerd Hoffmann
` (3 preceding siblings ...)
2011-09-15 11:18 ` [Qemu-devel] [PATCH 4/6] usb-host: factor out code Gerd Hoffmann
@ 2011-09-15 11:18 ` Gerd Hoffmann
2011-09-15 11:18 ` [Qemu-devel] [PATCH 6/6] hw/usb-ohci: Fix OHCI_TD_T1 bit position definition Gerd Hoffmann
5 siblings, 0 replies; 7+ messages in thread
From: Gerd Hoffmann @ 2011-09-15 11:18 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
In case the host uses the usb device usbfs will refuse to set the
configuration due to the device being busy. Handle this case by
disconnection the interfaces, then trying again.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
usb-linux.c | 36 +++++++++++++++++++++++++++++++++++-
1 files changed, 35 insertions(+), 1 deletions(-)
diff --git a/usb-linux.c b/usb-linux.c
index ff1a29c..7d4d1d7 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -485,6 +485,26 @@ static int usb_host_disconnect_ifaces(USBHostDevice *dev, int nb_interfaces)
return 0;
}
+static int usb_linux_get_num_interfaces(USBHostDevice *s)
+{
+ char device_name[64], line[1024];
+ int num_interfaces = 0;
+
+ if (usb_fs_type != USB_FS_SYS) {
+ return -1;
+ }
+
+ sprintf(device_name, "%d-%s", s->bus_num, s->port);
+ if (!usb_host_read_file(line, sizeof(line), "bNumInterfaces",
+ device_name)) {
+ return -1;
+ }
+ if (sscanf(line, "%d", &num_interfaces) != 1) {
+ return -1;
+ }
+ return num_interfaces;
+}
+
static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
{
const char *op = NULL;
@@ -901,14 +921,28 @@ static int usb_host_set_address(USBHostDevice *s, int addr)
static int usb_host_set_config(USBHostDevice *s, int config)
{
+ int ret, first = 1;
+
trace_usb_host_set_config(s->bus_num, s->addr, config);
usb_host_release_interfaces(s);
- int ret = ioctl(s->fd, USBDEVFS_SETCONFIGURATION, &config);
+again:
+ ret = ioctl(s->fd, USBDEVFS_SETCONFIGURATION, &config);
DPRINTF("husb: ctrl set config %d ret %d errno %d\n", config, ret, errno);
+ if (ret < 0 && errno == EBUSY && first) {
+ /* happens if usb device is in use by host drivers */
+ int count = usb_linux_get_num_interfaces(s);
+ if (count > 0) {
+ DPRINTF("husb: busy -> disconnecting %d interfaces\n", count);
+ usb_host_disconnect_ifaces(s, count);
+ first = 0;
+ goto again;
+ }
+ }
+
if (ret < 0) {
return ctrl_error();
}
--
1.7.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 6/6] hw/usb-ohci: Fix OHCI_TD_T1 bit position definition
2011-09-15 11:17 [Qemu-devel] [PATCH 0/6] usb patch queue Gerd Hoffmann
` (4 preceding siblings ...)
2011-09-15 11:18 ` [Qemu-devel] [PATCH 5/6] usb-host: handle USBDEVFS_SETCONFIGURATION returning EBUSY Gerd Hoffmann
@ 2011-09-15 11:18 ` Gerd Hoffmann
5 siblings, 0 replies; 7+ messages in thread
From: Gerd Hoffmann @ 2011-09-15 11:18 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Gerd Hoffmann
From: Peter Maydell <peter.maydell@linaro.org>
The OHCI Transfer Descriptor T (DataToggle) bits are 24 and 25;
fix an error which accidentally overlaid them both on the same bit.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-ohci.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 34243c8..fedea3f 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -150,7 +150,7 @@ static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev);
#define OHCI_TD_DI_SHIFT 21
#define OHCI_TD_DI_MASK (7<<OHCI_TD_DI_SHIFT)
#define OHCI_TD_T0 (1<<24)
-#define OHCI_TD_T1 (1<<24)
+#define OHCI_TD_T1 (1<<25)
#define OHCI_TD_EC_SHIFT 26
#define OHCI_TD_EC_MASK (3<<OHCI_TD_EC_SHIFT)
#define OHCI_TD_CC_SHIFT 28
--
1.7.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2011-09-15 11:29 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-09-15 11:17 [Qemu-devel] [PATCH 0/6] usb patch queue Gerd Hoffmann
2011-09-15 11:17 ` [Qemu-devel] [PATCH 1/6] usb-storage: fix NULL pointer dereference Gerd Hoffmann
2011-09-15 11:17 ` [Qemu-devel] [PATCH 2/6] usb-hub: need to check dev->attached Gerd Hoffmann
2011-09-15 11:17 ` [Qemu-devel] [PATCH 3/6] usb: fix port reset Gerd Hoffmann
2011-09-15 11:18 ` [Qemu-devel] [PATCH 4/6] usb-host: factor out code Gerd Hoffmann
2011-09-15 11:18 ` [Qemu-devel] [PATCH 5/6] usb-host: handle USBDEVFS_SETCONFIGURATION returning EBUSY Gerd Hoffmann
2011-09-15 11:18 ` [Qemu-devel] [PATCH 6/6] hw/usb-ohci: Fix OHCI_TD_T1 bit position definition Gerd Hoffmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).