Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8af548dc authored by Inaky Perez-Gonzalez's avatar Inaky Perez-Gonzalez Committed by Greg Kroah-Hartman
Browse files

wusb: teach choose_address() about wireless devices



Modify choose_address() so it knows about our special scheme of
addressing WUSB devices (1:1 w/ port number).

Signed-off-by: default avatarInaky Perez-Gonzalez <inaky@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent b1d8dfb0
Loading
Loading
Loading
Loading
+31 −9
Original line number Diff line number Diff line
@@ -1195,21 +1195,42 @@ void usb_set_device_state(struct usb_device *udev,
	spin_unlock_irqrestore(&device_state_lock, flags);
}

/*
 * WUSB devices are simple: they have no hubs behind, so the mapping
 * device <-> virtual port number becomes 1:1. Why? to simplify the
 * life of the device connection logic in
 * drivers/usb/wusbcore/devconnect.c. When we do the initial secret
 * handshake we need to assign a temporary address in the unauthorized
 * space. For simplicity we use the first virtual port number found to
 * be free [drivers/usb/wusbcore/devconnect.c:wusbhc_devconnect_ack()]
 * and that becomes it's address [X < 128] or its unauthorized address
 * [X | 0x80].
 *
 * We add 1 as an offset to the one-based USB-stack port number
 * (zero-based wusb virtual port index) for two reasons: (a) dev addr
 * 0 is reserved by USB for default address; (b) Linux's USB stack
 * uses always #1 for the root hub of the controller. So USB stack's
 * port #1, which is wusb virtual-port #0 has address #2.
 */
static void choose_address(struct usb_device *udev)
{
	int		devnum;
	struct usb_bus	*bus = udev->bus;

	/* If khubd ever becomes multithreaded, this will need a lock */

	/* Try to allocate the next devnum beginning at bus->devnum_next. */
	if (udev->wusb) {
		devnum = udev->portnum + 1;
		BUG_ON(test_bit(devnum, bus->devmap.devicemap));
	} else {
		/* Try to allocate the next devnum beginning at
		 * bus->devnum_next. */
		devnum = find_next_zero_bit(bus->devmap.devicemap, 128,
					    bus->devnum_next);
		if (devnum >= 128)
		devnum = find_next_zero_bit(bus->devmap.devicemap, 128, 1);

			devnum = find_next_zero_bit(bus->devmap.devicemap,
						    128, 1);
		bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1);

	}
	if (devnum < 128) {
		set_bit(devnum, bus->devmap.devicemap);
		udev->devnum = devnum;
@@ -2611,6 +2632,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
		udev->speed = USB_SPEED_UNKNOWN;
 		udev->bus_mA = hub->mA_per_port;
		udev->level = hdev->level + 1;
		udev->wusb = hub_is_wusb(hub);

		/* set the address */
		choose_address(udev);