190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez/* 290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Wireless USB Host Controller 390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Root Hub operations 490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Copyright (C) 2005-2006 Intel Corporation 790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> 890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * This program is free software; you can redistribute it and/or 1090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * modify it under the terms of the GNU General Public License version 1190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 2 as published by the Free Software Foundation. 1290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 1390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * This program is distributed in the hope that it will be useful, 1490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * but WITHOUT ANY WARRANTY; without even the implied warranty of 1590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * GNU General Public License for more details. 1790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 1890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * You should have received a copy of the GNU General Public License 1990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * along with this program; if not, write to the Free Software 2090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 02110-1301, USA. 2290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 2390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 2490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * We fake a root hub that has fake ports (as many as simultaneous 2590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * devices the Wireless USB Host Controller can deal with). For each 2690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * port we keep an state in @wusbhc->port[index] identical to the one 2790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * specified in the USB2.0[ch11] spec and some extra device 2890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * information that complements the one in 'struct usb_device' (as 2990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * this lacs a hcpriv pointer). 3090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 3190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Note this is common to WHCI and HWA host controllers. 3290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 3390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Through here we enable most of the state changes that the USB stack 3490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * will use to connect or disconnect devices. We need to do some 3590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * forced adaptation of Wireless USB device states vs. wired: 3690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 3790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * USB: WUSB: 3890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 3990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Port Powered-off port slot n/a 4090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Powered-on port slot available 4190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Disconnected port slot available 4290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Connected port slot assigned device 4390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * device sent DN_Connect 4490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * device was authenticated 4590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Enabled device is authenticated, transitioned 4690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * from unauth -> auth -> default address 4790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * -> enabled 4890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Reset disconnect 4990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Disable disconnect 5090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 5190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * This maps the standard USB port states with the WUSB device states 5290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * so we can fake ports without having to modify the USB stack. 5390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 5490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * FIXME: this process will change in the future 5590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 5690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 5790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * ENTRY POINTS 5890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 5990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Our entry points into here are, as in hcd.c, the USB stack root hub 6090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * ops defined in the usb_hcd struct: 6190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 6290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * wusbhc_rh_status_data() Provide hub and port status data bitmap 6390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 6490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * wusbhc_rh_control() Execution of all the major requests 6590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * you can do to a hub (Set|Clear 6690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * features, get descriptors, status, etc). 6790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 6890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * wusbhc_rh_[suspend|resume]() That 6990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 7090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * wusbhc_rh_start_port_reset() ??? unimplemented 7190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez */ 725a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 73f940fcd8eadfe5b909a1474b57de7755edeee62bPaul Gortmaker#include <linux/export.h> 7490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez#include "wusbhc.h" 7590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 7690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez/* 7790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Reset a fake port 7890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 794656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel * Using a Reset Device IE is too heavyweight as it causes the device 804656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel * to enter the UnConnected state and leave the cluster, this can mean 814656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel * that when the device reconnects it is connected to a different fake 824656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel * port. 8390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 844656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel * Instead, reset authenticated devices with a SetAddress(0), followed 854656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel * by a SetAddresss(AuthAddr). 864656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel * 874656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel * For unauthenticated devices just pretend to reset but do nothing. 884656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel * If the device initialization continues to fail it will eventually 894656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel * time out after TrustTimeout and enter the UnConnected state. 9090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 9190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * @wusbhc is assumed referenced and @wusbhc->mutex unlocked. 9290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 9390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Supposedly we are the only thread accesing @wusbhc->port; in any 9490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * case, maybe we should move the mutex locking from 9590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * wusbhc_devconnect_auth() to here. 9690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 9790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * @port_idx refers to the wusbhc's port index, not the USB port number 9890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez */ 9990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalezstatic int wusbhc_rh_port_reset(struct wusbhc *wusbhc, u8 port_idx) 10090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez{ 10190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez int result = 0; 10290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez struct wusb_port *port = wusb_port_by_idx(wusbhc, port_idx); 1034656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel struct wusb_dev *wusb_dev = port->wusb_dev; 1044656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel 1059a9b1d17ba59b78e4bae67f7a7cf546986a42e7dDavid Vrabel if (wusb_dev == NULL) 1069a9b1d17ba59b78e4bae67f7a7cf546986a42e7dDavid Vrabel return -ENOTCONN; 1079a9b1d17ba59b78e4bae67f7a7cf546986a42e7dDavid Vrabel 1084656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel port->status |= USB_PORT_STAT_RESET; 1094656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel port->change |= USB_PORT_STAT_C_RESET; 11090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 1114656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel if (wusb_dev->addr & WUSB_DEV_ADDR_UNAUTH) 1124656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel result = 0; 11390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez else 1144656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel result = wusb_dev_update_address(wusbhc, wusb_dev); 1154656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel 1164656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel port->status &= ~USB_PORT_STAT_RESET; 1174656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel port->status |= USB_PORT_STAT_ENABLE; 1184656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel port->change |= USB_PORT_STAT_C_RESET | USB_PORT_STAT_C_ENABLE; 1194656d5de9555e263c5b4c0462b5af7e7bded1b42David Vrabel 12090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez return result; 12190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez} 12290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 12390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez/* 12490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Return the hub change status bitmap 12590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 12690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * The bits in the change status bitmap are cleared when a 12790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * ClearPortFeature request is issued (USB2.0[11.12.3,11.12.4]. 12890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 12990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * @wusbhc is assumed referenced and @wusbhc->mutex unlocked. 13090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 13190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * WARNING!! This gets called from atomic context; we cannot get the 13290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * mutex--the only race condition we can find is some bit 13390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * changing just after we copy it, which shouldn't be too 13490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * big of a problem [and we can't make it an spinlock 13590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * because other parts need to take it and sleep] . 13690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 13725985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * @usb_hcd is refcounted, so it won't disappear under us 13890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * and before killing a host, the polling of the root hub 13990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * would be stopped anyway. 14090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez */ 14190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalezint wusbhc_rh_status_data(struct usb_hcd *usb_hcd, char *_buf) 14290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez{ 14390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); 144467d296f47731bcba578cfdea8416b4c152c4f1bThomas Pugliese size_t cnt, size, bits_set = 0; 14590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 14690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez /* WE DON'T LOCK, see comment */ 147467d296f47731bcba578cfdea8416b4c152c4f1bThomas Pugliese /* round up to bytes. Hub bit is bit 0 so add 1. */ 148467d296f47731bcba578cfdea8416b4c152c4f1bThomas Pugliese size = DIV_ROUND_UP(wusbhc->ports_max + 1, 8); 149467d296f47731bcba578cfdea8416b4c152c4f1bThomas Pugliese 150467d296f47731bcba578cfdea8416b4c152c4f1bThomas Pugliese /* clear the output buffer. */ 151467d296f47731bcba578cfdea8416b4c152c4f1bThomas Pugliese memset(_buf, 0, size); 152467d296f47731bcba578cfdea8416b4c152c4f1bThomas Pugliese /* set the bit for each changed port. */ 153467d296f47731bcba578cfdea8416b4c152c4f1bThomas Pugliese for (cnt = 0; cnt < wusbhc->ports_max; cnt++) { 154467d296f47731bcba578cfdea8416b4c152c4f1bThomas Pugliese 155467d296f47731bcba578cfdea8416b4c152c4f1bThomas Pugliese if (wusb_port_by_idx(wusbhc, cnt)->change) { 156467d296f47731bcba578cfdea8416b4c152c4f1bThomas Pugliese const int bitpos = cnt+1; 157467d296f47731bcba578cfdea8416b4c152c4f1bThomas Pugliese 158467d296f47731bcba578cfdea8416b4c152c4f1bThomas Pugliese _buf[bitpos/8] |= (1 << (bitpos % 8)); 159467d296f47731bcba578cfdea8416b4c152c4f1bThomas Pugliese bits_set++; 160467d296f47731bcba578cfdea8416b4c152c4f1bThomas Pugliese } 161467d296f47731bcba578cfdea8416b4c152c4f1bThomas Pugliese } 162467d296f47731bcba578cfdea8416b4c152c4f1bThomas Pugliese 163467d296f47731bcba578cfdea8416b4c152c4f1bThomas Pugliese return bits_set ? size : 0; 16490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez} 16590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-GonzalezEXPORT_SYMBOL_GPL(wusbhc_rh_status_data); 16690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 16790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez/* 16832b801e9fa5e05c179b86802ccb19b3b97d47471Justin P. Mattock * Return the hub's descriptor 16990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 17090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * NOTE: almost cut and paste from ehci-hub.c 17190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 17290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * @wusbhc is assumed referenced and @wusbhc->mutex unlocked 17390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez */ 17490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalezstatic int wusbhc_rh_get_hub_descr(struct wusbhc *wusbhc, u16 wValue, 17590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez u16 wIndex, 17690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez struct usb_hub_descriptor *descr, 17790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez u16 wLength) 17890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez{ 17990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez u16 temp = 1 + (wusbhc->ports_max / 8); 18090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez u8 length = 7 + 2 * temp; 18190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 18290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez if (wLength < length) 18390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez return -ENOSPC; 18490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez descr->bDescLength = 7 + 2 * temp; 18590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez descr->bDescriptorType = 0x29; /* HUB type */ 18690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez descr->bNbrPorts = wusbhc->ports_max; 18790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez descr->wHubCharacteristics = cpu_to_le16( 18890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 0x00 /* All ports power at once */ 18990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez | 0x00 /* not part of compound device */ 19090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez | 0x10 /* No overcurrent protection */ 19190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez | 0x00 /* 8 FS think time FIXME ?? */ 19290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez | 0x00); /* No port indicators */ 19390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez descr->bPwrOn2PwrGood = 0; 19490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez descr->bHubContrCurrent = 0; 19590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ 196dbe79bbe9dcb22cb3651c46f18943477141ca452John Youn memset(&descr->u.hs.DeviceRemovable[0], 0, temp); 197dbe79bbe9dcb22cb3651c46f18943477141ca452John Youn memset(&descr->u.hs.DeviceRemovable[temp], 0xff, temp); 19890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez return 0; 19990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez} 20090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 20190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez/* 20290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Clear a hub feature 20390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 20490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * @wusbhc is assumed referenced and @wusbhc->mutex unlocked. 20590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 20690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Nothing to do, so no locking needed ;) 20790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez */ 20890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalezstatic int wusbhc_rh_clear_hub_feat(struct wusbhc *wusbhc, u16 feature) 20990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez{ 21090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez int result; 21190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 21290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez switch (feature) { 21390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case C_HUB_LOCAL_POWER: 21490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez /* FIXME: maybe plug bit 0 to the power input status, 21590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * if any? 21690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * see wusbhc_rh_get_hub_status() */ 21790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case C_HUB_OVER_CURRENT: 21890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez result = 0; 21990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez break; 22090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez default: 22190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez result = -EPIPE; 22290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez } 22390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez return result; 22490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez} 22590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 22690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez/* 22790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Return hub status (it is always zero...) 22890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 22990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * @wusbhc is assumed referenced and @wusbhc->mutex unlocked. 23090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 23190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Nothing to do, so no locking needed ;) 23290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez */ 23390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalezstatic int wusbhc_rh_get_hub_status(struct wusbhc *wusbhc, u32 *buf, 23490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez u16 wLength) 23590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez{ 23690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez /* FIXME: maybe plug bit 0 to the power input status (if any)? */ 23790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez *buf = 0; 23890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez return 0; 23990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez} 24090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 24190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez/* 24290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Set a port feature 24390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 24490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * @wusbhc is assumed referenced and @wusbhc->mutex unlocked. 24590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez */ 24690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalezstatic int wusbhc_rh_set_port_feat(struct wusbhc *wusbhc, u16 feature, 24790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez u8 selector, u8 port_idx) 24890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez{ 24990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez struct device *dev = wusbhc->dev; 25090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 25190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez if (port_idx > wusbhc->ports_max) 252bce83697c5fe84a7a5d38c96fbbe43b4bc028c3eDavid Vrabel return -EINVAL; 25390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 25490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez switch (feature) { 25590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez /* According to USB2.0[11.24.2.13]p2, these features 25690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * are not required to be implemented. */ 25790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case USB_PORT_FEAT_C_OVER_CURRENT: 25890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case USB_PORT_FEAT_C_ENABLE: 25990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case USB_PORT_FEAT_C_SUSPEND: 26090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case USB_PORT_FEAT_C_CONNECTION: 26190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case USB_PORT_FEAT_C_RESET: 262bce83697c5fe84a7a5d38c96fbbe43b4bc028c3eDavid Vrabel return 0; 26390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case USB_PORT_FEAT_POWER: 26490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez /* No such thing, but we fake it works */ 26590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez mutex_lock(&wusbhc->mutex); 26690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez wusb_port_by_idx(wusbhc, port_idx)->status |= USB_PORT_STAT_POWER; 26790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez mutex_unlock(&wusbhc->mutex); 268bce83697c5fe84a7a5d38c96fbbe43b4bc028c3eDavid Vrabel return 0; 26990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case USB_PORT_FEAT_RESET: 270bce83697c5fe84a7a5d38c96fbbe43b4bc028c3eDavid Vrabel return wusbhc_rh_port_reset(wusbhc, port_idx); 27190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case USB_PORT_FEAT_ENABLE: 27290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case USB_PORT_FEAT_SUSPEND: 27390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez dev_err(dev, "(port_idx %d) set feat %d/%d UNIMPLEMENTED\n", 27490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez port_idx, feature, selector); 275bce83697c5fe84a7a5d38c96fbbe43b4bc028c3eDavid Vrabel return -ENOSYS; 27690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez default: 27790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez dev_err(dev, "(port_idx %d) set feat %d/%d UNKNOWN\n", 27890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez port_idx, feature, selector); 279bce83697c5fe84a7a5d38c96fbbe43b4bc028c3eDavid Vrabel return -EPIPE; 28090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez } 281bce83697c5fe84a7a5d38c96fbbe43b4bc028c3eDavid Vrabel 282bce83697c5fe84a7a5d38c96fbbe43b4bc028c3eDavid Vrabel return 0; 28390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez} 28490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 28590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez/* 28690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Clear a port feature... 28790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 28890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * @wusbhc is assumed referenced and @wusbhc->mutex unlocked. 28990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez */ 29090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalezstatic int wusbhc_rh_clear_port_feat(struct wusbhc *wusbhc, u16 feature, 29190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez u8 selector, u8 port_idx) 29290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez{ 293bce83697c5fe84a7a5d38c96fbbe43b4bc028c3eDavid Vrabel int result = 0; 29490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez struct device *dev = wusbhc->dev; 29590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 29690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez if (port_idx > wusbhc->ports_max) 297bce83697c5fe84a7a5d38c96fbbe43b4bc028c3eDavid Vrabel return -EINVAL; 29890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 29990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez mutex_lock(&wusbhc->mutex); 30090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez switch (feature) { 30190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case USB_PORT_FEAT_POWER: /* fake port always on */ 30290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez /* According to USB2.0[11.24.2.7.1.4], no need to implement? */ 30390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case USB_PORT_FEAT_C_OVER_CURRENT: 30490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez break; 30590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case USB_PORT_FEAT_C_RESET: 30690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez wusb_port_by_idx(wusbhc, port_idx)->change &= ~USB_PORT_STAT_C_RESET; 30790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez break; 30890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case USB_PORT_FEAT_C_CONNECTION: 30990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez wusb_port_by_idx(wusbhc, port_idx)->change &= ~USB_PORT_STAT_C_CONNECTION; 31090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez break; 31190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case USB_PORT_FEAT_ENABLE: 31290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez __wusbhc_dev_disable(wusbhc, port_idx); 31390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez break; 31490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case USB_PORT_FEAT_C_ENABLE: 31590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez wusb_port_by_idx(wusbhc, port_idx)->change &= ~USB_PORT_STAT_C_ENABLE; 31690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez break; 31790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case USB_PORT_FEAT_SUSPEND: 31890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case USB_PORT_FEAT_C_SUSPEND: 31990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez dev_err(dev, "(port_idx %d) Clear feat %d/%d UNIMPLEMENTED\n", 32090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez port_idx, feature, selector); 32190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez result = -ENOSYS; 32290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez break; 32390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez default: 32490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez dev_err(dev, "(port_idx %d) Clear feat %d/%d UNKNOWN\n", 32590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez port_idx, feature, selector); 32690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez result = -EPIPE; 32790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez break; 32890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez } 32990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez mutex_unlock(&wusbhc->mutex); 330bce83697c5fe84a7a5d38c96fbbe43b4bc028c3eDavid Vrabel 33190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez return result; 33290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez} 33390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 33490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez/* 33590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Return the port's status 33690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 33790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * @wusbhc is assumed referenced and @wusbhc->mutex unlocked. 33890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez */ 33990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalezstatic int wusbhc_rh_get_port_status(struct wusbhc *wusbhc, u16 port_idx, 34090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez u32 *_buf, u16 wLength) 34190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez{ 342d767d888750a8e15656b7ee15d68f90a151b8936Harvey Harrison __le16 *buf = (__le16 *)_buf; 34390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 34490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez if (port_idx > wusbhc->ports_max) 345bce83697c5fe84a7a5d38c96fbbe43b4bc028c3eDavid Vrabel return -EINVAL; 346bce83697c5fe84a7a5d38c96fbbe43b4bc028c3eDavid Vrabel 34790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez mutex_lock(&wusbhc->mutex); 34890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez buf[0] = cpu_to_le16(wusb_port_by_idx(wusbhc, port_idx)->status); 34990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez buf[1] = cpu_to_le16(wusb_port_by_idx(wusbhc, port_idx)->change); 35090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez mutex_unlock(&wusbhc->mutex); 351bce83697c5fe84a7a5d38c96fbbe43b4bc028c3eDavid Vrabel 352bce83697c5fe84a7a5d38c96fbbe43b4bc028c3eDavid Vrabel return 0; 35390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez} 35490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 35590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez/* 35690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Entry point for Root Hub operations 35790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * 35890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * @wusbhc is assumed referenced and @wusbhc->mutex unlocked. 35990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez */ 36090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalezint wusbhc_rh_control(struct usb_hcd *usb_hcd, u16 reqntype, u16 wValue, 36190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez u16 wIndex, char *buf, u16 wLength) 36290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez{ 36390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez int result = -ENOSYS; 36490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); 36590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 36690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez switch (reqntype) { 36790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case GetHubDescriptor: 36890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez result = wusbhc_rh_get_hub_descr( 36990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez wusbhc, wValue, wIndex, 37090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez (struct usb_hub_descriptor *) buf, wLength); 37190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez break; 37290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case ClearHubFeature: 37390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez result = wusbhc_rh_clear_hub_feat(wusbhc, wValue); 37490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez break; 37590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case GetHubStatus: 37690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez result = wusbhc_rh_get_hub_status(wusbhc, (u32 *)buf, wLength); 37790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez break; 37890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 37990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case SetPortFeature: 38090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez result = wusbhc_rh_set_port_feat(wusbhc, wValue, wIndex >> 8, 38190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez (wIndex & 0xff) - 1); 38290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez break; 38390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case ClearPortFeature: 38490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez result = wusbhc_rh_clear_port_feat(wusbhc, wValue, wIndex >> 8, 38590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez (wIndex & 0xff) - 1); 38690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez break; 38790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case GetPortStatus: 38890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez result = wusbhc_rh_get_port_status(wusbhc, wIndex - 1, 38990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez (u32 *)buf, wLength); 39090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez break; 39190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 39290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez case SetHubFeature: 39390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez default: 39490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez dev_err(wusbhc->dev, "%s (%p [%p], %x, %x, %x, %p, %x) " 39590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez "UNIMPLEMENTED\n", __func__, usb_hcd, wusbhc, reqntype, 39690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez wValue, wIndex, buf, wLength); 39790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez /* dump_stack(); */ 39890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez result = -ENOSYS; 39990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez } 40090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez return result; 40190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez} 40290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-GonzalezEXPORT_SYMBOL_GPL(wusbhc_rh_control); 40390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 40490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalezint wusbhc_rh_start_port_reset(struct usb_hcd *usb_hcd, unsigned port_idx) 40590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez{ 40690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); 40790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez dev_err(wusbhc->dev, "%s (%p [%p], port_idx %u) UNIMPLEMENTED\n", 40890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez __func__, usb_hcd, wusbhc, port_idx); 40990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez WARN_ON(1); 41090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez return -ENOSYS; 41190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez} 41290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-GonzalezEXPORT_SYMBOL_GPL(wusbhc_rh_start_port_reset); 41390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 41490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalezstatic void wusb_port_init(struct wusb_port *port) 41590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez{ 41690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez port->status |= USB_PORT_STAT_HIGH_SPEED; 41790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez} 41890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 41990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez/* 42090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez * Alloc fake port specific fields and status. 42190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez */ 42290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalezint wusbhc_rh_create(struct wusbhc *wusbhc) 42390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez{ 42490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez int result = -ENOMEM; 42590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez size_t port_size, itr; 42690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez port_size = wusbhc->ports_max * sizeof(wusbhc->port[0]); 42790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez wusbhc->port = kzalloc(port_size, GFP_KERNEL); 42890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez if (wusbhc->port == NULL) 42990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez goto error_port_alloc; 43090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez for (itr = 0; itr < wusbhc->ports_max; itr++) 43190ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez wusb_port_init(&wusbhc->port[itr]); 43290ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez result = 0; 43390ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalezerror_port_alloc: 43490ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez return result; 43590ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez} 43690ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez 43790ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalezvoid wusbhc_rh_destroy(struct wusbhc *wusbhc) 43890ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez{ 43990ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez kfree(wusbhc->port); 44090ff96f22426a9d1a06df97dead0a9098facb567Inaky Perez-Gonzalez} 441