提交 c75fead6 编写于 作者: G Gerd Hoffmann

usb-host: properly release port on unplug & exit

Factor out port release into a separate function.  Call release function
in exit notifier too.  Add explicit call the USBDEVFS_RELEASE_PORT
ioctl, just closing the hub file handle seems not to be enougth.  Make
sure we release the port before resetting the device, otherwise host
drivers will not re-attach.
Signed-off-by: NGerd Hoffmann <kraxel@redhat.com>
上级 24a5bbe1
...@@ -116,6 +116,7 @@ typedef struct USBHostDevice { ...@@ -116,6 +116,7 @@ typedef struct USBHostDevice {
USBDevice dev; USBDevice dev;
int fd; int fd;
int hub_fd; int hub_fd;
int hub_port;
uint8_t descr[8192]; uint8_t descr[8192];
int descr_len; int descr_len;
...@@ -434,7 +435,7 @@ static int usb_host_claim_port(USBHostDevice *s) ...@@ -434,7 +435,7 @@ static int usb_host_claim_port(USBHostDevice *s)
{ {
#ifdef USBDEVFS_CLAIM_PORT #ifdef USBDEVFS_CLAIM_PORT
char *h, hub_name[64], line[1024]; char *h, hub_name[64], line[1024];
int hub_addr, portnr, ret; int hub_addr, ret;
snprintf(hub_name, sizeof(hub_name), "%d-%s", snprintf(hub_name, sizeof(hub_name), "%d-%s",
s->match.bus_num, s->match.port); s->match.bus_num, s->match.port);
...@@ -442,13 +443,13 @@ static int usb_host_claim_port(USBHostDevice *s) ...@@ -442,13 +443,13 @@ static int usb_host_claim_port(USBHostDevice *s)
/* try strip off last ".$portnr" to get hub */ /* try strip off last ".$portnr" to get hub */
h = strrchr(hub_name, '.'); h = strrchr(hub_name, '.');
if (h != NULL) { if (h != NULL) {
portnr = atoi(h+1); s->hub_port = atoi(h+1);
*h = '\0'; *h = '\0';
} else { } else {
/* no dot in there -> it is the root hub */ /* no dot in there -> it is the root hub */
snprintf(hub_name, sizeof(hub_name), "usb%d", snprintf(hub_name, sizeof(hub_name), "usb%d",
s->match.bus_num); s->match.bus_num);
portnr = atoi(s->match.port); s->hub_port = atoi(s->match.port);
} }
if (!usb_host_read_file(line, sizeof(line), "devnum", if (!usb_host_read_file(line, sizeof(line), "devnum",
...@@ -469,20 +470,32 @@ static int usb_host_claim_port(USBHostDevice *s) ...@@ -469,20 +470,32 @@ static int usb_host_claim_port(USBHostDevice *s)
return -1; return -1;
} }
ret = ioctl(s->hub_fd, USBDEVFS_CLAIM_PORT, &portnr); ret = ioctl(s->hub_fd, USBDEVFS_CLAIM_PORT, &s->hub_port);
if (ret < 0) { if (ret < 0) {
close(s->hub_fd); close(s->hub_fd);
s->hub_fd = -1; s->hub_fd = -1;
return -1; return -1;
} }
trace_usb_host_claim_port(s->match.bus_num, hub_addr, portnr); trace_usb_host_claim_port(s->match.bus_num, hub_addr, s->hub_port);
return 0; return 0;
#else #else
return -1; return -1;
#endif #endif
} }
static void usb_host_release_port(USBHostDevice *s)
{
if (s->hub_fd == -1) {
return;
}
#ifdef USBDEVFS_RELEASE_PORT
ioctl(s->hub_fd, USBDEVFS_RELEASE_PORT, &s->hub_port);
#endif
close(s->hub_fd);
s->hub_fd = -1;
}
static int usb_host_disconnect_ifaces(USBHostDevice *dev, int nb_interfaces) static int usb_host_disconnect_ifaces(USBHostDevice *dev, int nb_interfaces)
{ {
/* earlier Linux 2.4 do not support that */ /* earlier Linux 2.4 do not support that */
...@@ -635,10 +648,8 @@ static void usb_host_handle_destroy(USBDevice *dev) ...@@ -635,10 +648,8 @@ static void usb_host_handle_destroy(USBDevice *dev)
{ {
USBHostDevice *s = (USBHostDevice *)dev; USBHostDevice *s = (USBHostDevice *)dev;
usb_host_release_port(s);
usb_host_close(s); usb_host_close(s);
if (s->hub_fd != -1) {
close(s->hub_fd);
}
QTAILQ_REMOVE(&hostdevs, s, next); QTAILQ_REMOVE(&hostdevs, s, next);
qemu_remove_exit_notifier(&s->exit); qemu_remove_exit_notifier(&s->exit);
} }
...@@ -1402,6 +1413,7 @@ static void usb_host_exit_notifier(struct Notifier *n, void *data) ...@@ -1402,6 +1413,7 @@ static void usb_host_exit_notifier(struct Notifier *n, void *data)
{ {
USBHostDevice *s = container_of(n, USBHostDevice, exit); USBHostDevice *s = container_of(n, USBHostDevice, exit);
usb_host_release_port(s);
if (s->fd != -1) { if (s->fd != -1) {
usb_host_do_reset(s);; usb_host_do_reset(s);;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册