diff options
| -rw-r--r-- | drivers/usb/wusbcore/devconnect.c | 100 | ||||
| -rw-r--r-- | drivers/usb/wusbcore/rh.c | 40 | ||||
| -rw-r--r-- | drivers/usb/wusbcore/security.c | 3 | ||||
| -rw-r--r-- | drivers/usb/wusbcore/wusbhc.h | 4 |
4 files changed, 25 insertions, 122 deletions
diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c index f45d777bef34..c01c7a80744c 100644 --- a/drivers/usb/wusbcore/devconnect.c +++ b/drivers/usb/wusbcore/devconnect.c | |||
| @@ -57,9 +57,6 @@ | |||
| 57 | * Called by notif.c:wusb_handle_dn_connect() | 57 | * Called by notif.c:wusb_handle_dn_connect() |
| 58 | * when a DN_Connect is received. | 58 | * when a DN_Connect is received. |
| 59 | * | 59 | * |
| 60 | * wusbhc_devconnect_auth() Called by rh.c:wusbhc_rh_port_reset() when | ||
| 61 | * doing the device connect sequence. | ||
| 62 | * | ||
| 63 | * wusb_devconnect_acked() Ack done, release resources. | 60 | * wusb_devconnect_acked() Ack done, release resources. |
| 64 | * | 61 | * |
| 65 | * wusb_handle_dn_alive() Called by notif.c:wusb_handle_dn() | 62 | * wusb_handle_dn_alive() Called by notif.c:wusb_handle_dn() |
| @@ -69,9 +66,6 @@ | |||
| 69 | * process a disconenct request from a | 66 | * process a disconenct request from a |
| 70 | * device. | 67 | * device. |
| 71 | * | 68 | * |
| 72 | * wusb_dev_reset() Called by rh.c:wusbhc_rh_port_reset() when | ||
| 73 | * resetting a device. | ||
| 74 | * | ||
| 75 | * __wusb_dev_disable() Called by rh.c:wusbhc_rh_clear_port_feat() when | 69 | * __wusb_dev_disable() Called by rh.c:wusbhc_rh_clear_port_feat() when |
| 76 | * disabling a port. | 70 | * disabling a port. |
| 77 | * | 71 | * |
| @@ -366,12 +360,10 @@ void wusbhc_devconnect_ack(struct wusbhc *wusbhc, struct wusb_dn_connect *dnc, | |||
| 366 | port->wusb_dev = wusb_dev; | 360 | port->wusb_dev = wusb_dev; |
| 367 | port->status |= USB_PORT_STAT_CONNECTION; | 361 | port->status |= USB_PORT_STAT_CONNECTION; |
| 368 | port->change |= USB_PORT_STAT_C_CONNECTION; | 362 | port->change |= USB_PORT_STAT_C_CONNECTION; |
| 369 | port->reset_count = 0; | ||
| 370 | /* Now the port status changed to connected; khubd will | 363 | /* Now the port status changed to connected; khubd will |
| 371 | * pick the change up and try to reset the port to bring it to | 364 | * pick the change up and try to reset the port to bring it to |
| 372 | * the enabled state--so this process returns up to the stack | 365 | * the enabled state--so this process returns up to the stack |
| 373 | * and it calls back into wusbhc_rh_port_reset() who will call | 366 | * and it calls back into wusbhc_rh_port_reset(). |
| 374 | * devconnect_auth(). | ||
| 375 | */ | 367 | */ |
| 376 | error_unlock: | 368 | error_unlock: |
| 377 | mutex_unlock(&wusbhc->mutex); | 369 | mutex_unlock(&wusbhc->mutex); |
| @@ -413,9 +405,6 @@ static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc, | |||
| 413 | wusb_dev_put(wusb_dev); | 405 | wusb_dev_put(wusb_dev); |
| 414 | } | 406 | } |
| 415 | port->wusb_dev = NULL; | 407 | port->wusb_dev = NULL; |
| 416 | /* don't reset the reset_count to zero or wusbhc_rh_port_reset will get | ||
| 417 | * confused! We only reset to zero when we connect a new device. | ||
| 418 | */ | ||
| 419 | 408 | ||
| 420 | /* After a device disconnects, change the GTK (see [WUSB] | 409 | /* After a device disconnects, change the GTK (see [WUSB] |
| 421 | * section 6.2.11.2). */ | 410 | * section 6.2.11.2). */ |
| @@ -429,39 +418,6 @@ static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc, | |||
| 429 | } | 418 | } |
| 430 | 419 | ||
| 431 | /* | 420 | /* |
| 432 | * Authenticate a device into the WUSB Cluster | ||
| 433 | * | ||
| 434 | * Called from the Root Hub code (rh.c:wusbhc_rh_port_reset()) when | ||
| 435 | * asking for a reset on a port that is not enabled (ie: first connect | ||
| 436 | * on the port). | ||
| 437 | * | ||
| 438 | * Performs the 4way handshake to allow the device to comunicate w/ the | ||
| 439 | * WUSB Cluster securely; once done, issue a request to the device for | ||
| 440 | * it to change to address 0. | ||
| 441 | * | ||
| 442 | * This mimics the reset step of Wired USB that once resetting a | ||
| 443 | * device, leaves the port in enabled state and the dev with the | ||
| 444 | * default address (0). | ||
| 445 | * | ||
| 446 | * WUSB1.0[7.1.2] | ||
| 447 | * | ||
| 448 | * @port_idx: port where the change happened--This is the index into | ||
| 449 | * the wusbhc port array, not the USB port number. | ||
| 450 | */ | ||
| 451 | int wusbhc_devconnect_auth(struct wusbhc *wusbhc, u8 port_idx) | ||
| 452 | { | ||
| 453 | struct device *dev = wusbhc->dev; | ||
| 454 | struct wusb_port *port = wusb_port_by_idx(wusbhc, port_idx); | ||
| 455 | |||
| 456 | d_fnstart(3, dev, "(%p, %u)\n", wusbhc, port_idx); | ||
| 457 | port->status &= ~USB_PORT_STAT_RESET; | ||
| 458 | port->status |= USB_PORT_STAT_ENABLE; | ||
| 459 | port->change |= USB_PORT_STAT_C_RESET | USB_PORT_STAT_C_ENABLE; | ||
| 460 | d_fnend(3, dev, "(%p, %u) = 0\n", wusbhc, port_idx); | ||
| 461 | return 0; | ||
| 462 | } | ||
| 463 | |||
| 464 | /* | ||
| 465 | * Refresh the list of keep alives to emit in the MMC | 421 | * Refresh the list of keep alives to emit in the MMC |
| 466 | * | 422 | * |
| 467 | * Some devices don't respond to keep alives unless they've been | 423 | * Some devices don't respond to keep alives unless they've been |
| @@ -662,60 +618,6 @@ static void wusbhc_handle_dn_disconnect(struct wusbhc *wusbhc, struct wusb_dev * | |||
| 662 | } | 618 | } |
| 663 | 619 | ||
| 664 | /* | 620 | /* |
| 665 | * Reset a WUSB device on a HWA | ||
| 666 | * | ||
| 667 | * @wusbhc | ||
| 668 | * @port_idx Index of the port where the device is | ||
| 669 | * | ||
| 670 | * In Wireless USB, a reset is more or less equivalent to a full | ||
| 671 | * disconnect; so we just do a full disconnect and send the device a | ||
| 672 | * Device Reset IE (WUSB1.0[7.5.11]) giving it a few millisecs (6 MMCs). | ||
| 673 | * | ||
| 674 | * @wusbhc should be refcounted and unlocked | ||
| 675 | */ | ||
| 676 | int wusbhc_dev_reset(struct wusbhc *wusbhc, u8 port_idx) | ||
| 677 | { | ||
| 678 | int result; | ||
| 679 | struct device *dev = wusbhc->dev; | ||
| 680 | struct wusb_dev *wusb_dev; | ||
| 681 | struct wuie_reset *ie; | ||
| 682 | |||
| 683 | d_fnstart(3, dev, "(%p, %u)\n", wusbhc, port_idx); | ||
| 684 | mutex_lock(&wusbhc->mutex); | ||
| 685 | result = 0; | ||
| 686 | wusb_dev = wusb_port_by_idx(wusbhc, port_idx)->wusb_dev; | ||
| 687 | if (wusb_dev == NULL) { | ||
| 688 | /* reset no device? ignore */ | ||
| 689 | dev_dbg(dev, "RESET: no device at port %u, ignoring\n", | ||
| 690 | port_idx); | ||
| 691 | goto error_unlock; | ||
| 692 | } | ||
| 693 | result = -ENOMEM; | ||
| 694 | ie = kzalloc(sizeof(*ie), GFP_KERNEL); | ||
| 695 | if (ie == NULL) | ||
| 696 | goto error_unlock; | ||
| 697 | ie->hdr.bLength = sizeof(ie->hdr) + sizeof(ie->CDID); | ||
| 698 | ie->hdr.bIEIdentifier = WUIE_ID_RESET_DEVICE; | ||
| 699 | ie->CDID = wusb_dev->cdid; | ||
| 700 | result = wusbhc_mmcie_set(wusbhc, 0xff, 6, &ie->hdr); | ||
| 701 | if (result < 0) { | ||
| 702 | dev_err(dev, "RESET: cant's set MMC: %d\n", result); | ||
| 703 | goto error_kfree; | ||
| 704 | } | ||
| 705 | __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc, port_idx)); | ||
| 706 | |||
| 707 | /* 120ms, hopefully 6 MMCs (FIXME) */ | ||
| 708 | msleep(120); | ||
| 709 | wusbhc_mmcie_rm(wusbhc, &ie->hdr); | ||
| 710 | error_kfree: | ||
| 711 | kfree(ie); | ||
| 712 | error_unlock: | ||
| 713 | mutex_unlock(&wusbhc->mutex); | ||
| 714 | d_fnend(3, dev, "(%p, %u) = %d\n", wusbhc, port_idx, result); | ||
| 715 | return result; | ||
| 716 | } | ||
| 717 | |||
| 718 | /* | ||
| 719 | * Handle a Device Notification coming a host | 621 | * Handle a Device Notification coming a host |
| 720 | * | 622 | * |
| 721 | * The Device Notification comes from a host (HWA, DWA or WHCI) | 623 | * The Device Notification comes from a host (HWA, DWA or WHCI) |
diff --git a/drivers/usb/wusbcore/rh.c b/drivers/usb/wusbcore/rh.c index 267a64325106..1c733192ec2a 100644 --- a/drivers/usb/wusbcore/rh.c +++ b/drivers/usb/wusbcore/rh.c | |||
| @@ -77,13 +77,17 @@ | |||
| 77 | /* | 77 | /* |
| 78 | * Reset a fake port | 78 | * Reset a fake port |
| 79 | * | 79 | * |
| 80 | * This can be called to reset a port from any other state or to reset | 80 | * Using a Reset Device IE is too heavyweight as it causes the device |
| 81 | * it when connecting. In Wireless USB they are different; when doing | 81 | * to enter the UnConnected state and leave the cluster, this can mean |
| 82 | * a new connect that involves going over the authentication. When | 82 | * that when the device reconnects it is connected to a different fake |
| 83 | * just reseting, its a different story. | 83 | * port. |
| 84 | * | 84 | * |
| 85 | * The Linux USB stack resets a port twice before it considers it | 85 | * Instead, reset authenticated devices with a SetAddress(0), followed |
| 86 | * enabled, so we have to detect and ignore that. | 86 | * by a SetAddresss(AuthAddr). |
| 87 | * | ||
| 88 | * For unauthenticated devices just pretend to reset but do nothing. | ||
| 89 | * If the device initialization continues to fail it will eventually | ||
| 90 | * time out after TrustTimeout and enter the UnConnected state. | ||
| 87 | * | 91 | * |
| 88 | * @wusbhc is assumed referenced and @wusbhc->mutex unlocked. | 92 | * @wusbhc is assumed referenced and @wusbhc->mutex unlocked. |
| 89 | * | 93 | * |
| @@ -97,20 +101,20 @@ static int wusbhc_rh_port_reset(struct wusbhc *wusbhc, u8 port_idx) | |||
| 97 | { | 101 | { |
| 98 | int result = 0; | 102 | int result = 0; |
| 99 | struct wusb_port *port = wusb_port_by_idx(wusbhc, port_idx); | 103 | struct wusb_port *port = wusb_port_by_idx(wusbhc, port_idx); |
| 104 | struct wusb_dev *wusb_dev = port->wusb_dev; | ||
| 105 | |||
| 106 | port->status |= USB_PORT_STAT_RESET; | ||
| 107 | port->change |= USB_PORT_STAT_C_RESET; | ||
| 100 | 108 | ||
| 101 | d_fnstart(3, wusbhc->dev, "(wusbhc %p port_idx %u)\n", | 109 | if (wusb_dev->addr & WUSB_DEV_ADDR_UNAUTH) |
| 102 | wusbhc, port_idx); | 110 | result = 0; |
| 103 | if (port->reset_count == 0) { | ||
| 104 | wusbhc_devconnect_auth(wusbhc, port_idx); | ||
| 105 | port->reset_count++; | ||
| 106 | } else if (port->reset_count == 1) | ||
| 107 | /* see header */ | ||
| 108 | d_printf(2, wusbhc->dev, "Ignoring second reset on port_idx " | ||
| 109 | "%u\n", port_idx); | ||
| 110 | else | 111 | else |
| 111 | result = wusbhc_dev_reset(wusbhc, port_idx); | 112 | result = wusb_dev_update_address(wusbhc, wusb_dev); |
| 112 | d_fnend(3, wusbhc->dev, "(wusbhc %p port_idx %u) = %d\n", | 113 | |
| 113 | wusbhc, port_idx, result); | 114 | port->status &= ~USB_PORT_STAT_RESET; |
| 115 | port->status |= USB_PORT_STAT_ENABLE; | ||
| 116 | port->change |= USB_PORT_STAT_C_RESET | USB_PORT_STAT_C_ENABLE; | ||
| 117 | |||
| 114 | return result; | 118 | return result; |
| 115 | } | 119 | } |
| 116 | 120 | ||
diff --git a/drivers/usb/wusbcore/security.c b/drivers/usb/wusbcore/security.c index a101cad6a8d4..ac00640bba64 100644 --- a/drivers/usb/wusbcore/security.c +++ b/drivers/usb/wusbcore/security.c | |||
| @@ -338,8 +338,7 @@ static void hs_printk(unsigned level, struct device *dev, | |||
| 338 | * Before the device's address (as known by it) was usb_dev->devnum | | 338 | * Before the device's address (as known by it) was usb_dev->devnum | |
| 339 | * 0x80 (unauthenticated address). With this we update it to usb_dev->devnum. | 339 | * 0x80 (unauthenticated address). With this we update it to usb_dev->devnum. |
| 340 | */ | 340 | */ |
| 341 | static int wusb_dev_update_address(struct wusbhc *wusbhc, | 341 | int wusb_dev_update_address(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) |
| 342 | struct wusb_dev *wusb_dev) | ||
| 343 | { | 342 | { |
| 344 | int result = -ENOMEM; | 343 | int result = -ENOMEM; |
| 345 | struct usb_device *usb_dev = wusb_dev->usb_dev; | 344 | struct usb_device *usb_dev = wusb_dev->usb_dev; |
diff --git a/drivers/usb/wusbcore/wusbhc.h b/drivers/usb/wusbcore/wusbhc.h index b9bdf5a5f11b..8fef934ad2f3 100644 --- a/drivers/usb/wusbcore/wusbhc.h +++ b/drivers/usb/wusbcore/wusbhc.h | |||
| @@ -154,7 +154,6 @@ struct wusb_port { | |||
| 154 | u16 status; | 154 | u16 status; |
| 155 | u16 change; | 155 | u16 change; |
| 156 | struct wusb_dev *wusb_dev; /* connected device's info */ | 156 | struct wusb_dev *wusb_dev; /* connected device's info */ |
| 157 | unsigned reset_count; | ||
| 158 | u32 ptk_tkid; | 157 | u32 ptk_tkid; |
| 159 | }; | 158 | }; |
| 160 | 159 | ||
| @@ -387,10 +386,8 @@ extern void wusbhc_devconnect_destroy(struct wusbhc *); | |||
| 387 | extern int wusbhc_devconnect_start(struct wusbhc *wusbhc, | 386 | extern int wusbhc_devconnect_start(struct wusbhc *wusbhc, |
| 388 | const struct wusb_ckhdid *chid); | 387 | const struct wusb_ckhdid *chid); |
| 389 | extern void wusbhc_devconnect_stop(struct wusbhc *wusbhc); | 388 | extern void wusbhc_devconnect_stop(struct wusbhc *wusbhc); |
| 390 | extern int wusbhc_devconnect_auth(struct wusbhc *, u8); | ||
| 391 | extern void wusbhc_handle_dn(struct wusbhc *, u8 srcaddr, | 389 | extern void wusbhc_handle_dn(struct wusbhc *, u8 srcaddr, |
| 392 | struct wusb_dn_hdr *dn_hdr, size_t size); | 390 | struct wusb_dn_hdr *dn_hdr, size_t size); |
| 393 | extern int wusbhc_dev_reset(struct wusbhc *wusbhc, u8 port); | ||
| 394 | extern void __wusbhc_dev_disable(struct wusbhc *wusbhc, u8 port); | 391 | extern void __wusbhc_dev_disable(struct wusbhc *wusbhc, u8 port); |
| 395 | extern int wusb_usb_ncb(struct notifier_block *nb, unsigned long val, | 392 | extern int wusb_usb_ncb(struct notifier_block *nb, unsigned long val, |
| 396 | void *priv); | 393 | void *priv); |
| @@ -436,6 +433,7 @@ extern void wusb_dev_sec_rm(struct wusb_dev *) ; | |||
| 436 | extern int wusb_dev_4way_handshake(struct wusbhc *, struct wusb_dev *, | 433 | extern int wusb_dev_4way_handshake(struct wusbhc *, struct wusb_dev *, |
| 437 | struct wusb_ckhdid *ck); | 434 | struct wusb_ckhdid *ck); |
| 438 | void wusbhc_gtk_rekey(struct wusbhc *wusbhc); | 435 | void wusbhc_gtk_rekey(struct wusbhc *wusbhc); |
| 436 | int wusb_dev_update_address(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev); | ||
| 439 | 437 | ||
| 440 | 438 | ||
| 441 | /* WUSB Cluster ID handling */ | 439 | /* WUSB Cluster ID handling */ |
