| Tony Olech | d774efe | 2006-09-13 11:27:35 +0100 | [diff] [blame] | 1 | /* | 
 | 2 | * Host Controller Driver for the Elan Digital Systems U132 adapter | 
 | 3 | * | 
 | 4 | * Copyright(C) 2006 Elan Digital Systems Limited | 
 | 5 | * http://www.elandigitalsystems.com | 
 | 6 | * | 
 | 7 | * Author and Maintainer - Tony Olech - Elan Digital Systems | 
 | 8 | * tony.olech@elandigitalsystems.com | 
 | 9 | * | 
 | 10 | * This program is free software;you can redistribute it and/or | 
 | 11 | * modify it under the terms of the GNU General Public License as | 
 | 12 | * published by the Free Software Foundation, version 2. | 
 | 13 | * | 
 | 14 | * | 
 | 15 | * This driver was written by Tony Olech(tony.olech@elandigitalsystems.com) | 
 | 16 | * based on various USB host drivers in the 2.6.15 linux kernel | 
 | 17 | * with constant reference to the 3rd Edition of Linux Device Drivers | 
 | 18 | * published by O'Reilly | 
 | 19 | * | 
 | 20 | * The U132 adapter is a USB to CardBus adapter specifically designed | 
 | 21 | * for PC cards that contain an OHCI host controller. Typical PC cards | 
 | 22 | * are the Orange Mobile 3G Option GlobeTrotter Fusion card. | 
 | 23 | * | 
 | 24 | * The U132 adapter will *NOT *work with PC cards that do not contain | 
 | 25 | * an OHCI controller. A simple way to test whether a PC card has an | 
 | 26 | * OHCI controller as an interface is to insert the PC card directly | 
 | 27 | * into a laptop(or desktop) with a CardBus slot and if "lspci" shows | 
 | 28 | * a new USB controller and "lsusb -v" shows a new OHCI Host Controller | 
 | 29 | * then there is a good chance that the U132 adapter will support the | 
 | 30 | * PC card.(you also need the specific client driver for the PC card) | 
 | 31 | * | 
 | 32 | * Please inform the Author and Maintainer about any PC cards that | 
 | 33 | * contain OHCI Host Controller and work when directly connected to | 
 | 34 | * an embedded CardBus slot but do not work when they are connected | 
 | 35 | * via an ELAN U132 adapter. | 
 | 36 | * | 
 | 37 | */ | 
| Tony Olech | d774efe | 2006-09-13 11:27:35 +0100 | [diff] [blame] | 38 | #include <linux/kernel.h> | 
 | 39 | #include <linux/module.h> | 
 | 40 | #include <linux/moduleparam.h> | 
 | 41 | #include <linux/delay.h> | 
 | 42 | #include <linux/ioport.h> | 
 | 43 | #include <linux/sched.h> | 
 | 44 | #include <linux/slab.h> | 
 | 45 | #include <linux/smp_lock.h> | 
 | 46 | #include <linux/errno.h> | 
 | 47 | #include <linux/init.h> | 
 | 48 | #include <linux/timer.h> | 
 | 49 | #include <linux/list.h> | 
 | 50 | #include <linux/interrupt.h> | 
 | 51 | #include <linux/usb.h> | 
 | 52 | #include <linux/workqueue.h> | 
 | 53 | #include <linux/platform_device.h> | 
 | 54 | #include <linux/pci_ids.h> | 
 | 55 | #include <asm/io.h> | 
 | 56 | #include <asm/irq.h> | 
 | 57 | #include <asm/system.h> | 
 | 58 | #include <asm/byteorder.h> | 
 | 59 | #include "../core/hcd.h" | 
 | 60 | #include "ohci.h" | 
 | 61 | #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR | 
 | 62 | #define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \ | 
 | 63 |         OHCI_INTR_WDH) | 
 | 64 | MODULE_AUTHOR("Tony Olech - Elan Digital Systems Limited"); | 
 | 65 | MODULE_DESCRIPTION("U132 USB Host Controller Driver"); | 
 | 66 | MODULE_LICENSE("GPL"); | 
 | 67 | #define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444) | 
 | 68 | INT_MODULE_PARM(testing, 0); | 
 | 69 | /* Some boards misreport power switching/overcurrent*/ | 
 | 70 | static int distrust_firmware = 1; | 
 | 71 | module_param(distrust_firmware, bool, 0); | 
 | 72 | MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren" | 
 | 73 |         "t setup"); | 
 | 74 | DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait); | 
 | 75 | /* | 
 | 76 | * u132_module_lock exists to protect access to global variables | 
 | 77 | * | 
 | 78 | */ | 
 | 79 | static struct semaphore u132_module_lock; | 
 | 80 | static int u132_exiting = 0; | 
 | 81 | static int u132_instances = 0; | 
 | 82 | static struct list_head u132_static_list; | 
 | 83 | /* | 
 | 84 | * end of the global variables protected by u132_module_lock | 
 | 85 | */ | 
 | 86 | static struct workqueue_struct *workqueue; | 
 | 87 | #define MAX_U132_PORTS 7 | 
 | 88 | #define MAX_U132_ADDRS 128 | 
 | 89 | #define MAX_U132_UDEVS 4 | 
 | 90 | #define MAX_U132_ENDPS 100 | 
 | 91 | #define MAX_U132_RINGS 4 | 
 | 92 | static const char *cc_to_text[16] = { | 
 | 93 |         "No Error ", | 
 | 94 |         "CRC Error ", | 
 | 95 |         "Bit Stuff ", | 
 | 96 |         "Data Togg ", | 
 | 97 |         "Stall ", | 
 | 98 |         "DevNotResp ", | 
 | 99 |         "PIDCheck ", | 
 | 100 |         "UnExpPID ", | 
 | 101 |         "DataOver ", | 
 | 102 |         "DataUnder ", | 
 | 103 |         "(for hw) ", | 
 | 104 |         "(for hw) ", | 
 | 105 |         "BufferOver ", | 
 | 106 |         "BuffUnder ", | 
 | 107 |         "(for HCD) ", | 
 | 108 |         "(for HCD) " | 
 | 109 | }; | 
 | 110 | struct u132_port { | 
 | 111 |         struct u132 *u132; | 
 | 112 |         int reset; | 
 | 113 |         int enable; | 
 | 114 |         int power; | 
 | 115 |         int Status; | 
 | 116 | }; | 
 | 117 | struct u132_addr { | 
 | 118 |         u8 address; | 
 | 119 | }; | 
 | 120 | struct u132_udev { | 
 | 121 |         struct kref kref; | 
 | 122 |         struct usb_device *usb_device; | 
 | 123 |         u8 enumeration; | 
 | 124 |         u8 udev_number; | 
 | 125 |         u8 usb_addr; | 
 | 126 |         u8 portnumber; | 
 | 127 |         u8 endp_number_in[16]; | 
 | 128 |         u8 endp_number_out[16]; | 
 | 129 | }; | 
 | 130 | #define ENDP_QUEUE_SHIFT 3 | 
 | 131 | #define ENDP_QUEUE_SIZE (1<<ENDP_QUEUE_SHIFT) | 
 | 132 | #define ENDP_QUEUE_MASK (ENDP_QUEUE_SIZE-1) | 
 | 133 | struct u132_urbq { | 
 | 134 |         struct list_head urb_more; | 
 | 135 |         struct urb *urb; | 
 | 136 | }; | 
 | 137 | struct u132_spin { | 
 | 138 |         spinlock_t slock; | 
 | 139 | }; | 
 | 140 | struct u132_endp { | 
 | 141 |         struct kref kref; | 
 | 142 |         u8 udev_number; | 
 | 143 |         u8 endp_number; | 
 | 144 |         u8 usb_addr; | 
 | 145 |         u8 usb_endp; | 
 | 146 |         struct u132 *u132; | 
 | 147 |         struct list_head endp_ring; | 
 | 148 |         struct u132_ring *ring; | 
 | 149 |         unsigned toggle_bits:2; | 
 | 150 |         unsigned active:1; | 
 | 151 |         unsigned delayed:1; | 
 | 152 |         unsigned input:1; | 
 | 153 |         unsigned output:1; | 
 | 154 |         unsigned pipetype:2; | 
 | 155 |         unsigned dequeueing:1; | 
 | 156 |         unsigned edset_flush:1; | 
 | 157 |         unsigned spare_bits:14; | 
 | 158 |         unsigned long jiffies; | 
 | 159 |         struct usb_host_endpoint *hep; | 
 | 160 |         struct u132_spin queue_lock; | 
 | 161 |         u16 queue_size; | 
 | 162 |         u16 queue_last; | 
 | 163 |         u16 queue_next; | 
 | 164 |         struct urb *urb_list[ENDP_QUEUE_SIZE]; | 
 | 165 |         struct list_head urb_more; | 
 | 166 |         struct work_struct scheduler; | 
 | 167 | }; | 
 | 168 | struct u132_ring { | 
 | 169 |         unsigned in_use:1; | 
 | 170 |         unsigned length:7; | 
 | 171 |         u8 number; | 
 | 172 |         struct u132 *u132; | 
 | 173 |         struct u132_endp *curr_endp; | 
 | 174 |         struct work_struct scheduler; | 
 | 175 | }; | 
 | 176 | #define OHCI_QUIRK_AMD756 0x01 | 
 | 177 | #define OHCI_QUIRK_SUPERIO 0x02 | 
 | 178 | #define OHCI_QUIRK_INITRESET 0x04 | 
 | 179 | #define OHCI_BIG_ENDIAN 0x08 | 
 | 180 | #define OHCI_QUIRK_ZFMICRO 0x10 | 
 | 181 | struct u132 { | 
 | 182 |         struct kref kref; | 
 | 183 |         struct list_head u132_list; | 
 | 184 |         struct semaphore sw_lock; | 
 | 185 |         struct semaphore scheduler_lock; | 
 | 186 |         struct u132_platform_data *board; | 
 | 187 |         struct platform_device *platform_dev; | 
 | 188 |         struct u132_ring ring[MAX_U132_RINGS]; | 
 | 189 |         int sequence_num; | 
 | 190 |         int going; | 
 | 191 |         int power; | 
 | 192 |         int reset; | 
 | 193 |         int num_ports; | 
 | 194 |         u32 hc_control; | 
 | 195 |         u32 hc_fminterval; | 
 | 196 |         u32 hc_roothub_status; | 
 | 197 |         u32 hc_roothub_a; | 
 | 198 |         u32 hc_roothub_portstatus[MAX_ROOT_PORTS]; | 
 | 199 |         int flags; | 
 | 200 |         unsigned long next_statechange; | 
 | 201 |         struct work_struct monitor; | 
 | 202 |         int num_endpoints; | 
 | 203 |         struct u132_addr addr[MAX_U132_ADDRS]; | 
 | 204 |         struct u132_udev udev[MAX_U132_UDEVS]; | 
 | 205 |         struct u132_port port[MAX_U132_PORTS]; | 
 | 206 |         struct u132_endp *endp[MAX_U132_ENDPS]; | 
 | 207 | }; | 
 | 208 | int usb_ftdi_elan_read_reg(struct platform_device *pdev, u32 *data); | 
 | 209 | int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, u8 addressofs, | 
 | 210 |         u8 width, u32 *data); | 
 | 211 | int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, u8 addressofs, | 
 | 212 |         u8 width, u32 data); | 
 | 213 | /* | 
 | 214 | * these can not be inlines because we need the structure offset!! | 
 | 215 | * Does anyone have a better way????? | 
 | 216 | */ | 
 | 217 | #define u132_read_pcimem(u132, member, data) \ | 
 | 218 |         usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \ | 
 | 219 |         ohci_regs, member), 0, data); | 
 | 220 | #define u132_write_pcimem(u132, member, data) \ | 
 | 221 |         usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \ | 
 | 222 |         ohci_regs, member), 0, data); | 
 | 223 | #define u132_write_pcimem_byte(u132, member, data) \ | 
 | 224 |         usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \ | 
 | 225 |         ohci_regs, member), 0x0e, data); | 
 | 226 | static inline struct u132 *udev_to_u132(struct u132_udev *udev) | 
 | 227 | { | 
 | 228 |         u8 udev_number = udev->udev_number; | 
 | 229 |         return container_of(udev, struct u132, udev[udev_number]); | 
 | 230 | } | 
 | 231 |  | 
 | 232 | static inline struct u132 *hcd_to_u132(struct usb_hcd *hcd) | 
 | 233 | { | 
 | 234 |         return (struct u132 *)(hcd->hcd_priv); | 
 | 235 | } | 
 | 236 |  | 
 | 237 | static inline struct usb_hcd *u132_to_hcd(struct u132 *u132) | 
 | 238 | { | 
 | 239 |         return container_of((void *)u132, struct usb_hcd, hcd_priv); | 
 | 240 | } | 
 | 241 |  | 
 | 242 | static inline void u132_disable(struct u132 *u132) | 
 | 243 | { | 
 | 244 |         u132_to_hcd(u132)->state = HC_STATE_HALT; | 
 | 245 | } | 
 | 246 |  | 
 | 247 |  | 
 | 248 | #define kref_to_u132(d) container_of(d, struct u132, kref) | 
 | 249 | #define kref_to_u132_endp(d) container_of(d, struct u132_endp, kref) | 
 | 250 | #define kref_to_u132_udev(d) container_of(d, struct u132_udev, kref) | 
 | 251 | #include "../misc/usb_u132.h" | 
 | 252 | static const char hcd_name[] = "u132_hcd"; | 
 | 253 | #define PORT_C_MASK ((USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | \ | 
 | 254 |         USB_PORT_STAT_C_SUSPEND | USB_PORT_STAT_C_OVERCURRENT | \ | 
 | 255 |         USB_PORT_STAT_C_RESET) << 16) | 
 | 256 | static void u132_hcd_delete(struct kref *kref) | 
 | 257 | { | 
 | 258 |         struct u132 *u132 = kref_to_u132(kref); | 
 | 259 |         struct platform_device *pdev = u132->platform_dev; | 
 | 260 |         struct usb_hcd *hcd = u132_to_hcd(u132); | 
 | 261 |         u132->going += 1; | 
 | 262 |         down(&u132_module_lock); | 
 | 263 |         list_del_init(&u132->u132_list); | 
 | 264 |         u132_instances -= 1; | 
 | 265 |         up(&u132_module_lock); | 
 | 266 |         dev_warn(&u132->platform_dev->dev, "FREEING the hcd=%p and thus the u13" | 
 | 267 |                 "2=%p going=%d pdev=%p\n", hcd, u132, u132->going, pdev); | 
 | 268 |         usb_put_hcd(hcd); | 
 | 269 | } | 
 | 270 |  | 
 | 271 | static inline void u132_u132_put_kref(struct u132 *u132) | 
 | 272 | { | 
 | 273 |         kref_put(&u132->kref, u132_hcd_delete); | 
 | 274 | } | 
 | 275 |  | 
 | 276 | static inline void u132_u132_init_kref(struct u132 *u132) | 
 | 277 | { | 
 | 278 |         kref_init(&u132->kref); | 
 | 279 | } | 
 | 280 |  | 
 | 281 | static void u132_udev_delete(struct kref *kref) | 
 | 282 | { | 
 | 283 |         struct u132_udev *udev = kref_to_u132_udev(kref); | 
 | 284 |         udev->udev_number = 0; | 
 | 285 |         udev->usb_device = NULL; | 
 | 286 |         udev->usb_addr = 0; | 
 | 287 |         udev->enumeration = 0; | 
 | 288 | } | 
 | 289 |  | 
 | 290 | static inline void u132_udev_put_kref(struct u132 *u132, struct u132_udev *udev) | 
 | 291 | { | 
 | 292 |         kref_put(&udev->kref, u132_udev_delete); | 
 | 293 | } | 
 | 294 |  | 
 | 295 | static inline void u132_udev_get_kref(struct u132 *u132, struct u132_udev *udev) | 
 | 296 | { | 
 | 297 |         kref_get(&udev->kref); | 
 | 298 | } | 
 | 299 |  | 
 | 300 | static inline void u132_udev_init_kref(struct u132 *u132, | 
 | 301 |         struct u132_udev *udev) | 
 | 302 | { | 
 | 303 |         kref_init(&udev->kref); | 
 | 304 | } | 
 | 305 |  | 
 | 306 | static inline void u132_ring_put_kref(struct u132 *u132, struct u132_ring *ring) | 
 | 307 | { | 
 | 308 |         kref_put(&u132->kref, u132_hcd_delete); | 
 | 309 | } | 
 | 310 |  | 
 | 311 | static void u132_ring_requeue_work(struct u132 *u132, struct u132_ring *ring, | 
 | 312 |         unsigned int delta) | 
 | 313 | { | 
 | 314 |         if (delta > 0) { | 
 | 315 |                 if (queue_delayed_work(workqueue, &ring->scheduler, delta)) | 
 | 316 |                         return; | 
 | 317 |         } else if (queue_work(workqueue, &ring->scheduler)) | 
 | 318 |                 return; | 
 | 319 |         kref_put(&u132->kref, u132_hcd_delete); | 
 | 320 |         return; | 
 | 321 | } | 
 | 322 |  | 
 | 323 | static void u132_ring_queue_work(struct u132 *u132, struct u132_ring *ring, | 
 | 324 |         unsigned int delta) | 
 | 325 | { | 
 | 326 |         kref_get(&u132->kref); | 
 | 327 |         u132_ring_requeue_work(u132, ring, delta); | 
 | 328 |         return; | 
 | 329 | } | 
 | 330 |  | 
 | 331 | static void u132_ring_cancel_work(struct u132 *u132, struct u132_ring *ring) | 
 | 332 | { | 
 | 333 |         if (cancel_delayed_work(&ring->scheduler)) { | 
 | 334 |                 kref_put(&u132->kref, u132_hcd_delete); | 
 | 335 |         } | 
 | 336 | } | 
 | 337 |  | 
 | 338 | static void u132_endp_delete(struct kref *kref) | 
 | 339 | { | 
 | 340 |         struct u132_endp *endp = kref_to_u132_endp(kref); | 
 | 341 |         struct u132 *u132 = endp->u132; | 
 | 342 |         u8 usb_addr = endp->usb_addr; | 
 | 343 |         u8 usb_endp = endp->usb_endp; | 
 | 344 |         u8 address = u132->addr[usb_addr].address; | 
 | 345 |         struct u132_udev *udev = &u132->udev[address]; | 
 | 346 |         u8 endp_number = endp->endp_number; | 
 | 347 |         struct usb_host_endpoint *hep = endp->hep; | 
 | 348 |         struct u132_ring *ring = endp->ring; | 
 | 349 |         struct list_head *head = &endp->endp_ring; | 
 | 350 |         ring->length -= 1; | 
 | 351 |         if (endp == ring->curr_endp) { | 
 | 352 |                 if (list_empty(head)) { | 
 | 353 |                         ring->curr_endp = NULL; | 
 | 354 |                         list_del(head); | 
 | 355 |                 } else { | 
 | 356 |                         struct u132_endp *next_endp = list_entry(head->next, | 
 | 357 |                                 struct u132_endp, endp_ring); | 
 | 358 |                         ring->curr_endp = next_endp; | 
 | 359 |                         list_del(head); | 
 | 360 |         }} else | 
 | 361 |                 list_del(head); | 
 | 362 |         if (endp->input) { | 
 | 363 |                 udev->endp_number_in[usb_endp] = 0; | 
 | 364 |                 u132_udev_put_kref(u132, udev); | 
 | 365 |         } | 
 | 366 |         if (endp->output) { | 
 | 367 |                 udev->endp_number_out[usb_endp] = 0; | 
 | 368 |                 u132_udev_put_kref(u132, udev); | 
 | 369 |         } | 
 | 370 |         u132->endp[endp_number - 1] = NULL; | 
 | 371 |         hep->hcpriv = NULL; | 
 | 372 |         kfree(endp); | 
 | 373 |         u132_u132_put_kref(u132); | 
 | 374 | } | 
 | 375 |  | 
 | 376 | static inline void u132_endp_put_kref(struct u132 *u132, struct u132_endp *endp) | 
 | 377 | { | 
 | 378 |         kref_put(&endp->kref, u132_endp_delete); | 
 | 379 | } | 
 | 380 |  | 
 | 381 | static inline void u132_endp_get_kref(struct u132 *u132, struct u132_endp *endp) | 
 | 382 | { | 
 | 383 |         kref_get(&endp->kref); | 
 | 384 | } | 
 | 385 |  | 
 | 386 | static inline void u132_endp_init_kref(struct u132 *u132, | 
 | 387 |         struct u132_endp *endp) | 
 | 388 | { | 
 | 389 |         kref_init(&endp->kref); | 
 | 390 |         kref_get(&u132->kref); | 
 | 391 | } | 
 | 392 |  | 
 | 393 | static void u132_endp_queue_work(struct u132 *u132, struct u132_endp *endp, | 
 | 394 |         unsigned int delta) | 
 | 395 | { | 
 | 396 |         if (delta > 0) { | 
 | 397 |                 if (queue_delayed_work(workqueue, &endp->scheduler, delta)) | 
 | 398 |                         kref_get(&endp->kref); | 
 | 399 |         } else if (queue_work(workqueue, &endp->scheduler)) | 
 | 400 |                 kref_get(&endp->kref); | 
 | 401 |         return; | 
 | 402 | } | 
 | 403 |  | 
 | 404 | static void u132_endp_cancel_work(struct u132 *u132, struct u132_endp *endp) | 
 | 405 | { | 
 | 406 |         if (cancel_delayed_work(&endp->scheduler)) | 
 | 407 |                 kref_put(&endp->kref, u132_endp_delete); | 
 | 408 | } | 
 | 409 |  | 
 | 410 | static inline void u132_monitor_put_kref(struct u132 *u132) | 
 | 411 | { | 
 | 412 |         kref_put(&u132->kref, u132_hcd_delete); | 
 | 413 | } | 
 | 414 |  | 
 | 415 | static void u132_monitor_queue_work(struct u132 *u132, unsigned int delta) | 
 | 416 | { | 
 | 417 |         if (delta > 0) { | 
 | 418 |                 if (queue_delayed_work(workqueue, &u132->monitor, delta)) { | 
 | 419 |                         kref_get(&u132->kref); | 
 | 420 |                 } | 
 | 421 |         } else if (queue_work(workqueue, &u132->monitor)) | 
 | 422 |                 kref_get(&u132->kref); | 
 | 423 |         return; | 
 | 424 | } | 
 | 425 |  | 
 | 426 | static void u132_monitor_requeue_work(struct u132 *u132, unsigned int delta) | 
 | 427 | { | 
 | 428 |         if (delta > 0) { | 
 | 429 |                 if (queue_delayed_work(workqueue, &u132->monitor, delta)) | 
 | 430 |                         return; | 
 | 431 |         } else if (queue_work(workqueue, &u132->monitor)) | 
 | 432 |                 return; | 
 | 433 |         kref_put(&u132->kref, u132_hcd_delete); | 
 | 434 |         return; | 
 | 435 | } | 
 | 436 |  | 
 | 437 | static void u132_monitor_cancel_work(struct u132 *u132) | 
 | 438 | { | 
 | 439 |         if (cancel_delayed_work(&u132->monitor)) | 
 | 440 |                 kref_put(&u132->kref, u132_hcd_delete); | 
 | 441 | } | 
 | 442 |  | 
 | 443 | static int read_roothub_info(struct u132 *u132) | 
 | 444 | { | 
 | 445 |         u32 revision; | 
 | 446 |         int retval; | 
 | 447 |         retval = u132_read_pcimem(u132, revision, &revision); | 
 | 448 |         if (retval) { | 
 | 449 |                 dev_err(&u132->platform_dev->dev, "error %d accessing device co" | 
 | 450 |                         "ntrol\n", retval); | 
 | 451 |                 return retval; | 
 | 452 |         } else if ((revision & 0xFF) == 0x10) { | 
 | 453 |         } else if ((revision & 0xFF) == 0x11) { | 
 | 454 |         } else { | 
 | 455 |                 dev_err(&u132->platform_dev->dev, "device revision is not valid" | 
 | 456 |                         " %08X\n", revision); | 
 | 457 |                 return -ENODEV; | 
 | 458 |         } | 
 | 459 |         retval = u132_read_pcimem(u132, control, &u132->hc_control); | 
 | 460 |         if (retval) { | 
 | 461 |                 dev_err(&u132->platform_dev->dev, "error %d accessing device co" | 
 | 462 |                         "ntrol\n", retval); | 
 | 463 |                 return retval; | 
 | 464 |         } | 
 | 465 |         retval = u132_read_pcimem(u132, roothub.status, | 
 | 466 |                 &u132->hc_roothub_status); | 
 | 467 |         if (retval) { | 
 | 468 |                 dev_err(&u132->platform_dev->dev, "error %d accessing device re" | 
 | 469 |                         "g roothub.status\n", retval); | 
 | 470 |                 return retval; | 
 | 471 |         } | 
 | 472 |         retval = u132_read_pcimem(u132, roothub.a, &u132->hc_roothub_a); | 
 | 473 |         if (retval) { | 
 | 474 |                 dev_err(&u132->platform_dev->dev, "error %d accessing device re" | 
 | 475 |                         "g roothub.a\n", retval); | 
 | 476 |                 return retval; | 
 | 477 |         } | 
 | 478 |         { | 
 | 479 |                 int I = u132->num_ports; | 
 | 480 |                 int i = 0; | 
 | 481 |                 while (I-- > 0) { | 
 | 482 |                         retval = u132_read_pcimem(u132, roothub.portstatus[i], | 
 | 483 |                                 &u132->hc_roothub_portstatus[i]); | 
 | 484 |                         if (retval) { | 
 | 485 |                                 dev_err(&u132->platform_dev->dev, "error %d acc" | 
 | 486 |                                         "essing device roothub.portstatus[%d]\n" | 
 | 487 |                                         , retval, i); | 
 | 488 |                                 return retval; | 
 | 489 |                         } else | 
 | 490 |                                 i += 1; | 
 | 491 |                 } | 
 | 492 |         } | 
 | 493 |         return 0; | 
 | 494 | } | 
 | 495 |  | 
 | 496 | static void u132_hcd_monitor_work(void *data) | 
 | 497 | { | 
 | 498 |         struct u132 *u132 = data; | 
 | 499 |         if (u132->going > 1) { | 
 | 500 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 501 |                         , u132->going); | 
 | 502 |                 u132_monitor_put_kref(u132); | 
 | 503 |                 return; | 
 | 504 |         } else if (u132->going > 0) { | 
 | 505 |                 dev_err(&u132->platform_dev->dev, "device is being removed\n"); | 
 | 506 |                 u132_monitor_put_kref(u132); | 
 | 507 |                 return; | 
 | 508 |         } else { | 
 | 509 |                 int retval; | 
 | 510 |                 down(&u132->sw_lock); | 
 | 511 |                 retval = read_roothub_info(u132); | 
 | 512 |                 if (retval) { | 
 | 513 |                         struct usb_hcd *hcd = u132_to_hcd(u132); | 
 | 514 |                         u132_disable(u132); | 
 | 515 |                         u132->going = 1; | 
 | 516 |                         up(&u132->sw_lock); | 
 | 517 |                         usb_hc_died(hcd); | 
 | 518 |                         ftdi_elan_gone_away(u132->platform_dev); | 
 | 519 |                         u132_monitor_put_kref(u132); | 
 | 520 |                         return; | 
 | 521 |                 } else { | 
 | 522 |                         u132_monitor_requeue_work(u132, 500); | 
 | 523 |                         up(&u132->sw_lock); | 
 | 524 |                         return; | 
 | 525 |                 } | 
 | 526 |         } | 
 | 527 | } | 
 | 528 |  | 
 | 529 | static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp, | 
 | 530 |         struct urb *urb, int status) | 
 | 531 | { | 
 | 532 |         struct u132_ring *ring; | 
 | 533 |         unsigned long irqs; | 
 | 534 |         struct usb_hcd *hcd = u132_to_hcd(u132); | 
 | 535 |         urb->error_count = 0; | 
 | 536 |         urb->status = status; | 
 | 537 |         urb->hcpriv = NULL; | 
 | 538 |         spin_lock_irqsave(&endp->queue_lock.slock, irqs); | 
 | 539 |         endp->queue_next += 1; | 
 | 540 |         if (ENDP_QUEUE_SIZE > --endp->queue_size) { | 
 | 541 |                 endp->active = 0; | 
 | 542 |                 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | 
 | 543 |         } else { | 
 | 544 |                 struct list_head *next = endp->urb_more.next; | 
 | 545 |                 struct u132_urbq *urbq = list_entry(next, struct u132_urbq, | 
 | 546 |                         urb_more); | 
 | 547 |                 list_del(next); | 
 | 548 |                 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = | 
 | 549 |                         urbq->urb; | 
 | 550 |                 endp->active = 0; | 
 | 551 |                 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | 
 | 552 |                 kfree(urbq); | 
 | 553 |         } down(&u132->scheduler_lock); | 
 | 554 |         ring = endp->ring; | 
 | 555 |         ring->in_use = 0; | 
 | 556 |         u132_ring_cancel_work(u132, ring); | 
 | 557 |         u132_ring_queue_work(u132, ring, 0); | 
 | 558 |         up(&u132->scheduler_lock); | 
 | 559 |         u132_endp_put_kref(u132, endp); | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 560 |         usb_hcd_giveback_urb(hcd, urb); | 
| Tony Olech | d774efe | 2006-09-13 11:27:35 +0100 | [diff] [blame] | 561 |         return; | 
 | 562 | } | 
 | 563 |  | 
 | 564 | static void u132_hcd_forget_urb(struct u132 *u132, struct u132_endp *endp, | 
 | 565 |         struct urb *urb, int status) | 
 | 566 | { | 
 | 567 |         u132_endp_put_kref(u132, endp); | 
 | 568 | } | 
 | 569 |  | 
 | 570 | static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp, | 
 | 571 |         struct urb *urb, int status) | 
 | 572 | { | 
 | 573 |         unsigned long irqs; | 
 | 574 |         struct usb_hcd *hcd = u132_to_hcd(u132); | 
 | 575 |         urb->error_count = 0; | 
 | 576 |         urb->status = status; | 
 | 577 |         urb->hcpriv = NULL; | 
 | 578 |         spin_lock_irqsave(&endp->queue_lock.slock, irqs); | 
 | 579 |         endp->queue_next += 1; | 
 | 580 |         if (ENDP_QUEUE_SIZE > --endp->queue_size) { | 
 | 581 |                 endp->active = 0; | 
 | 582 |                 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | 
 | 583 |         } else { | 
 | 584 |                 struct list_head *next = endp->urb_more.next; | 
 | 585 |                 struct u132_urbq *urbq = list_entry(next, struct u132_urbq, | 
 | 586 |                         urb_more); | 
 | 587 |                 list_del(next); | 
 | 588 |                 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = | 
 | 589 |                         urbq->urb; | 
 | 590 |                 endp->active = 0; | 
 | 591 |                 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | 
 | 592 |                 kfree(urbq); | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 593 |         } usb_hcd_giveback_urb(hcd, urb); | 
| Tony Olech | d774efe | 2006-09-13 11:27:35 +0100 | [diff] [blame] | 594 |         return; | 
 | 595 | } | 
 | 596 |  | 
 | 597 | static inline int edset_input(struct u132 *u132, struct u132_ring *ring, | 
 | 598 |         struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits, | 
 | 599 |         void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | 
 | 600 |         int toggle_bits, int error_count, int condition_code, int repeat_number, | 
 | 601 |          int halted, int skipped, int actual, int non_null)) | 
 | 602 | { | 
 | 603 |         return usb_ftdi_elan_edset_input(u132->platform_dev, ring->number, endp, | 
 | 604 |                  urb, address, endp->usb_endp, toggle_bits, callback); | 
 | 605 | } | 
 | 606 |  | 
 | 607 | static inline int edset_setup(struct u132 *u132, struct u132_ring *ring, | 
 | 608 |         struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits, | 
 | 609 |         void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | 
 | 610 |         int toggle_bits, int error_count, int condition_code, int repeat_number, | 
 | 611 |          int halted, int skipped, int actual, int non_null)) | 
 | 612 | { | 
 | 613 |         return usb_ftdi_elan_edset_setup(u132->platform_dev, ring->number, endp, | 
 | 614 |                  urb, address, endp->usb_endp, toggle_bits, callback); | 
 | 615 | } | 
 | 616 |  | 
 | 617 | static inline int edset_single(struct u132 *u132, struct u132_ring *ring, | 
 | 618 |         struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits, | 
 | 619 |         void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | 
 | 620 |         int toggle_bits, int error_count, int condition_code, int repeat_number, | 
 | 621 |          int halted, int skipped, int actual, int non_null)) | 
 | 622 | { | 
 | 623 |         return usb_ftdi_elan_edset_single(u132->platform_dev, ring->number, | 
 | 624 |                 endp, urb, address, endp->usb_endp, toggle_bits, callback); | 
 | 625 | } | 
 | 626 |  | 
 | 627 | static inline int edset_output(struct u132 *u132, struct u132_ring *ring, | 
 | 628 |         struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits, | 
 | 629 |         void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | 
 | 630 |         int toggle_bits, int error_count, int condition_code, int repeat_number, | 
 | 631 |          int halted, int skipped, int actual, int non_null)) | 
 | 632 | { | 
 | 633 |         return usb_ftdi_elan_edset_output(u132->platform_dev, ring->number, | 
 | 634 |                 endp, urb, address, endp->usb_endp, toggle_bits, callback); | 
 | 635 | } | 
 | 636 |  | 
 | 637 |  | 
 | 638 | /* | 
 | 639 | * must not LOCK sw_lock | 
 | 640 | * | 
 | 641 | */ | 
 | 642 | static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf, | 
 | 643 |         int len, int toggle_bits, int error_count, int condition_code, | 
 | 644 |         int repeat_number, int halted, int skipped, int actual, int non_null) | 
 | 645 | { | 
 | 646 |         struct u132_endp *endp = data; | 
 | 647 |         struct u132 *u132 = endp->u132; | 
 | 648 |         u8 address = u132->addr[endp->usb_addr].address; | 
 | 649 |         struct u132_udev *udev = &u132->udev[address]; | 
 | 650 |         down(&u132->scheduler_lock); | 
 | 651 |         if (u132->going > 1) { | 
 | 652 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 653 |                         , u132->going); | 
 | 654 |                 up(&u132->scheduler_lock); | 
 | 655 |                 u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | 
 | 656 |                 return; | 
 | 657 |         } else if (endp->dequeueing) { | 
 | 658 |                 endp->dequeueing = 0; | 
 | 659 |                 up(&u132->scheduler_lock); | 
 | 660 |                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 
 | 661 |                 return; | 
 | 662 |         } else if (u132->going > 0) { | 
 | 663 |                 dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 
 | 664 |                         "%p status=%d\n", urb, urb->status); | 
 | 665 |                 up(&u132->scheduler_lock); | 
 | 666 |                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 
 | 667 |                 return; | 
 | 668 |         } else if (urb->status == -EINPROGRESS) { | 
 | 669 |                 struct u132_ring *ring = endp->ring; | 
 | 670 |                 u8 *u = urb->transfer_buffer + urb->actual_length; | 
 | 671 |                 u8 *b = buf; | 
 | 672 |                 int L = len; | 
 | 673 |                 while (L-- > 0) { | 
 | 674 |                         *u++ = *b++; | 
 | 675 |                 } | 
 | 676 |                 urb->actual_length += len; | 
 | 677 |                 if ((condition_code == TD_CC_NOERROR) && | 
 | 678 |                         (urb->transfer_buffer_length > urb->actual_length)) { | 
 | 679 |                         endp->toggle_bits = toggle_bits; | 
 | 680 |                         usb_settoggle(udev->usb_device, endp->usb_endp, 0, | 
 | 681 |                                 1 & toggle_bits); | 
 | 682 |                         if (urb->actual_length > 0) { | 
 | 683 |                                 int retval; | 
 | 684 |                                 up(&u132->scheduler_lock); | 
 | 685 |                                 retval = edset_single(u132, ring, endp, urb, | 
 | 686 |                                         address, endp->toggle_bits, | 
 | 687 |                                         u132_hcd_interrupt_recv); | 
 | 688 |                                 if (retval == 0) { | 
 | 689 |                                 } else | 
 | 690 |                                         u132_hcd_giveback_urb(u132, endp, urb, | 
 | 691 |                                                 retval); | 
 | 692 |                         } else { | 
 | 693 |                                 ring->in_use = 0; | 
 | 694 |                                 endp->active = 0; | 
 | 695 |                                 endp->jiffies = jiffies + | 
 | 696 |                                         msecs_to_jiffies(urb->interval); | 
 | 697 |                                 u132_ring_cancel_work(u132, ring); | 
 | 698 |                                 u132_ring_queue_work(u132, ring, 0); | 
 | 699 |                                 up(&u132->scheduler_lock); | 
 | 700 |                                 u132_endp_put_kref(u132, endp); | 
 | 701 |                         } | 
 | 702 |                         return; | 
 | 703 |                 } else if ((condition_code == TD_DATAUNDERRUN) && | 
 | 704 |                         ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) { | 
 | 705 |                         endp->toggle_bits = toggle_bits; | 
 | 706 |                         usb_settoggle(udev->usb_device, endp->usb_endp, 0, | 
 | 707 |                                 1 & toggle_bits); | 
 | 708 |                         up(&u132->scheduler_lock); | 
 | 709 |                         u132_hcd_giveback_urb(u132, endp, urb, 0); | 
 | 710 |                         return; | 
 | 711 |                 } else { | 
 | 712 |                         if (condition_code == TD_CC_NOERROR) { | 
 | 713 |                                 endp->toggle_bits = toggle_bits; | 
 | 714 |                                 usb_settoggle(udev->usb_device, endp->usb_endp, | 
 | 715 |                                         0, 1 & toggle_bits); | 
 | 716 |                         } else if (condition_code == TD_CC_STALL) { | 
 | 717 |                                 endp->toggle_bits = 0x2; | 
 | 718 |                                 usb_settoggle(udev->usb_device, endp->usb_endp, | 
 | 719 |                                         0, 0); | 
 | 720 |                         } else { | 
 | 721 |                                 endp->toggle_bits = 0x2; | 
 | 722 |                                 usb_settoggle(udev->usb_device, endp->usb_endp, | 
 | 723 |                                         0, 0); | 
 | 724 |                                 dev_err(&u132->platform_dev->dev, "urb=%p givin" | 
 | 725 |                                         "g back INTERRUPT %s\n", urb, | 
 | 726 |                                         cc_to_text[condition_code]); | 
 | 727 |                         } | 
 | 728 |                         up(&u132->scheduler_lock); | 
 | 729 |                         u132_hcd_giveback_urb(u132, endp, urb, | 
 | 730 |                                 cc_to_error[condition_code]); | 
 | 731 |                         return; | 
 | 732 |                 } | 
 | 733 |         } else { | 
 | 734 |                 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 
 | 735 |                         "s=%d\n", urb, urb->status); | 
 | 736 |                 up(&u132->scheduler_lock); | 
 | 737 |                 u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 
 | 738 |                 return; | 
 | 739 |         } | 
 | 740 | } | 
 | 741 |  | 
 | 742 | static void u132_hcd_bulk_output_sent(void *data, struct urb *urb, u8 *buf, | 
 | 743 |         int len, int toggle_bits, int error_count, int condition_code, | 
 | 744 |         int repeat_number, int halted, int skipped, int actual, int non_null) | 
 | 745 | { | 
 | 746 |         struct u132_endp *endp = data; | 
 | 747 |         struct u132 *u132 = endp->u132; | 
 | 748 |         u8 address = u132->addr[endp->usb_addr].address; | 
 | 749 |         down(&u132->scheduler_lock); | 
 | 750 |         if (u132->going > 1) { | 
 | 751 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 752 |                         , u132->going); | 
 | 753 |                 up(&u132->scheduler_lock); | 
 | 754 |                 u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | 
 | 755 |                 return; | 
 | 756 |         } else if (endp->dequeueing) { | 
 | 757 |                 endp->dequeueing = 0; | 
 | 758 |                 up(&u132->scheduler_lock); | 
 | 759 |                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 
 | 760 |                 return; | 
 | 761 |         } else if (u132->going > 0) { | 
 | 762 |                 dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 
 | 763 |                         "%p status=%d\n", urb, urb->status); | 
 | 764 |                 up(&u132->scheduler_lock); | 
 | 765 |                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 
 | 766 |                 return; | 
 | 767 |         } else if (urb->status == -EINPROGRESS) { | 
 | 768 |                 struct u132_ring *ring = endp->ring; | 
 | 769 |                 urb->actual_length += len; | 
 | 770 |                 endp->toggle_bits = toggle_bits; | 
 | 771 |                 if (urb->transfer_buffer_length > urb->actual_length) { | 
 | 772 |                         int retval; | 
 | 773 |                         up(&u132->scheduler_lock); | 
 | 774 |                         retval = edset_output(u132, ring, endp, urb, address, | 
 | 775 |                                 endp->toggle_bits, u132_hcd_bulk_output_sent); | 
 | 776 |                         if (retval == 0) { | 
 | 777 |                         } else | 
 | 778 |                                 u132_hcd_giveback_urb(u132, endp, urb, retval); | 
 | 779 |                         return; | 
 | 780 |                 } else { | 
 | 781 |                         up(&u132->scheduler_lock); | 
 | 782 |                         u132_hcd_giveback_urb(u132, endp, urb, 0); | 
 | 783 |                         return; | 
 | 784 |                 } | 
 | 785 |         } else { | 
 | 786 |                 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 
 | 787 |                         "s=%d\n", urb, urb->status); | 
 | 788 |                 up(&u132->scheduler_lock); | 
 | 789 |                 u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 
 | 790 |                 return; | 
 | 791 |         } | 
 | 792 | } | 
 | 793 |  | 
 | 794 | static void u132_hcd_bulk_input_recv(void *data, struct urb *urb, u8 *buf, | 
 | 795 |         int len, int toggle_bits, int error_count, int condition_code, | 
 | 796 |         int repeat_number, int halted, int skipped, int actual, int non_null) | 
 | 797 | { | 
 | 798 |         struct u132_endp *endp = data; | 
 | 799 |         struct u132 *u132 = endp->u132; | 
 | 800 |         u8 address = u132->addr[endp->usb_addr].address; | 
 | 801 |         struct u132_udev *udev = &u132->udev[address]; | 
 | 802 |         down(&u132->scheduler_lock); | 
 | 803 |         if (u132->going > 1) { | 
 | 804 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 805 |                         , u132->going); | 
 | 806 |                 up(&u132->scheduler_lock); | 
 | 807 |                 u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | 
 | 808 |                 return; | 
 | 809 |         } else if (endp->dequeueing) { | 
 | 810 |                 endp->dequeueing = 0; | 
 | 811 |                 up(&u132->scheduler_lock); | 
 | 812 |                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 
 | 813 |                 return; | 
 | 814 |         } else if (u132->going > 0) { | 
 | 815 |                 dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 
 | 816 |                         "%p status=%d\n", urb, urb->status); | 
 | 817 |                 up(&u132->scheduler_lock); | 
 | 818 |                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 
 | 819 |                 return; | 
 | 820 |         } else if (urb->status == -EINPROGRESS) { | 
 | 821 |                 struct u132_ring *ring = endp->ring; | 
 | 822 |                 u8 *u = urb->transfer_buffer + urb->actual_length; | 
 | 823 |                 u8 *b = buf; | 
 | 824 |                 int L = len; | 
 | 825 |                 while (L-- > 0) { | 
 | 826 |                         *u++ = *b++; | 
 | 827 |                 } | 
 | 828 |                 urb->actual_length += len; | 
 | 829 |                 if ((condition_code == TD_CC_NOERROR) && | 
 | 830 |                         (urb->transfer_buffer_length > urb->actual_length)) { | 
 | 831 |                         int retval; | 
 | 832 |                         endp->toggle_bits = toggle_bits; | 
 | 833 |                         usb_settoggle(udev->usb_device, endp->usb_endp, 0, | 
 | 834 |                                 1 & toggle_bits); | 
 | 835 |                         up(&u132->scheduler_lock); | 
 | 836 |                         retval = usb_ftdi_elan_edset_input(u132->platform_dev, | 
 | 837 |                                 ring->number, endp, urb, address, | 
 | 838 |                                 endp->usb_endp, endp->toggle_bits, | 
 | 839 |                                 u132_hcd_bulk_input_recv); | 
 | 840 |                         if (retval == 0) { | 
 | 841 |                         } else | 
 | 842 |                                 u132_hcd_giveback_urb(u132, endp, urb, retval); | 
 | 843 |                         return; | 
 | 844 |                 } else if (condition_code == TD_CC_NOERROR) { | 
 | 845 |                         endp->toggle_bits = toggle_bits; | 
 | 846 |                         usb_settoggle(udev->usb_device, endp->usb_endp, 0, | 
 | 847 |                                 1 & toggle_bits); | 
 | 848 |                         up(&u132->scheduler_lock); | 
 | 849 |                         u132_hcd_giveback_urb(u132, endp, urb, | 
 | 850 |                                 cc_to_error[condition_code]); | 
 | 851 |                         return; | 
 | 852 |                 } else if ((condition_code == TD_DATAUNDERRUN) && | 
 | 853 |                         ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) { | 
 | 854 |                         endp->toggle_bits = toggle_bits; | 
 | 855 |                         usb_settoggle(udev->usb_device, endp->usb_endp, 0, | 
 | 856 |                                 1 & toggle_bits); | 
 | 857 |                         up(&u132->scheduler_lock); | 
 | 858 |                         u132_hcd_giveback_urb(u132, endp, urb, 0); | 
 | 859 |                         return; | 
 | 860 |                 } else if (condition_code == TD_DATAUNDERRUN) { | 
 | 861 |                         endp->toggle_bits = toggle_bits; | 
 | 862 |                         usb_settoggle(udev->usb_device, endp->usb_endp, 0, | 
 | 863 |                                 1 & toggle_bits); | 
 | 864 |                         dev_warn(&u132->platform_dev->dev, "urb=%p(SHORT NOT OK" | 
 | 865 |                                 ") giving back BULK IN %s\n", urb, | 
 | 866 |                                 cc_to_text[condition_code]); | 
 | 867 |                         up(&u132->scheduler_lock); | 
 | 868 |                         u132_hcd_giveback_urb(u132, endp, urb, 0); | 
 | 869 |                         return; | 
 | 870 |                 } else if (condition_code == TD_CC_STALL) { | 
 | 871 |                         endp->toggle_bits = 0x2; | 
 | 872 |                         usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0); | 
 | 873 |                         up(&u132->scheduler_lock); | 
 | 874 |                         u132_hcd_giveback_urb(u132, endp, urb, | 
 | 875 |                                 cc_to_error[condition_code]); | 
 | 876 |                         return; | 
 | 877 |                 } else { | 
 | 878 |                         endp->toggle_bits = 0x2; | 
 | 879 |                         usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0); | 
 | 880 |                         dev_err(&u132->platform_dev->dev, "urb=%p giving back B" | 
 | 881 |                                 "ULK IN code=%d %s\n", urb, condition_code, | 
 | 882 |                                 cc_to_text[condition_code]); | 
 | 883 |                         up(&u132->scheduler_lock); | 
 | 884 |                         u132_hcd_giveback_urb(u132, endp, urb, | 
 | 885 |                                 cc_to_error[condition_code]); | 
 | 886 |                         return; | 
 | 887 |                 } | 
 | 888 |         } else { | 
 | 889 |                 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 
 | 890 |                         "s=%d\n", urb, urb->status); | 
 | 891 |                 up(&u132->scheduler_lock); | 
 | 892 |                 u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 
 | 893 |                 return; | 
 | 894 |         } | 
 | 895 | } | 
 | 896 |  | 
 | 897 | static void u132_hcd_configure_empty_sent(void *data, struct urb *urb, u8 *buf, | 
 | 898 |         int len, int toggle_bits, int error_count, int condition_code, | 
 | 899 |         int repeat_number, int halted, int skipped, int actual, int non_null) | 
 | 900 | { | 
 | 901 |         struct u132_endp *endp = data; | 
 | 902 |         struct u132 *u132 = endp->u132; | 
 | 903 |         down(&u132->scheduler_lock); | 
 | 904 |         if (u132->going > 1) { | 
 | 905 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 906 |                         , u132->going); | 
 | 907 |                 up(&u132->scheduler_lock); | 
 | 908 |                 u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | 
 | 909 |                 return; | 
 | 910 |         } else if (endp->dequeueing) { | 
 | 911 |                 endp->dequeueing = 0; | 
 | 912 |                 up(&u132->scheduler_lock); | 
 | 913 |                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 
 | 914 |                 return; | 
 | 915 |         } else if (u132->going > 0) { | 
 | 916 |                 dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 
 | 917 |                         "%p status=%d\n", urb, urb->status); | 
 | 918 |                 up(&u132->scheduler_lock); | 
 | 919 |                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 
 | 920 |                 return; | 
 | 921 |         } else if (urb->status == -EINPROGRESS) { | 
 | 922 |                 up(&u132->scheduler_lock); | 
 | 923 |                 u132_hcd_giveback_urb(u132, endp, urb, 0); | 
 | 924 |                 return; | 
 | 925 |         } else { | 
 | 926 |                 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 
 | 927 |                         "s=%d\n", urb, urb->status); | 
 | 928 |                 up(&u132->scheduler_lock); | 
 | 929 |                 u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 
 | 930 |                 return; | 
 | 931 |         } | 
 | 932 | } | 
 | 933 |  | 
 | 934 | static void u132_hcd_configure_input_recv(void *data, struct urb *urb, u8 *buf, | 
 | 935 |         int len, int toggle_bits, int error_count, int condition_code, | 
 | 936 |         int repeat_number, int halted, int skipped, int actual, int non_null) | 
 | 937 | { | 
 | 938 |         struct u132_endp *endp = data; | 
 | 939 |         struct u132 *u132 = endp->u132; | 
 | 940 |         u8 address = u132->addr[endp->usb_addr].address; | 
 | 941 |         down(&u132->scheduler_lock); | 
 | 942 |         if (u132->going > 1) { | 
 | 943 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 944 |                         , u132->going); | 
 | 945 |                 up(&u132->scheduler_lock); | 
 | 946 |                 u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | 
 | 947 |                 return; | 
 | 948 |         } else if (endp->dequeueing) { | 
 | 949 |                 endp->dequeueing = 0; | 
 | 950 |                 up(&u132->scheduler_lock); | 
 | 951 |                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 
 | 952 |                 return; | 
 | 953 |         } else if (u132->going > 0) { | 
 | 954 |                 dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 
 | 955 |                         "%p status=%d\n", urb, urb->status); | 
 | 956 |                 up(&u132->scheduler_lock); | 
 | 957 |                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 
 | 958 |                 return; | 
 | 959 |         } else if (urb->status == -EINPROGRESS) { | 
 | 960 |                 struct u132_ring *ring = endp->ring; | 
 | 961 |                 u8 *u = urb->transfer_buffer; | 
 | 962 |                 u8 *b = buf; | 
 | 963 |                 int L = len; | 
 | 964 |                 while (L-- > 0) { | 
 | 965 |                         *u++ = *b++; | 
 | 966 |                 } | 
 | 967 |                 urb->actual_length = len; | 
 | 968 |                 if ((condition_code == TD_CC_NOERROR) || ((condition_code == | 
 | 969 |                         TD_DATAUNDERRUN) && ((urb->transfer_flags & | 
 | 970 |                         URB_SHORT_NOT_OK) == 0))) { | 
 | 971 |                         int retval; | 
 | 972 |                         up(&u132->scheduler_lock); | 
 | 973 |                         retval = usb_ftdi_elan_edset_empty(u132->platform_dev, | 
 | 974 |                                 ring->number, endp, urb, address, | 
 | 975 |                                 endp->usb_endp, 0x3, | 
 | 976 |                                 u132_hcd_configure_empty_sent); | 
 | 977 |                         if (retval == 0) { | 
 | 978 |                         } else | 
 | 979 |                                 u132_hcd_giveback_urb(u132, endp, urb, retval); | 
 | 980 |                         return; | 
 | 981 |                 } else if (condition_code == TD_CC_STALL) { | 
 | 982 |                         up(&u132->scheduler_lock); | 
 | 983 |                         dev_warn(&u132->platform_dev->dev, "giving back SETUP I" | 
 | 984 |                                 "NPUT STALL urb %p\n", urb); | 
 | 985 |                         u132_hcd_giveback_urb(u132, endp, urb, | 
 | 986 |                                 cc_to_error[condition_code]); | 
 | 987 |                         return; | 
 | 988 |                 } else { | 
 | 989 |                         up(&u132->scheduler_lock); | 
 | 990 |                         dev_err(&u132->platform_dev->dev, "giving back SETUP IN" | 
 | 991 |                                 "PUT %s urb %p\n", cc_to_text[condition_code], | 
 | 992 |                                 urb); | 
 | 993 |                         u132_hcd_giveback_urb(u132, endp, urb, | 
 | 994 |                                 cc_to_error[condition_code]); | 
 | 995 |                         return; | 
 | 996 |                 } | 
 | 997 |         } else { | 
 | 998 |                 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 
 | 999 |                         "s=%d\n", urb, urb->status); | 
 | 1000 |                 up(&u132->scheduler_lock); | 
 | 1001 |                 u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 
 | 1002 |                 return; | 
 | 1003 |         } | 
 | 1004 | } | 
 | 1005 |  | 
 | 1006 | static void u132_hcd_configure_empty_recv(void *data, struct urb *urb, u8 *buf, | 
 | 1007 |         int len, int toggle_bits, int error_count, int condition_code, | 
 | 1008 |         int repeat_number, int halted, int skipped, int actual, int non_null) | 
 | 1009 | { | 
 | 1010 |         struct u132_endp *endp = data; | 
 | 1011 |         struct u132 *u132 = endp->u132; | 
 | 1012 |         down(&u132->scheduler_lock); | 
 | 1013 |         if (u132->going > 1) { | 
 | 1014 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 1015 |                         , u132->going); | 
 | 1016 |                 up(&u132->scheduler_lock); | 
 | 1017 |                 u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | 
 | 1018 |                 return; | 
 | 1019 |         } else if (endp->dequeueing) { | 
 | 1020 |                 endp->dequeueing = 0; | 
 | 1021 |                 up(&u132->scheduler_lock); | 
 | 1022 |                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 
 | 1023 |                 return; | 
 | 1024 |         } else if (u132->going > 0) { | 
 | 1025 |                 dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 
 | 1026 |                         "%p status=%d\n", urb, urb->status); | 
 | 1027 |                 up(&u132->scheduler_lock); | 
 | 1028 |                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 
 | 1029 |                 return; | 
 | 1030 |         } else if (urb->status == -EINPROGRESS) { | 
 | 1031 |                 up(&u132->scheduler_lock); | 
 | 1032 |                 u132_hcd_giveback_urb(u132, endp, urb, 0); | 
 | 1033 |                 return; | 
 | 1034 |         } else { | 
 | 1035 |                 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 
 | 1036 |                         "s=%d\n", urb, urb->status); | 
 | 1037 |                 up(&u132->scheduler_lock); | 
 | 1038 |                 u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 
 | 1039 |                 return; | 
 | 1040 |         } | 
 | 1041 | } | 
 | 1042 |  | 
 | 1043 | static void u132_hcd_configure_setup_sent(void *data, struct urb *urb, u8 *buf, | 
 | 1044 |         int len, int toggle_bits, int error_count, int condition_code, | 
 | 1045 |         int repeat_number, int halted, int skipped, int actual, int non_null) | 
 | 1046 | { | 
 | 1047 |         struct u132_endp *endp = data; | 
 | 1048 |         struct u132 *u132 = endp->u132; | 
 | 1049 |         u8 address = u132->addr[endp->usb_addr].address; | 
 | 1050 |         down(&u132->scheduler_lock); | 
 | 1051 |         if (u132->going > 1) { | 
 | 1052 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 1053 |                         , u132->going); | 
 | 1054 |                 up(&u132->scheduler_lock); | 
 | 1055 |                 u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | 
 | 1056 |                 return; | 
 | 1057 |         } else if (endp->dequeueing) { | 
 | 1058 |                 endp->dequeueing = 0; | 
 | 1059 |                 up(&u132->scheduler_lock); | 
 | 1060 |                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 
 | 1061 |                 return; | 
 | 1062 |         } else if (u132->going > 0) { | 
 | 1063 |                 dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 
 | 1064 |                         "%p status=%d\n", urb, urb->status); | 
 | 1065 |                 up(&u132->scheduler_lock); | 
 | 1066 |                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 
 | 1067 |                 return; | 
 | 1068 |         } else if (urb->status == -EINPROGRESS) { | 
 | 1069 |                 if (usb_pipein(urb->pipe)) { | 
 | 1070 |                         int retval; | 
 | 1071 |                         struct u132_ring *ring = endp->ring; | 
 | 1072 |                         up(&u132->scheduler_lock); | 
 | 1073 |                         retval = usb_ftdi_elan_edset_input(u132->platform_dev, | 
 | 1074 |                                 ring->number, endp, urb, address, | 
 | 1075 |                                 endp->usb_endp, 0, | 
 | 1076 |                                 u132_hcd_configure_input_recv); | 
 | 1077 |                         if (retval == 0) { | 
 | 1078 |                         } else | 
 | 1079 |                                 u132_hcd_giveback_urb(u132, endp, urb, retval); | 
 | 1080 |                         return; | 
 | 1081 |                 } else { | 
 | 1082 |                         int retval; | 
 | 1083 |                         struct u132_ring *ring = endp->ring; | 
 | 1084 |                         up(&u132->scheduler_lock); | 
 | 1085 |                         retval = usb_ftdi_elan_edset_input(u132->platform_dev, | 
 | 1086 |                                 ring->number, endp, urb, address, | 
 | 1087 |                                 endp->usb_endp, 0, | 
 | 1088 |                                 u132_hcd_configure_empty_recv); | 
 | 1089 |                         if (retval == 0) { | 
 | 1090 |                         } else | 
 | 1091 |                                 u132_hcd_giveback_urb(u132, endp, urb, retval); | 
 | 1092 |                         return; | 
 | 1093 |                 } | 
 | 1094 |         } else { | 
 | 1095 |                 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 
 | 1096 |                         "s=%d\n", urb, urb->status); | 
 | 1097 |                 up(&u132->scheduler_lock); | 
 | 1098 |                 u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 
 | 1099 |                 return; | 
 | 1100 |         } | 
 | 1101 | } | 
 | 1102 |  | 
 | 1103 | static void u132_hcd_enumeration_empty_recv(void *data, struct urb *urb, | 
 | 1104 |         u8 *buf, int len, int toggle_bits, int error_count, int condition_code, | 
 | 1105 |         int repeat_number, int halted, int skipped, int actual, int non_null) | 
 | 1106 | { | 
 | 1107 |         struct u132_endp *endp = data; | 
 | 1108 |         struct u132 *u132 = endp->u132; | 
 | 1109 |         u8 address = u132->addr[endp->usb_addr].address; | 
 | 1110 |         struct u132_udev *udev = &u132->udev[address]; | 
 | 1111 |         down(&u132->scheduler_lock); | 
 | 1112 |         if (u132->going > 1) { | 
 | 1113 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 1114 |                         , u132->going); | 
 | 1115 |                 up(&u132->scheduler_lock); | 
 | 1116 |                 u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | 
 | 1117 |                 return; | 
 | 1118 |         } else if (endp->dequeueing) { | 
 | 1119 |                 endp->dequeueing = 0; | 
 | 1120 |                 up(&u132->scheduler_lock); | 
 | 1121 |                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 
 | 1122 |                 return; | 
 | 1123 |         } else if (u132->going > 0) { | 
 | 1124 |                 dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 
 | 1125 |                         "%p status=%d\n", urb, urb->status); | 
 | 1126 |                 up(&u132->scheduler_lock); | 
 | 1127 |                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 
 | 1128 |                 return; | 
 | 1129 |         } else if (urb->status == -EINPROGRESS) { | 
 | 1130 |                 u132->addr[0].address = 0; | 
 | 1131 |                 endp->usb_addr = udev->usb_addr; | 
 | 1132 |                 up(&u132->scheduler_lock); | 
 | 1133 |                 u132_hcd_giveback_urb(u132, endp, urb, 0); | 
 | 1134 |                 return; | 
 | 1135 |         } else { | 
 | 1136 |                 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 
 | 1137 |                         "s=%d\n", urb, urb->status); | 
 | 1138 |                 up(&u132->scheduler_lock); | 
 | 1139 |                 u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 
 | 1140 |                 return; | 
 | 1141 |         } | 
 | 1142 | } | 
 | 1143 |  | 
 | 1144 | static void u132_hcd_enumeration_address_sent(void *data, struct urb *urb, | 
 | 1145 |         u8 *buf, int len, int toggle_bits, int error_count, int condition_code, | 
 | 1146 |         int repeat_number, int halted, int skipped, int actual, int non_null) | 
 | 1147 | { | 
 | 1148 |         struct u132_endp *endp = data; | 
 | 1149 |         struct u132 *u132 = endp->u132; | 
 | 1150 |         down(&u132->scheduler_lock); | 
 | 1151 |         if (u132->going > 1) { | 
 | 1152 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 1153 |                         , u132->going); | 
 | 1154 |                 up(&u132->scheduler_lock); | 
 | 1155 |                 u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | 
 | 1156 |                 return; | 
 | 1157 |         } else if (endp->dequeueing) { | 
 | 1158 |                 endp->dequeueing = 0; | 
 | 1159 |                 up(&u132->scheduler_lock); | 
 | 1160 |                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 
 | 1161 |                 return; | 
 | 1162 |         } else if (u132->going > 0) { | 
 | 1163 |                 dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 
 | 1164 |                         "%p status=%d\n", urb, urb->status); | 
 | 1165 |                 up(&u132->scheduler_lock); | 
 | 1166 |                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 
 | 1167 |                 return; | 
 | 1168 |         } else if (urb->status == -EINPROGRESS) { | 
 | 1169 |                 int retval; | 
 | 1170 |                 struct u132_ring *ring = endp->ring; | 
 | 1171 |                 up(&u132->scheduler_lock); | 
 | 1172 |                 retval = usb_ftdi_elan_edset_input(u132->platform_dev, | 
 | 1173 |                         ring->number, endp, urb, 0, endp->usb_endp, 0, | 
 | 1174 |                         u132_hcd_enumeration_empty_recv); | 
 | 1175 |                 if (retval == 0) { | 
 | 1176 |                 } else | 
 | 1177 |                         u132_hcd_giveback_urb(u132, endp, urb, retval); | 
 | 1178 |                 return; | 
 | 1179 |         } else { | 
 | 1180 |                 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 
 | 1181 |                         "s=%d\n", urb, urb->status); | 
 | 1182 |                 up(&u132->scheduler_lock); | 
 | 1183 |                 u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 
 | 1184 |                 return; | 
 | 1185 |         } | 
 | 1186 | } | 
 | 1187 |  | 
 | 1188 | static void u132_hcd_initial_empty_sent(void *data, struct urb *urb, u8 *buf, | 
 | 1189 |         int len, int toggle_bits, int error_count, int condition_code, | 
 | 1190 |         int repeat_number, int halted, int skipped, int actual, int non_null) | 
 | 1191 | { | 
 | 1192 |         struct u132_endp *endp = data; | 
 | 1193 |         struct u132 *u132 = endp->u132; | 
 | 1194 |         down(&u132->scheduler_lock); | 
 | 1195 |         if (u132->going > 1) { | 
 | 1196 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 1197 |                         , u132->going); | 
 | 1198 |                 up(&u132->scheduler_lock); | 
 | 1199 |                 u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | 
 | 1200 |                 return; | 
 | 1201 |         } else if (endp->dequeueing) { | 
 | 1202 |                 endp->dequeueing = 0; | 
 | 1203 |                 up(&u132->scheduler_lock); | 
 | 1204 |                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 
 | 1205 |                 return; | 
 | 1206 |         } else if (u132->going > 0) { | 
 | 1207 |                 dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 
 | 1208 |                         "%p status=%d\n", urb, urb->status); | 
 | 1209 |                 up(&u132->scheduler_lock); | 
 | 1210 |                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 
 | 1211 |                 return; | 
 | 1212 |         } else if (urb->status == -EINPROGRESS) { | 
 | 1213 |                 up(&u132->scheduler_lock); | 
 | 1214 |                 u132_hcd_giveback_urb(u132, endp, urb, 0); | 
 | 1215 |                 return; | 
 | 1216 |         } else { | 
 | 1217 |                 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 
 | 1218 |                         "s=%d\n", urb, urb->status); | 
 | 1219 |                 up(&u132->scheduler_lock); | 
 | 1220 |                 u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 
 | 1221 |                 return; | 
 | 1222 |         } | 
 | 1223 | } | 
 | 1224 |  | 
 | 1225 | static void u132_hcd_initial_input_recv(void *data, struct urb *urb, u8 *buf, | 
 | 1226 |         int len, int toggle_bits, int error_count, int condition_code, | 
 | 1227 |         int repeat_number, int halted, int skipped, int actual, int non_null) | 
 | 1228 | { | 
 | 1229 |         struct u132_endp *endp = data; | 
 | 1230 |         struct u132 *u132 = endp->u132; | 
 | 1231 |         u8 address = u132->addr[endp->usb_addr].address; | 
 | 1232 |         down(&u132->scheduler_lock); | 
 | 1233 |         if (u132->going > 1) { | 
 | 1234 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 1235 |                         , u132->going); | 
 | 1236 |                 up(&u132->scheduler_lock); | 
 | 1237 |                 u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | 
 | 1238 |                 return; | 
 | 1239 |         } else if (endp->dequeueing) { | 
 | 1240 |                 endp->dequeueing = 0; | 
 | 1241 |                 up(&u132->scheduler_lock); | 
 | 1242 |                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 
 | 1243 |                 return; | 
 | 1244 |         } else if (u132->going > 0) { | 
 | 1245 |                 dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 
 | 1246 |                         "%p status=%d\n", urb, urb->status); | 
 | 1247 |                 up(&u132->scheduler_lock); | 
 | 1248 |                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 
 | 1249 |                 return; | 
 | 1250 |         } else if (urb->status == -EINPROGRESS) { | 
 | 1251 |                 int retval; | 
 | 1252 |                 struct u132_ring *ring = endp->ring; | 
 | 1253 |                 u8 *u = urb->transfer_buffer; | 
 | 1254 |                 u8 *b = buf; | 
 | 1255 |                 int L = len; | 
 | 1256 |                 while (L-- > 0) { | 
 | 1257 |                         *u++ = *b++; | 
 | 1258 |                 } | 
 | 1259 |                 urb->actual_length = len; | 
 | 1260 |                 up(&u132->scheduler_lock); | 
 | 1261 |                 retval = usb_ftdi_elan_edset_empty(u132->platform_dev, | 
 | 1262 |                         ring->number, endp, urb, address, endp->usb_endp, 0x3, | 
 | 1263 |                         u132_hcd_initial_empty_sent); | 
 | 1264 |                 if (retval == 0) { | 
 | 1265 |                 } else | 
 | 1266 |                         u132_hcd_giveback_urb(u132, endp, urb, retval); | 
 | 1267 |                 return; | 
 | 1268 |         } else { | 
 | 1269 |                 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 
 | 1270 |                         "s=%d\n", urb, urb->status); | 
 | 1271 |                 up(&u132->scheduler_lock); | 
 | 1272 |                 u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 
 | 1273 |                 return; | 
 | 1274 |         } | 
 | 1275 | } | 
 | 1276 |  | 
 | 1277 | static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf, | 
 | 1278 |         int len, int toggle_bits, int error_count, int condition_code, | 
 | 1279 |         int repeat_number, int halted, int skipped, int actual, int non_null) | 
 | 1280 | { | 
 | 1281 |         struct u132_endp *endp = data; | 
 | 1282 |         struct u132 *u132 = endp->u132; | 
 | 1283 |         u8 address = u132->addr[endp->usb_addr].address; | 
 | 1284 |         down(&u132->scheduler_lock); | 
 | 1285 |         if (u132->going > 1) { | 
 | 1286 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 1287 |                         , u132->going); | 
 | 1288 |                 up(&u132->scheduler_lock); | 
 | 1289 |                 u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | 
 | 1290 |                 return; | 
 | 1291 |         } else if (endp->dequeueing) { | 
 | 1292 |                 endp->dequeueing = 0; | 
 | 1293 |                 up(&u132->scheduler_lock); | 
 | 1294 |                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 
 | 1295 |                 return; | 
 | 1296 |         } else if (u132->going > 0) { | 
 | 1297 |                 dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 
 | 1298 |                         "%p status=%d\n", urb, urb->status); | 
 | 1299 |                 up(&u132->scheduler_lock); | 
 | 1300 |                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 
 | 1301 |                 return; | 
 | 1302 |         } else if (urb->status == -EINPROGRESS) { | 
 | 1303 |                 int retval; | 
 | 1304 |                 struct u132_ring *ring = endp->ring; | 
 | 1305 |                 up(&u132->scheduler_lock); | 
 | 1306 |                 retval = usb_ftdi_elan_edset_input(u132->platform_dev, | 
 | 1307 |                         ring->number, endp, urb, address, endp->usb_endp, 0, | 
 | 1308 |                         u132_hcd_initial_input_recv); | 
 | 1309 |                 if (retval == 0) { | 
 | 1310 |                 } else | 
 | 1311 |                         u132_hcd_giveback_urb(u132, endp, urb, retval); | 
 | 1312 |                 return; | 
 | 1313 |         } else { | 
 | 1314 |                 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 
 | 1315 |                         "s=%d\n", urb, urb->status); | 
 | 1316 |                 up(&u132->scheduler_lock); | 
 | 1317 |                 u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 
 | 1318 |                 return; | 
 | 1319 |         } | 
 | 1320 | } | 
 | 1321 |  | 
 | 1322 | static void u132_hcd_ring_work_scheduler(void *data); | 
 | 1323 | static void u132_hcd_endp_work_scheduler(void *data); | 
 | 1324 | /* | 
 | 1325 | * this work function is only executed from the work queue | 
 | 1326 | * | 
 | 1327 | */ | 
 | 1328 | static void u132_hcd_ring_work_scheduler(void *data) | 
 | 1329 | { | 
 | 1330 |         struct u132_ring *ring = data; | 
 | 1331 |         struct u132 *u132 = ring->u132; | 
 | 1332 |         down(&u132->scheduler_lock); | 
 | 1333 |         if (ring->in_use) { | 
 | 1334 |                 up(&u132->scheduler_lock); | 
 | 1335 |                 u132_ring_put_kref(u132, ring); | 
 | 1336 |                 return; | 
 | 1337 |         } else if (ring->curr_endp) { | 
 | 1338 |                 struct u132_endp *last_endp = ring->curr_endp; | 
 | 1339 |                 struct list_head *scan; | 
 | 1340 |                 struct list_head *head = &last_endp->endp_ring; | 
 | 1341 |                 unsigned long wakeup = 0; | 
 | 1342 |                 list_for_each(scan, head) { | 
 | 1343 |                         struct u132_endp *endp = list_entry(scan, | 
 | 1344 |                                 struct u132_endp, endp_ring); | 
 | 1345 |                         if (endp->queue_next == endp->queue_last) { | 
 | 1346 |                         } else if ((endp->delayed == 0) | 
 | 1347 |                                 || time_after_eq(jiffies, endp->jiffies)) { | 
 | 1348 |                                 ring->curr_endp = endp; | 
 | 1349 |                                 u132_endp_cancel_work(u132, last_endp); | 
 | 1350 |                                 u132_endp_queue_work(u132, last_endp, 0); | 
 | 1351 |                                 up(&u132->scheduler_lock); | 
 | 1352 |                                 u132_ring_put_kref(u132, ring); | 
 | 1353 |                                 return; | 
 | 1354 |                         } else { | 
 | 1355 |                                 unsigned long delta = endp->jiffies - jiffies; | 
 | 1356 |                                 if (delta > wakeup) | 
 | 1357 |                                         wakeup = delta; | 
 | 1358 |                         } | 
 | 1359 |                 } | 
 | 1360 |                 if (last_endp->queue_next == last_endp->queue_last) { | 
 | 1361 |                 } else if ((last_endp->delayed == 0) || time_after_eq(jiffies, | 
 | 1362 |                         last_endp->jiffies)) { | 
 | 1363 |                         u132_endp_cancel_work(u132, last_endp); | 
 | 1364 |                         u132_endp_queue_work(u132, last_endp, 0); | 
 | 1365 |                         up(&u132->scheduler_lock); | 
 | 1366 |                         u132_ring_put_kref(u132, ring); | 
 | 1367 |                         return; | 
 | 1368 |                 } else { | 
 | 1369 |                         unsigned long delta = last_endp->jiffies - jiffies; | 
 | 1370 |                         if (delta > wakeup) | 
 | 1371 |                                 wakeup = delta; | 
 | 1372 |                 } | 
 | 1373 |                 if (wakeup > 0) { | 
 | 1374 |                         u132_ring_requeue_work(u132, ring, wakeup); | 
 | 1375 |                         up(&u132->scheduler_lock); | 
 | 1376 |                         return; | 
 | 1377 |                 } else { | 
 | 1378 |                         up(&u132->scheduler_lock); | 
 | 1379 |                         u132_ring_put_kref(u132, ring); | 
 | 1380 |                         return; | 
 | 1381 |                 } | 
 | 1382 |         } else { | 
 | 1383 |                 up(&u132->scheduler_lock); | 
 | 1384 |                 u132_ring_put_kref(u132, ring); | 
 | 1385 |                 return; | 
 | 1386 |         } | 
 | 1387 | } | 
 | 1388 |  | 
 | 1389 | static void u132_hcd_endp_work_scheduler(void *data) | 
 | 1390 | { | 
 | 1391 |         struct u132_ring *ring; | 
 | 1392 |         struct u132_endp *endp = data; | 
 | 1393 |         struct u132 *u132 = endp->u132; | 
 | 1394 |         down(&u132->scheduler_lock); | 
 | 1395 |         ring = endp->ring; | 
 | 1396 |         if (endp->edset_flush) { | 
 | 1397 |                 endp->edset_flush = 0; | 
 | 1398 |                 if (endp->dequeueing) | 
 | 1399 |                         usb_ftdi_elan_edset_flush(u132->platform_dev, | 
 | 1400 |                                 ring->number, endp); | 
 | 1401 |                 up(&u132->scheduler_lock); | 
 | 1402 |                 u132_endp_put_kref(u132, endp); | 
 | 1403 |                 return; | 
 | 1404 |         } else if (endp->active) { | 
 | 1405 |                 up(&u132->scheduler_lock); | 
 | 1406 |                 u132_endp_put_kref(u132, endp); | 
 | 1407 |                 return; | 
 | 1408 |         } else if (ring->in_use) { | 
 | 1409 |                 up(&u132->scheduler_lock); | 
 | 1410 |                 u132_endp_put_kref(u132, endp); | 
 | 1411 |                 return; | 
 | 1412 |         } else if (endp->queue_next == endp->queue_last) { | 
 | 1413 |                 up(&u132->scheduler_lock); | 
 | 1414 |                 u132_endp_put_kref(u132, endp); | 
 | 1415 |                 return; | 
 | 1416 |         } else if (endp->pipetype == PIPE_INTERRUPT) { | 
 | 1417 |                 u8 address = u132->addr[endp->usb_addr].address; | 
 | 1418 |                 if (ring->in_use) { | 
 | 1419 |                         up(&u132->scheduler_lock); | 
 | 1420 |                         u132_endp_put_kref(u132, endp); | 
 | 1421 |                         return; | 
 | 1422 |                 } else { | 
 | 1423 |                         int retval; | 
 | 1424 |                         struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK & | 
 | 1425 |                                 endp->queue_next]; | 
 | 1426 |                         endp->active = 1; | 
 | 1427 |                         ring->curr_endp = endp; | 
 | 1428 |                         ring->in_use = 1; | 
 | 1429 |                         up(&u132->scheduler_lock); | 
 | 1430 |                         retval = edset_single(u132, ring, endp, urb, address, | 
 | 1431 |                                 endp->toggle_bits, u132_hcd_interrupt_recv); | 
 | 1432 |                         if (retval == 0) { | 
 | 1433 |                         } else | 
 | 1434 |                                 u132_hcd_giveback_urb(u132, endp, urb, retval); | 
 | 1435 |                         return; | 
 | 1436 |                 } | 
 | 1437 |         } else if (endp->pipetype == PIPE_CONTROL) { | 
 | 1438 |                 u8 address = u132->addr[endp->usb_addr].address; | 
 | 1439 |                 if (ring->in_use) { | 
 | 1440 |                         up(&u132->scheduler_lock); | 
 | 1441 |                         u132_endp_put_kref(u132, endp); | 
 | 1442 |                         return; | 
 | 1443 |                 } else if (address == 0) { | 
 | 1444 |                         int retval; | 
 | 1445 |                         struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK & | 
 | 1446 |                                 endp->queue_next]; | 
 | 1447 |                         endp->active = 1; | 
 | 1448 |                         ring->curr_endp = endp; | 
 | 1449 |                         ring->in_use = 1; | 
 | 1450 |                         up(&u132->scheduler_lock); | 
 | 1451 |                         retval = edset_setup(u132, ring, endp, urb, address, | 
 | 1452 |                                 0x2, u132_hcd_initial_setup_sent); | 
 | 1453 |                         if (retval == 0) { | 
 | 1454 |                         } else | 
 | 1455 |                                 u132_hcd_giveback_urb(u132, endp, urb, retval); | 
 | 1456 |                         return; | 
 | 1457 |                 } else if (endp->usb_addr == 0) { | 
 | 1458 |                         int retval; | 
 | 1459 |                         struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK & | 
 | 1460 |                                 endp->queue_next]; | 
 | 1461 |                         endp->active = 1; | 
 | 1462 |                         ring->curr_endp = endp; | 
 | 1463 |                         ring->in_use = 1; | 
 | 1464 |                         up(&u132->scheduler_lock); | 
 | 1465 |                         retval = edset_setup(u132, ring, endp, urb, 0, 0x2, | 
 | 1466 |                                 u132_hcd_enumeration_address_sent); | 
 | 1467 |                         if (retval == 0) { | 
 | 1468 |                         } else | 
 | 1469 |                                 u132_hcd_giveback_urb(u132, endp, urb, retval); | 
 | 1470 |                         return; | 
 | 1471 |                 } else { | 
 | 1472 |                         int retval; | 
 | 1473 |                         u8 address = u132->addr[endp->usb_addr].address; | 
 | 1474 |                         struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK & | 
 | 1475 |                                 endp->queue_next]; | 
 | 1476 |                         endp->active = 1; | 
 | 1477 |                         ring->curr_endp = endp; | 
 | 1478 |                         ring->in_use = 1; | 
 | 1479 |                         up(&u132->scheduler_lock); | 
 | 1480 |                         retval = edset_setup(u132, ring, endp, urb, address, | 
 | 1481 |                                 0x2, u132_hcd_configure_setup_sent); | 
 | 1482 |                         if (retval == 0) { | 
 | 1483 |                         } else | 
 | 1484 |                                 u132_hcd_giveback_urb(u132, endp, urb, retval); | 
 | 1485 |                         return; | 
 | 1486 |                 } | 
 | 1487 |         } else { | 
 | 1488 |                 if (endp->input) { | 
 | 1489 |                         u8 address = u132->addr[endp->usb_addr].address; | 
 | 1490 |                         if (ring->in_use) { | 
 | 1491 |                                 up(&u132->scheduler_lock); | 
 | 1492 |                                 u132_endp_put_kref(u132, endp); | 
 | 1493 |                                 return; | 
 | 1494 |                         } else { | 
 | 1495 |                                 int retval; | 
 | 1496 |                                 struct urb *urb = endp->urb_list[ | 
 | 1497 |                                         ENDP_QUEUE_MASK & endp->queue_next]; | 
 | 1498 |                                 endp->active = 1; | 
 | 1499 |                                 ring->curr_endp = endp; | 
 | 1500 |                                 ring->in_use = 1; | 
 | 1501 |                                 up(&u132->scheduler_lock); | 
 | 1502 |                                 retval = edset_input(u132, ring, endp, urb, | 
 | 1503 |                                         address, endp->toggle_bits, | 
 | 1504 |                                         u132_hcd_bulk_input_recv); | 
 | 1505 |                                 if (retval == 0) { | 
 | 1506 |                                 } else | 
 | 1507 |                                         u132_hcd_giveback_urb(u132, endp, urb, | 
 | 1508 |                                                 retval); | 
 | 1509 |                                 return; | 
 | 1510 |                         } | 
 | 1511 |                 } else {        /* output pipe */ | 
 | 1512 |                         u8 address = u132->addr[endp->usb_addr].address; | 
 | 1513 |                         if (ring->in_use) { | 
 | 1514 |                                 up(&u132->scheduler_lock); | 
 | 1515 |                                 u132_endp_put_kref(u132, endp); | 
 | 1516 |                                 return; | 
 | 1517 |                         } else { | 
 | 1518 |                                 int retval; | 
 | 1519 |                                 struct urb *urb = endp->urb_list[ | 
 | 1520 |                                         ENDP_QUEUE_MASK & endp->queue_next]; | 
 | 1521 |                                 endp->active = 1; | 
 | 1522 |                                 ring->curr_endp = endp; | 
 | 1523 |                                 ring->in_use = 1; | 
 | 1524 |                                 up(&u132->scheduler_lock); | 
 | 1525 |                                 retval = edset_output(u132, ring, endp, urb, | 
 | 1526 |                                         address, endp->toggle_bits, | 
 | 1527 |                                         u132_hcd_bulk_output_sent); | 
 | 1528 |                                 if (retval == 0) { | 
 | 1529 |                                 } else | 
 | 1530 |                                         u132_hcd_giveback_urb(u132, endp, urb, | 
 | 1531 |                                                 retval); | 
 | 1532 |                                 return; | 
 | 1533 |                         } | 
 | 1534 |                 } | 
 | 1535 |         } | 
 | 1536 | } | 
 | 1537 |  | 
 | 1538 | static void port_power(struct u132 *u132, int pn, int is_on) | 
 | 1539 | { | 
 | 1540 |         u132->port[pn].power = is_on; | 
 | 1541 | } | 
 | 1542 |  | 
 | 1543 | static void u132_power(struct u132 *u132, int is_on) | 
 | 1544 | { | 
 | 1545 |         struct usb_hcd *hcd = u132_to_hcd(u132) | 
 | 1546 |                 ;        /* hub is inactive unless the port is powered */ | 
 | 1547 |         if (is_on) { | 
 | 1548 |                 if (u132->power) | 
 | 1549 |                         return; | 
 | 1550 |                 u132->power = 1; | 
 | 1551 |                 hcd->self.controller->power.power_state = PMSG_ON; | 
 | 1552 |         } else { | 
 | 1553 |                 u132->power = 0; | 
 | 1554 |                 hcd->state = HC_STATE_HALT; | 
 | 1555 |                 hcd->self.controller->power.power_state = PMSG_SUSPEND; | 
 | 1556 |         } | 
 | 1557 | } | 
 | 1558 |  | 
 | 1559 | static int u132_periodic_reinit(struct u132 *u132) | 
 | 1560 | { | 
 | 1561 |         int retval; | 
 | 1562 |         u32 fi = u132->hc_fminterval & 0x03fff; | 
 | 1563 |         u32 fit; | 
 | 1564 |         u32 fminterval; | 
 | 1565 |         retval = u132_read_pcimem(u132, fminterval, &fminterval); | 
 | 1566 |         if (retval) | 
 | 1567 |                 return retval; | 
 | 1568 |         fit = fminterval & FIT; | 
 | 1569 |         retval = u132_write_pcimem(u132, fminterval, | 
 | 1570 |                 (fit ^ FIT) | u132->hc_fminterval); | 
 | 1571 |         if (retval) | 
 | 1572 |                 return retval; | 
 | 1573 |         retval = u132_write_pcimem(u132, periodicstart, | 
 | 1574 |                 ((9 *fi) / 10) & 0x3fff); | 
 | 1575 |         if (retval) | 
 | 1576 |                 return retval; | 
 | 1577 |         return 0; | 
 | 1578 | } | 
 | 1579 |  | 
 | 1580 | static char *hcfs2string(int state) | 
 | 1581 | { | 
 | 1582 |         switch (state) { | 
 | 1583 |         case OHCI_USB_RESET: | 
 | 1584 |                 return "reset"; | 
 | 1585 |         case OHCI_USB_RESUME: | 
 | 1586 |                 return "resume"; | 
 | 1587 |         case OHCI_USB_OPER: | 
 | 1588 |                 return "operational"; | 
 | 1589 |         case OHCI_USB_SUSPEND: | 
 | 1590 |                 return "suspend"; | 
 | 1591 |         } | 
 | 1592 |         return "?"; | 
 | 1593 | } | 
 | 1594 |  | 
 | 1595 | static int u132_usb_reset(struct u132 *u132) | 
 | 1596 | { | 
 | 1597 |         int retval; | 
 | 1598 |         retval = u132_read_pcimem(u132, control, &u132->hc_control); | 
 | 1599 |         if (retval) | 
 | 1600 |                 return retval; | 
 | 1601 |         u132->hc_control &= OHCI_CTRL_RWC; | 
 | 1602 |         retval = u132_write_pcimem(u132, control, u132->hc_control); | 
 | 1603 |         if (retval) | 
 | 1604 |                 return retval; | 
 | 1605 |         return 0; | 
 | 1606 | } | 
 | 1607 |  | 
 | 1608 | static int u132_init(struct u132 *u132) | 
 | 1609 | { | 
 | 1610 |         int retval; | 
 | 1611 |         u32 control; | 
 | 1612 |         u132_disable(u132); | 
 | 1613 |         u132->next_statechange = | 
 | 1614 |                 jiffies; /* SMM owns the HC? not for long! */  { | 
 | 1615 |                 u32 control; | 
 | 1616 |                 retval = u132_read_pcimem(u132, control, &control); | 
 | 1617 |                 if (retval) | 
 | 1618 |                         return retval; | 
 | 1619 |                 if (control & OHCI_CTRL_IR) { | 
 | 1620 |                         u32 temp = 50; | 
 | 1621 |                         retval = u132_write_pcimem(u132, intrenable, | 
 | 1622 |                                 OHCI_INTR_OC); | 
 | 1623 |                         if (retval) | 
 | 1624 |                                 return retval; | 
 | 1625 |                         retval = u132_write_pcimem_byte(u132, cmdstatus, | 
 | 1626 |                                 OHCI_OCR); | 
 | 1627 |                         if (retval) | 
 | 1628 |                                 return retval; | 
 | 1629 |                       check:{ | 
 | 1630 |                                 retval = u132_read_pcimem(u132, control, | 
 | 1631 |                                         &control); | 
 | 1632 |                                 if (retval) | 
 | 1633 |                                         return retval; | 
 | 1634 |                         } | 
 | 1635 |                         if (control & OHCI_CTRL_IR) { | 
 | 1636 |                                 msleep(10); | 
 | 1637 |                                 if (--temp == 0) { | 
 | 1638 |                                         dev_err(&u132->platform_dev->dev, "USB " | 
 | 1639 |                                                 "HC takeover failed!(BIOS/SMM b" | 
 | 1640 |                                                 "ug) control=%08X\n", control); | 
 | 1641 |                                         return -EBUSY; | 
 | 1642 |                                 } | 
 | 1643 |                                 goto check; | 
 | 1644 |                         } | 
 | 1645 |                         u132_usb_reset(u132); | 
 | 1646 |                 } | 
 | 1647 |         } | 
 | 1648 |         retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE); | 
 | 1649 |         if (retval) | 
 | 1650 |                 return retval; | 
 | 1651 |         retval = u132_read_pcimem(u132, control, &control); | 
 | 1652 |         if (retval) | 
 | 1653 |                 return retval; | 
 | 1654 |         if (u132->num_ports == 0) { | 
 | 1655 |                 u32 rh_a = -1; | 
 | 1656 |                 retval = u132_read_pcimem(u132, roothub.a, &rh_a); | 
 | 1657 |                 if (retval) | 
 | 1658 |                         return retval; | 
 | 1659 |                 u132->num_ports = rh_a & RH_A_NDP; | 
 | 1660 |                 retval = read_roothub_info(u132); | 
 | 1661 |                 if (retval) | 
 | 1662 |                         return retval; | 
 | 1663 |         } | 
 | 1664 |         if (u132->num_ports > MAX_U132_PORTS) { | 
 | 1665 |                 return -EINVAL; | 
 | 1666 |         } | 
 | 1667 |         return 0; | 
 | 1668 | } | 
 | 1669 |  | 
 | 1670 |  | 
 | 1671 | /* Start an OHCI controller, set the BUS operational | 
 | 1672 | * resets USB and controller | 
 | 1673 | * enable interrupts | 
 | 1674 | */ | 
 | 1675 | static int u132_run(struct u132 *u132) | 
 | 1676 | { | 
 | 1677 |         int retval; | 
 | 1678 |         u32 control; | 
 | 1679 |         u32 status; | 
 | 1680 |         u32 fminterval; | 
 | 1681 |         u32 periodicstart; | 
 | 1682 |         u32 cmdstatus; | 
 | 1683 |         u32 roothub_a; | 
 | 1684 |         int mask = OHCI_INTR_INIT; | 
 | 1685 |         int first = u132->hc_fminterval == 0; | 
 | 1686 |         int sleep_time = 0; | 
 | 1687 |         int reset_timeout = 30;        /* ... allow extra time */ | 
 | 1688 |         u132_disable(u132); | 
 | 1689 |         if (first) { | 
 | 1690 |                 u32 temp; | 
 | 1691 |                 retval = u132_read_pcimem(u132, fminterval, &temp); | 
 | 1692 |                 if (retval) | 
 | 1693 |                         return retval; | 
 | 1694 |                 u132->hc_fminterval = temp & 0x3fff; | 
 | 1695 |                 if (u132->hc_fminterval != FI) { | 
 | 1696 |                 } | 
 | 1697 |                 u132->hc_fminterval |= FSMP(u132->hc_fminterval) << 16; | 
 | 1698 |         } | 
 | 1699 |         retval = u132_read_pcimem(u132, control, &u132->hc_control); | 
 | 1700 |         if (retval) | 
 | 1701 |                 return retval; | 
 | 1702 |         dev_info(&u132->platform_dev->dev, "resetting from state '%s', control " | 
 | 1703 |                 "= %08X\n", hcfs2string(u132->hc_control & OHCI_CTRL_HCFS), | 
 | 1704 |                 u132->hc_control); | 
 | 1705 |         switch (u132->hc_control & OHCI_CTRL_HCFS) { | 
 | 1706 |         case OHCI_USB_OPER: | 
 | 1707 |                 sleep_time = 0; | 
 | 1708 |                 break; | 
 | 1709 |         case OHCI_USB_SUSPEND: | 
 | 1710 |         case OHCI_USB_RESUME: | 
 | 1711 |                 u132->hc_control &= OHCI_CTRL_RWC; | 
 | 1712 |                 u132->hc_control |= OHCI_USB_RESUME; | 
 | 1713 |                 sleep_time = 10; | 
 | 1714 |                 break; | 
 | 1715 |         default: | 
 | 1716 |                 u132->hc_control &= OHCI_CTRL_RWC; | 
 | 1717 |                 u132->hc_control |= OHCI_USB_RESET; | 
 | 1718 |                 sleep_time = 50; | 
 | 1719 |                 break; | 
 | 1720 |         } | 
 | 1721 |         retval = u132_write_pcimem(u132, control, u132->hc_control); | 
 | 1722 |         if (retval) | 
 | 1723 |                 return retval; | 
 | 1724 |         retval = u132_read_pcimem(u132, control, &control); | 
 | 1725 |         if (retval) | 
 | 1726 |                 return retval; | 
 | 1727 |         msleep(sleep_time); | 
 | 1728 |         retval = u132_read_pcimem(u132, roothub.a, &roothub_a); | 
 | 1729 |         if (retval) | 
 | 1730 |                 return retval; | 
 | 1731 |         if (!(roothub_a & RH_A_NPS)) { | 
 | 1732 |                 int temp;        /* power down each port */ | 
 | 1733 |                 for (temp = 0; temp < u132->num_ports; temp++) { | 
 | 1734 |                         retval = u132_write_pcimem(u132, | 
 | 1735 |                                 roothub.portstatus[temp], RH_PS_LSDA); | 
 | 1736 |                         if (retval) | 
 | 1737 |                                 return retval; | 
 | 1738 |                 } | 
 | 1739 |         } | 
 | 1740 |         retval = u132_read_pcimem(u132, control, &control); | 
 | 1741 |         if (retval) | 
 | 1742 |                 return retval; | 
 | 1743 |       retry:retval = u132_read_pcimem(u132, cmdstatus, &status); | 
 | 1744 |         if (retval) | 
 | 1745 |                 return retval; | 
 | 1746 |         retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_HCR); | 
 | 1747 |         if (retval) | 
 | 1748 |                 return retval; | 
 | 1749 |       extra:{ | 
 | 1750 |                 retval = u132_read_pcimem(u132, cmdstatus, &status); | 
 | 1751 |                 if (retval) | 
 | 1752 |                         return retval; | 
 | 1753 |                 if (0 != (status & OHCI_HCR)) { | 
 | 1754 |                         if (--reset_timeout == 0) { | 
 | 1755 |                                 dev_err(&u132->platform_dev->dev, "USB HC reset" | 
 | 1756 |                                         " timed out!\n"); | 
 | 1757 |                                 return -ENODEV; | 
 | 1758 |                         } else { | 
 | 1759 |                                 msleep(5); | 
 | 1760 |                                 goto extra; | 
 | 1761 |                         } | 
 | 1762 |                 } | 
 | 1763 |         } | 
 | 1764 |         if (u132->flags & OHCI_QUIRK_INITRESET) { | 
 | 1765 |                 retval = u132_write_pcimem(u132, control, u132->hc_control); | 
 | 1766 |                 if (retval) | 
 | 1767 |                         return retval; | 
 | 1768 |                 retval = u132_read_pcimem(u132, control, &control); | 
 | 1769 |                 if (retval) | 
 | 1770 |                         return retval; | 
 | 1771 |         } | 
 | 1772 |         retval = u132_write_pcimem(u132, ed_controlhead, 0x00000000); | 
 | 1773 |         if (retval) | 
 | 1774 |                 return retval; | 
 | 1775 |         retval = u132_write_pcimem(u132, ed_bulkhead, 0x11000000); | 
 | 1776 |         if (retval) | 
 | 1777 |                 return retval; | 
 | 1778 |         retval = u132_write_pcimem(u132, hcca, 0x00000000); | 
 | 1779 |         if (retval) | 
 | 1780 |                 return retval; | 
 | 1781 |         retval = u132_periodic_reinit(u132); | 
 | 1782 |         if (retval) | 
 | 1783 |                 return retval; | 
 | 1784 |         retval = u132_read_pcimem(u132, fminterval, &fminterval); | 
 | 1785 |         if (retval) | 
 | 1786 |                 return retval; | 
 | 1787 |         retval = u132_read_pcimem(u132, periodicstart, &periodicstart); | 
 | 1788 |         if (retval) | 
 | 1789 |                 return retval; | 
 | 1790 |         if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) { | 
 | 1791 |                 if (!(u132->flags & OHCI_QUIRK_INITRESET)) { | 
 | 1792 |                         u132->flags |= OHCI_QUIRK_INITRESET; | 
 | 1793 |                         goto retry; | 
 | 1794 |                 } else | 
 | 1795 |                         dev_err(&u132->platform_dev->dev, "init err(%08x %04x)" | 
 | 1796 |                                 "\n", fminterval, periodicstart); | 
 | 1797 |         }                        /* start controller operations */ | 
 | 1798 |         u132->hc_control &= OHCI_CTRL_RWC; | 
 | 1799 |         u132->hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER; | 
 | 1800 |         retval = u132_write_pcimem(u132, control, u132->hc_control); | 
 | 1801 |         if (retval) | 
 | 1802 |                 return retval; | 
 | 1803 |         retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_BLF); | 
 | 1804 |         if (retval) | 
 | 1805 |                 return retval; | 
 | 1806 |         retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus); | 
 | 1807 |         if (retval) | 
 | 1808 |                 return retval; | 
 | 1809 |         retval = u132_read_pcimem(u132, control, &control); | 
 | 1810 |         if (retval) | 
 | 1811 |                 return retval; | 
 | 1812 |         u132_to_hcd(u132)->state = HC_STATE_RUNNING; | 
 | 1813 |         retval = u132_write_pcimem(u132, roothub.status, RH_HS_DRWE); | 
 | 1814 |         if (retval) | 
 | 1815 |                 return retval; | 
 | 1816 |         retval = u132_write_pcimem(u132, intrstatus, mask); | 
 | 1817 |         if (retval) | 
 | 1818 |                 return retval; | 
 | 1819 |         retval = u132_write_pcimem(u132, intrdisable, | 
 | 1820 |                 OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO | | 
 | 1821 |                 OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH | | 
 | 1822 |                 OHCI_INTR_SO); | 
 | 1823 |         if (retval) | 
 | 1824 |                 return retval;        /* handle root hub init quirks ... */ | 
 | 1825 |         retval = u132_read_pcimem(u132, roothub.a, &roothub_a); | 
 | 1826 |         if (retval) | 
 | 1827 |                 return retval; | 
 | 1828 |         roothub_a &= ~(RH_A_PSM | RH_A_OCPM); | 
 | 1829 |         if (u132->flags & OHCI_QUIRK_SUPERIO) { | 
 | 1830 |                 roothub_a |= RH_A_NOCP; | 
 | 1831 |                 roothub_a &= ~(RH_A_POTPGT | RH_A_NPS); | 
 | 1832 |                 retval = u132_write_pcimem(u132, roothub.a, roothub_a); | 
 | 1833 |                 if (retval) | 
 | 1834 |                         return retval; | 
 | 1835 |         } else if ((u132->flags & OHCI_QUIRK_AMD756) || distrust_firmware) { | 
 | 1836 |                 roothub_a |= RH_A_NPS; | 
 | 1837 |                 retval = u132_write_pcimem(u132, roothub.a, roothub_a); | 
 | 1838 |                 if (retval) | 
 | 1839 |                         return retval; | 
 | 1840 |         } | 
 | 1841 |         retval = u132_write_pcimem(u132, roothub.status, RH_HS_LPSC); | 
 | 1842 |         if (retval) | 
 | 1843 |                 return retval; | 
 | 1844 |         retval = u132_write_pcimem(u132, roothub.b, | 
 | 1845 |                 (roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM); | 
 | 1846 |         if (retval) | 
 | 1847 |                 return retval; | 
 | 1848 |         retval = u132_read_pcimem(u132, control, &control); | 
 | 1849 |         if (retval) | 
 | 1850 |                 return retval; | 
 | 1851 |         mdelay((roothub_a >> 23) & 0x1fe); | 
 | 1852 |         u132_to_hcd(u132)->state = HC_STATE_RUNNING; | 
 | 1853 |         return 0; | 
 | 1854 | } | 
 | 1855 |  | 
 | 1856 | static void u132_hcd_stop(struct usb_hcd *hcd) | 
 | 1857 | { | 
 | 1858 |         struct u132 *u132 = hcd_to_u132(hcd); | 
 | 1859 |         if (u132->going > 1) { | 
 | 1860 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 1861 |                         , u132->going); | 
 | 1862 |         } else if (u132->going > 0) { | 
 | 1863 |                 dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov" | 
 | 1864 |                         "ed\n", hcd); | 
 | 1865 |         } else { | 
 | 1866 |                 down(&u132->sw_lock); | 
 | 1867 |                 msleep(100); | 
 | 1868 |                 u132_power(u132, 0); | 
 | 1869 |                 up(&u132->sw_lock); | 
 | 1870 |         } | 
 | 1871 | } | 
 | 1872 |  | 
 | 1873 | static int u132_hcd_start(struct usb_hcd *hcd) | 
 | 1874 | { | 
 | 1875 |         struct u132 *u132 = hcd_to_u132(hcd); | 
 | 1876 |         if (u132->going > 1) { | 
 | 1877 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 1878 |                         , u132->going); | 
 | 1879 |                 return -ENODEV; | 
 | 1880 |         } else if (u132->going > 0) { | 
 | 1881 |                 dev_err(&u132->platform_dev->dev, "device is being removed\n"); | 
 | 1882 |                 return -ESHUTDOWN; | 
 | 1883 |         } else if (hcd->self.controller) { | 
 | 1884 |                 int retval; | 
 | 1885 |                 struct platform_device *pdev = | 
 | 1886 |                         to_platform_device(hcd->self.controller); | 
 | 1887 |                 u16 vendor = ((struct u132_platform_data *) | 
 | 1888 |                         (pdev->dev.platform_data))->vendor; | 
 | 1889 |                 u16 device = ((struct u132_platform_data *) | 
 | 1890 |                         (pdev->dev.platform_data))->device; | 
 | 1891 |                 down(&u132->sw_lock); | 
 | 1892 |                 msleep(10); | 
 | 1893 |                 if (vendor == PCI_VENDOR_ID_AMD && device == 0x740c) { | 
 | 1894 |                         u132->flags = OHCI_QUIRK_AMD756; | 
 | 1895 |                 } else if (vendor == PCI_VENDOR_ID_OPTI && device == 0xc861) { | 
 | 1896 |                         dev_err(&u132->platform_dev->dev, "WARNING: OPTi workar" | 
 | 1897 |                                 "ounds unavailable\n"); | 
 | 1898 |                 } else if (vendor == PCI_VENDOR_ID_COMPAQ && device == 0xa0f8) | 
 | 1899 |                         u132->flags |= OHCI_QUIRK_ZFMICRO; | 
 | 1900 |                 retval = u132_run(u132); | 
 | 1901 |                 if (retval) { | 
 | 1902 |                         u132_disable(u132); | 
 | 1903 |                         u132->going = 1; | 
 | 1904 |                 } | 
 | 1905 |                 msleep(100); | 
 | 1906 |                 up(&u132->sw_lock); | 
 | 1907 |                 return retval; | 
 | 1908 |         } else { | 
 | 1909 |                 dev_err(&u132->platform_dev->dev, "platform_device missing\n"); | 
 | 1910 |                 return -ENODEV; | 
 | 1911 |         } | 
 | 1912 | } | 
 | 1913 |  | 
 | 1914 | static int u132_hcd_reset(struct usb_hcd *hcd) | 
 | 1915 | { | 
 | 1916 |         struct u132 *u132 = hcd_to_u132(hcd); | 
 | 1917 |         if (u132->going > 1) { | 
 | 1918 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 1919 |                         , u132->going); | 
 | 1920 |                 return -ENODEV; | 
 | 1921 |         } else if (u132->going > 0) { | 
 | 1922 |                 dev_err(&u132->platform_dev->dev, "device is being removed\n"); | 
 | 1923 |                 return -ESHUTDOWN; | 
 | 1924 |         } else { | 
 | 1925 |                 int retval; | 
 | 1926 |                 down(&u132->sw_lock); | 
 | 1927 |                 retval = u132_init(u132); | 
 | 1928 |                 if (retval) { | 
 | 1929 |                         u132_disable(u132); | 
 | 1930 |                         u132->going = 1; | 
 | 1931 |                 } | 
 | 1932 |                 up(&u132->sw_lock); | 
 | 1933 |                 return retval; | 
 | 1934 |         } | 
 | 1935 | } | 
 | 1936 |  | 
 | 1937 | static int create_endpoint_and_queue_int(struct u132 *u132, | 
 | 1938 |         struct u132_udev *udev, struct usb_host_endpoint *hep, struct urb *urb, | 
 | 1939 |         struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address, | 
 | 1940 |         gfp_t mem_flags) | 
 | 1941 | { | 
 | 1942 |         struct u132_ring *ring; | 
 | 1943 |         unsigned long irqs; | 
 | 1944 |         u8 endp_number = ++u132->num_endpoints; | 
 | 1945 |         struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] = | 
 | 1946 |                 kmalloc(sizeof(struct u132_endp), mem_flags); | 
 | 1947 |         if (!endp) { | 
 | 1948 |                 return -ENOMEM; | 
 | 1949 |         } | 
 | 1950 |         INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp); | 
 | 1951 |         spin_lock_init(&endp->queue_lock.slock); | 
 | 1952 |         INIT_LIST_HEAD(&endp->urb_more); | 
 | 1953 |         ring = endp->ring = &u132->ring[0]; | 
 | 1954 |         if (ring->curr_endp) { | 
 | 1955 |                 list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring); | 
 | 1956 |         } else { | 
 | 1957 |                 INIT_LIST_HEAD(&endp->endp_ring); | 
 | 1958 |                 ring->curr_endp = endp; | 
 | 1959 |         } | 
 | 1960 |         ring->length += 1; | 
 | 1961 |         endp->dequeueing = 0; | 
 | 1962 |         endp->edset_flush = 0; | 
 | 1963 |         endp->active = 0; | 
 | 1964 |         endp->delayed = 0; | 
 | 1965 |         endp->endp_number = endp_number; | 
 | 1966 |         endp->u132 = u132; | 
 | 1967 |         endp->hep = hep; | 
 | 1968 |         endp->pipetype = usb_pipetype(urb->pipe); | 
 | 1969 |         u132_endp_init_kref(u132, endp); | 
 | 1970 |         if (usb_pipein(urb->pipe)) { | 
 | 1971 |                 endp->toggle_bits = 0x2; | 
 | 1972 |                 usb_settoggle(udev->usb_device, usb_endp, 0, 0); | 
 | 1973 |                 endp->input = 1; | 
 | 1974 |                 endp->output = 0; | 
 | 1975 |                 udev->endp_number_in[usb_endp] = endp_number; | 
 | 1976 |                 u132_udev_get_kref(u132, udev); | 
 | 1977 |         } else { | 
 | 1978 |                 endp->toggle_bits = 0x2; | 
 | 1979 |                 usb_settoggle(udev->usb_device, usb_endp, 1, 0); | 
 | 1980 |                 endp->input = 0; | 
 | 1981 |                 endp->output = 1; | 
 | 1982 |                 udev->endp_number_out[usb_endp] = endp_number; | 
 | 1983 |                 u132_udev_get_kref(u132, udev); | 
 | 1984 |         } | 
 | 1985 |         urb->hcpriv = u132; | 
 | 1986 |         spin_lock_irqsave(&endp->queue_lock.slock, irqs); | 
 | 1987 |         endp->delayed = 1; | 
 | 1988 |         endp->jiffies = jiffies + msecs_to_jiffies(urb->interval); | 
 | 1989 |         endp->udev_number = address; | 
 | 1990 |         endp->usb_addr = usb_addr; | 
 | 1991 |         endp->usb_endp = usb_endp; | 
 | 1992 |         endp->queue_size = 1; | 
 | 1993 |         endp->queue_last = 0; | 
 | 1994 |         endp->queue_next = 0; | 
 | 1995 |         endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb; | 
 | 1996 |         spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | 
 | 1997 |         u132_endp_queue_work(u132, endp, msecs_to_jiffies(urb->interval)); | 
 | 1998 |         return 0; | 
 | 1999 | } | 
 | 2000 |  | 
 | 2001 | static int queue_int_on_old_endpoint(struct u132 *u132, struct u132_udev *udev, | 
 | 2002 |         struct usb_host_endpoint *hep, struct urb *urb, | 
 | 2003 |         struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr, | 
 | 2004 |         u8 usb_endp, u8 address) | 
 | 2005 | { | 
 | 2006 |         urb->hcpriv = u132; | 
 | 2007 |         endp->delayed = 1; | 
 | 2008 |         endp->jiffies = jiffies + msecs_to_jiffies(urb->interval); | 
 | 2009 |         if (endp->queue_size++ < ENDP_QUEUE_SIZE) { | 
 | 2010 |                 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb; | 
 | 2011 |         } else { | 
 | 2012 |                 struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq), | 
 | 2013 |                         GFP_ATOMIC); | 
 | 2014 |                 if (urbq == NULL) { | 
 | 2015 |                         endp->queue_size -= 1; | 
 | 2016 |                         return -ENOMEM; | 
 | 2017 |                 } else { | 
 | 2018 |                         list_add_tail(&urbq->urb_more, &endp->urb_more); | 
 | 2019 |                         urbq->urb = urb; | 
 | 2020 |                 } | 
 | 2021 |         } | 
 | 2022 |         return 0; | 
 | 2023 | } | 
 | 2024 |  | 
 | 2025 | static int create_endpoint_and_queue_bulk(struct u132 *u132, | 
 | 2026 |         struct u132_udev *udev, struct usb_host_endpoint *hep, struct urb *urb, | 
 | 2027 |         struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address, | 
 | 2028 |         gfp_t mem_flags) | 
 | 2029 | { | 
 | 2030 |         int ring_number; | 
 | 2031 |         struct u132_ring *ring; | 
 | 2032 |         unsigned long irqs; | 
 | 2033 |         u8 endp_number = ++u132->num_endpoints; | 
 | 2034 |         struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] = | 
 | 2035 |                 kmalloc(sizeof(struct u132_endp), mem_flags); | 
 | 2036 |         if (!endp) { | 
 | 2037 |                 return -ENOMEM; | 
 | 2038 |         } | 
 | 2039 |         INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp); | 
 | 2040 |         spin_lock_init(&endp->queue_lock.slock); | 
 | 2041 |         INIT_LIST_HEAD(&endp->urb_more); | 
 | 2042 |         endp->dequeueing = 0; | 
 | 2043 |         endp->edset_flush = 0; | 
 | 2044 |         endp->active = 0; | 
 | 2045 |         endp->delayed = 0; | 
 | 2046 |         endp->endp_number = endp_number; | 
 | 2047 |         endp->u132 = u132; | 
 | 2048 |         endp->hep = hep; | 
 | 2049 |         endp->pipetype = usb_pipetype(urb->pipe); | 
 | 2050 |         u132_endp_init_kref(u132, endp); | 
 | 2051 |         if (usb_pipein(urb->pipe)) { | 
 | 2052 |                 endp->toggle_bits = 0x2; | 
 | 2053 |                 usb_settoggle(udev->usb_device, usb_endp, 0, 0); | 
 | 2054 |                 ring_number = 3; | 
 | 2055 |                 endp->input = 1; | 
 | 2056 |                 endp->output = 0; | 
 | 2057 |                 udev->endp_number_in[usb_endp] = endp_number; | 
 | 2058 |                 u132_udev_get_kref(u132, udev); | 
 | 2059 |         } else { | 
 | 2060 |                 endp->toggle_bits = 0x2; | 
 | 2061 |                 usb_settoggle(udev->usb_device, usb_endp, 1, 0); | 
 | 2062 |                 ring_number = 2; | 
 | 2063 |                 endp->input = 0; | 
 | 2064 |                 endp->output = 1; | 
 | 2065 |                 udev->endp_number_out[usb_endp] = endp_number; | 
 | 2066 |                 u132_udev_get_kref(u132, udev); | 
 | 2067 |         } | 
 | 2068 |         ring = endp->ring = &u132->ring[ring_number - 1]; | 
 | 2069 |         if (ring->curr_endp) { | 
 | 2070 |                 list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring); | 
 | 2071 |         } else { | 
 | 2072 |                 INIT_LIST_HEAD(&endp->endp_ring); | 
 | 2073 |                 ring->curr_endp = endp; | 
 | 2074 |         } | 
 | 2075 |         ring->length += 1; | 
 | 2076 |         urb->hcpriv = u132; | 
 | 2077 |         spin_lock_irqsave(&endp->queue_lock.slock, irqs); | 
 | 2078 |         endp->udev_number = address; | 
 | 2079 |         endp->usb_addr = usb_addr; | 
 | 2080 |         endp->usb_endp = usb_endp; | 
 | 2081 |         endp->queue_size = 1; | 
 | 2082 |         endp->queue_last = 0; | 
 | 2083 |         endp->queue_next = 0; | 
 | 2084 |         endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb; | 
 | 2085 |         spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | 
 | 2086 |         u132_endp_queue_work(u132, endp, 0); | 
 | 2087 |         return 0; | 
 | 2088 | } | 
 | 2089 |  | 
 | 2090 | static int queue_bulk_on_old_endpoint(struct u132 *u132, struct u132_udev *udev, | 
 | 2091 |          struct usb_host_endpoint *hep, struct urb *urb, | 
 | 2092 |         struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr, | 
 | 2093 |         u8 usb_endp, u8 address) | 
 | 2094 | { | 
 | 2095 |         urb->hcpriv = u132; | 
 | 2096 |         if (endp->queue_size++ < ENDP_QUEUE_SIZE) { | 
 | 2097 |                 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb; | 
 | 2098 |         } else { | 
 | 2099 |                 struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq), | 
 | 2100 |                         GFP_ATOMIC); | 
 | 2101 |                 if (urbq == NULL) { | 
 | 2102 |                         endp->queue_size -= 1; | 
 | 2103 |                         return -ENOMEM; | 
 | 2104 |                 } else { | 
 | 2105 |                         list_add_tail(&urbq->urb_more, &endp->urb_more); | 
 | 2106 |                         urbq->urb = urb; | 
 | 2107 |                 } | 
 | 2108 |         } | 
 | 2109 |         return 0; | 
 | 2110 | } | 
 | 2111 |  | 
 | 2112 | static int create_endpoint_and_queue_control(struct u132 *u132, | 
 | 2113 |         struct usb_host_endpoint *hep, struct urb *urb, | 
 | 2114 |         struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, | 
 | 2115 |         gfp_t mem_flags) | 
 | 2116 | { | 
 | 2117 |         struct u132_ring *ring; | 
 | 2118 |         u8 endp_number = ++u132->num_endpoints; | 
 | 2119 |         struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] = | 
 | 2120 |                 kmalloc(sizeof(struct u132_endp), mem_flags); | 
 | 2121 |         if (!endp) { | 
 | 2122 |                 return -ENOMEM; | 
 | 2123 |         } | 
 | 2124 |         INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp); | 
 | 2125 |         spin_lock_init(&endp->queue_lock.slock); | 
 | 2126 |         INIT_LIST_HEAD(&endp->urb_more); | 
 | 2127 |         ring = endp->ring = &u132->ring[0]; | 
 | 2128 |         if (ring->curr_endp) { | 
 | 2129 |                 list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring); | 
 | 2130 |         } else { | 
 | 2131 |                 INIT_LIST_HEAD(&endp->endp_ring); | 
 | 2132 |                 ring->curr_endp = endp; | 
 | 2133 |         } | 
 | 2134 |         ring->length += 1; | 
 | 2135 |         endp->dequeueing = 0; | 
 | 2136 |         endp->edset_flush = 0; | 
 | 2137 |         endp->active = 0; | 
 | 2138 |         endp->delayed = 0; | 
 | 2139 |         endp->endp_number = endp_number; | 
 | 2140 |         endp->u132 = u132; | 
 | 2141 |         endp->hep = hep; | 
 | 2142 |         u132_endp_init_kref(u132, endp); | 
 | 2143 |         u132_endp_get_kref(u132, endp); | 
 | 2144 |         if (usb_addr == 0) { | 
 | 2145 |                 unsigned long irqs; | 
 | 2146 |                 u8 address = u132->addr[usb_addr].address; | 
 | 2147 |                 struct u132_udev *udev = &u132->udev[address]; | 
 | 2148 |                 endp->udev_number = address; | 
 | 2149 |                 endp->usb_addr = usb_addr; | 
 | 2150 |                 endp->usb_endp = usb_endp; | 
 | 2151 |                 endp->input = 1; | 
 | 2152 |                 endp->output = 1; | 
 | 2153 |                 endp->pipetype = usb_pipetype(urb->pipe); | 
 | 2154 |                 u132_udev_init_kref(u132, udev); | 
 | 2155 |                 u132_udev_get_kref(u132, udev); | 
 | 2156 |                 udev->endp_number_in[usb_endp] = endp_number; | 
 | 2157 |                 udev->endp_number_out[usb_endp] = endp_number; | 
 | 2158 |                 urb->hcpriv = u132; | 
 | 2159 |                 spin_lock_irqsave(&endp->queue_lock.slock, irqs); | 
 | 2160 |                 endp->queue_size = 1; | 
 | 2161 |                 endp->queue_last = 0; | 
 | 2162 |                 endp->queue_next = 0; | 
 | 2163 |                 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb; | 
 | 2164 |                 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | 
 | 2165 |                 u132_endp_queue_work(u132, endp, 0); | 
 | 2166 |                 return 0; | 
 | 2167 |         } else {                /*(usb_addr > 0) */ | 
 | 2168 |                 unsigned long irqs; | 
 | 2169 |                 u8 address = u132->addr[usb_addr].address; | 
 | 2170 |                 struct u132_udev *udev = &u132->udev[address]; | 
 | 2171 |                 endp->udev_number = address; | 
 | 2172 |                 endp->usb_addr = usb_addr; | 
 | 2173 |                 endp->usb_endp = usb_endp; | 
 | 2174 |                 endp->input = 1; | 
 | 2175 |                 endp->output = 1; | 
 | 2176 |                 endp->pipetype = usb_pipetype(urb->pipe); | 
 | 2177 |                 u132_udev_get_kref(u132, udev); | 
 | 2178 |                 udev->enumeration = 2; | 
 | 2179 |                 udev->endp_number_in[usb_endp] = endp_number; | 
 | 2180 |                 udev->endp_number_out[usb_endp] = endp_number; | 
 | 2181 |                 urb->hcpriv = u132; | 
 | 2182 |                 spin_lock_irqsave(&endp->queue_lock.slock, irqs); | 
 | 2183 |                 endp->queue_size = 1; | 
 | 2184 |                 endp->queue_last = 0; | 
 | 2185 |                 endp->queue_next = 0; | 
 | 2186 |                 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb; | 
 | 2187 |                 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | 
 | 2188 |                 u132_endp_queue_work(u132, endp, 0); | 
 | 2189 |                 return 0; | 
 | 2190 |         } | 
 | 2191 | } | 
 | 2192 |  | 
 | 2193 | static int queue_control_on_old_endpoint(struct u132 *u132, | 
 | 2194 |         struct usb_host_endpoint *hep, struct urb *urb, | 
 | 2195 |         struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr, | 
 | 2196 |         u8 usb_endp) | 
 | 2197 | { | 
 | 2198 |         if (usb_addr == 0) { | 
 | 2199 |                 if (usb_pipein(urb->pipe)) { | 
 | 2200 |                         urb->hcpriv = u132; | 
 | 2201 |                         if (endp->queue_size++ < ENDP_QUEUE_SIZE) { | 
 | 2202 |                                 endp->urb_list[ENDP_QUEUE_MASK & | 
 | 2203 |                                         endp->queue_last++] = urb; | 
 | 2204 |                         } else { | 
 | 2205 |                                 struct u132_urbq *urbq = | 
 | 2206 |                                         kmalloc(sizeof(struct u132_urbq), | 
 | 2207 |                                         GFP_ATOMIC); | 
 | 2208 |                                 if (urbq == NULL) { | 
 | 2209 |                                         endp->queue_size -= 1; | 
 | 2210 |                                         return -ENOMEM; | 
 | 2211 |                                 } else { | 
 | 2212 |                                         list_add_tail(&urbq->urb_more, | 
 | 2213 |                                                 &endp->urb_more); | 
 | 2214 |                                         urbq->urb = urb; | 
 | 2215 |                                 } | 
 | 2216 |                         } | 
 | 2217 |                         return 0; | 
 | 2218 |                 } else {        /* usb_pipeout(urb->pipe) */ | 
 | 2219 |                         struct u132_addr *addr = &u132->addr[usb_dev->devnum]; | 
 | 2220 |                         int I = MAX_U132_UDEVS; | 
 | 2221 |                         int i = 0; | 
 | 2222 |                         while (--I > 0) { | 
 | 2223 |                                 struct u132_udev *udev = &u132->udev[++i]; | 
 | 2224 |                                 if (udev->usb_device) { | 
 | 2225 |                                         continue; | 
 | 2226 |                                 } else { | 
 | 2227 |                                         udev->enumeration = 1; | 
 | 2228 |                                         u132->addr[0].address = i; | 
 | 2229 |                                         endp->udev_number = i; | 
 | 2230 |                                         udev->udev_number = i; | 
 | 2231 |                                         udev->usb_addr = usb_dev->devnum; | 
 | 2232 |                                         u132_udev_init_kref(u132, udev); | 
 | 2233 |                                         udev->endp_number_in[usb_endp] = | 
 | 2234 |                                                 endp->endp_number; | 
 | 2235 |                                         u132_udev_get_kref(u132, udev); | 
 | 2236 |                                         udev->endp_number_out[usb_endp] = | 
 | 2237 |                                                 endp->endp_number; | 
 | 2238 |                                         udev->usb_device = usb_dev; | 
 | 2239 |                                         ((u8 *) (urb->setup_packet))[2] = | 
 | 2240 |                                                 addr->address = i; | 
 | 2241 |                                         u132_udev_get_kref(u132, udev); | 
 | 2242 |                                         break; | 
 | 2243 |                                 } | 
 | 2244 |                         } | 
 | 2245 |                         if (I == 0) { | 
 | 2246 |                                 dev_err(&u132->platform_dev->dev, "run out of d" | 
 | 2247 |                                         "evice space\n"); | 
 | 2248 |                                 return -EINVAL; | 
 | 2249 |                         } | 
 | 2250 |                         urb->hcpriv = u132; | 
 | 2251 |                         if (endp->queue_size++ < ENDP_QUEUE_SIZE) { | 
 | 2252 |                                 endp->urb_list[ENDP_QUEUE_MASK & | 
 | 2253 |                                         endp->queue_last++] = urb; | 
 | 2254 |                         } else { | 
 | 2255 |                                 struct u132_urbq *urbq = | 
 | 2256 |                                         kmalloc(sizeof(struct u132_urbq), | 
 | 2257 |                                         GFP_ATOMIC); | 
 | 2258 |                                 if (urbq == NULL) { | 
 | 2259 |                                         endp->queue_size -= 1; | 
 | 2260 |                                         return -ENOMEM; | 
 | 2261 |                                 } else { | 
 | 2262 |                                         list_add_tail(&urbq->urb_more, | 
 | 2263 |                                                 &endp->urb_more); | 
 | 2264 |                                         urbq->urb = urb; | 
 | 2265 |                                 } | 
 | 2266 |                         } | 
 | 2267 |                         return 0; | 
 | 2268 |                 } | 
 | 2269 |         } else {                /*(usb_addr > 0) */ | 
 | 2270 |                 u8 address = u132->addr[usb_addr].address; | 
 | 2271 |                 struct u132_udev *udev = &u132->udev[address]; | 
 | 2272 |                 urb->hcpriv = u132; | 
 | 2273 |                 if (udev->enumeration == 2) { | 
 | 2274 |                 } else | 
 | 2275 |                         udev->enumeration = 2; | 
 | 2276 |                 if (endp->queue_size++ < ENDP_QUEUE_SIZE) { | 
 | 2277 |                         endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = | 
 | 2278 |                                 urb; | 
 | 2279 |                 } else { | 
 | 2280 |                         struct u132_urbq *urbq = | 
 | 2281 |                                 kmalloc(sizeof(struct u132_urbq), GFP_ATOMIC); | 
 | 2282 |                         if (urbq == NULL) { | 
 | 2283 |                                 endp->queue_size -= 1; | 
 | 2284 |                                 return -ENOMEM; | 
 | 2285 |                         } else { | 
 | 2286 |                                 list_add_tail(&urbq->urb_more, &endp->urb_more); | 
 | 2287 |                                 urbq->urb = urb; | 
 | 2288 |                         } | 
 | 2289 |                 } | 
 | 2290 |                 return 0; | 
 | 2291 |         } | 
 | 2292 | } | 
 | 2293 |  | 
 | 2294 | static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep, | 
 | 2295 |         struct urb *urb, gfp_t mem_flags) | 
 | 2296 | { | 
 | 2297 |         struct u132 *u132 = hcd_to_u132(hcd); | 
 | 2298 |         if (irqs_disabled()) { | 
 | 2299 |                 if (__GFP_WAIT & mem_flags) { | 
 | 2300 |                         printk(KERN_ERR "invalid context for function that migh" | 
 | 2301 |                                 "t sleep\n"); | 
 | 2302 |                         return -EINVAL; | 
 | 2303 |                 } | 
 | 2304 |         } | 
 | 2305 |         if (u132->going > 1) { | 
 | 2306 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 2307 |                         , u132->going); | 
 | 2308 |                 return -ENODEV; | 
 | 2309 |         } else if (u132->going > 0) { | 
 | 2310 |                 dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 
 | 2311 |                         "%p status=%d\n", urb, urb->status); | 
 | 2312 |                 return -ESHUTDOWN; | 
 | 2313 |         } else { | 
 | 2314 |                 u8 usb_addr = usb_pipedevice(urb->pipe); | 
 | 2315 |                 u8 usb_endp = usb_pipeendpoint(urb->pipe); | 
 | 2316 |                 struct usb_device *usb_dev = urb->dev; | 
 | 2317 |                 if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) { | 
 | 2318 |                         u8 address = u132->addr[usb_addr].address; | 
 | 2319 |                         struct u132_udev *udev = &u132->udev[address]; | 
 | 2320 |                         struct u132_endp *endp = hep->hcpriv; | 
 | 2321 |                         urb->actual_length = 0; | 
 | 2322 |                         if (endp) { | 
 | 2323 |                                 unsigned long irqs; | 
 | 2324 |                                 int retval; | 
 | 2325 |                                 spin_lock_irqsave(&endp->queue_lock.slock, | 
 | 2326 |                                         irqs); | 
 | 2327 |                                 retval = queue_int_on_old_endpoint(u132, udev, | 
 | 2328 |                                         hep, urb, usb_dev, endp, usb_addr, | 
 | 2329 |                                         usb_endp, address); | 
 | 2330 |                                 spin_unlock_irqrestore(&endp->queue_lock.slock, | 
 | 2331 |                                         irqs); | 
 | 2332 |                                 if (retval) { | 
 | 2333 |                                         return retval; | 
 | 2334 |                                 } else { | 
 | 2335 |                                         u132_endp_queue_work(u132, endp, | 
 | 2336 |                                                 msecs_to_jiffies(urb->interval)) | 
 | 2337 |                                                 ; | 
 | 2338 |                                         return 0; | 
 | 2339 |                                 } | 
 | 2340 |                         } else if (u132->num_endpoints == MAX_U132_ENDPS) { | 
 | 2341 |                                 return -EINVAL; | 
 | 2342 |                         } else {        /*(endp == NULL) */ | 
 | 2343 |                                 return create_endpoint_and_queue_int(u132, udev, | 
 | 2344 |                                          hep, urb, usb_dev, usb_addr, usb_endp, | 
 | 2345 |                                         address, mem_flags); | 
 | 2346 |                         } | 
 | 2347 |                 } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { | 
 | 2348 |                         dev_err(&u132->platform_dev->dev, "the hardware does no" | 
 | 2349 |                                 "t support PIPE_ISOCHRONOUS\n"); | 
 | 2350 |                         return -EINVAL; | 
 | 2351 |                 } else if (usb_pipetype(urb->pipe) == PIPE_BULK) { | 
 | 2352 |                         u8 address = u132->addr[usb_addr].address; | 
 | 2353 |                         struct u132_udev *udev = &u132->udev[address]; | 
 | 2354 |                         struct u132_endp *endp = hep->hcpriv; | 
 | 2355 |                         urb->actual_length = 0; | 
 | 2356 |                         if (endp) { | 
 | 2357 |                                 unsigned long irqs; | 
 | 2358 |                                 int retval; | 
 | 2359 |                                 spin_lock_irqsave(&endp->queue_lock.slock, | 
 | 2360 |                                         irqs); | 
 | 2361 |                                 retval = queue_bulk_on_old_endpoint(u132, udev, | 
 | 2362 |                                         hep, urb, usb_dev, endp, usb_addr, | 
 | 2363 |                                         usb_endp, address); | 
 | 2364 |                                 spin_unlock_irqrestore(&endp->queue_lock.slock, | 
 | 2365 |                                         irqs); | 
 | 2366 |                                 if (retval) { | 
 | 2367 |                                         return retval; | 
 | 2368 |                                 } else { | 
 | 2369 |                                         u132_endp_queue_work(u132, endp, 0); | 
 | 2370 |                                         return 0; | 
 | 2371 |                                 } | 
 | 2372 |                         } else if (u132->num_endpoints == MAX_U132_ENDPS) { | 
 | 2373 |                                 return -EINVAL; | 
 | 2374 |                         } else | 
 | 2375 |                                 return create_endpoint_and_queue_bulk(u132, | 
 | 2376 |                                         udev, hep, urb, usb_dev, usb_addr, | 
 | 2377 |                                         usb_endp, address, mem_flags); | 
 | 2378 |                 } else { | 
 | 2379 |                         struct u132_endp *endp = hep->hcpriv; | 
 | 2380 |                         u16 urb_size = 8; | 
 | 2381 |                         u8 *b = urb->setup_packet; | 
 | 2382 |                         int i = 0; | 
 | 2383 |                         char data[30 *3 + 4]; | 
 | 2384 |                         char *d = data; | 
 | 2385 |                         int m = (sizeof(data) - 1) / 3; | 
 | 2386 |                         int l = 0; | 
 | 2387 |                         data[0] = 0; | 
 | 2388 |                         while (urb_size-- > 0) { | 
 | 2389 |                                 if (i > m) { | 
 | 2390 |                                 } else if (i++ < m) { | 
 | 2391 |                                         int w = sprintf(d, " %02X", *b++); | 
 | 2392 |                                         d += w; | 
 | 2393 |                                         l += w; | 
 | 2394 |                                 } else | 
 | 2395 |                                         d += sprintf(d, " .."); | 
 | 2396 |                         } | 
 | 2397 |                         if (endp) { | 
 | 2398 |                                 unsigned long irqs; | 
 | 2399 |                                 int retval; | 
 | 2400 |                                 spin_lock_irqsave(&endp->queue_lock.slock, | 
 | 2401 |                                         irqs); | 
 | 2402 |                                 retval = queue_control_on_old_endpoint(u132, | 
 | 2403 |                                         hep, urb, usb_dev, endp, usb_addr, | 
 | 2404 |                                         usb_endp); | 
 | 2405 |                                 spin_unlock_irqrestore(&endp->queue_lock.slock, | 
 | 2406 |                                         irqs); | 
 | 2407 |                                 if (retval) { | 
 | 2408 |                                         return retval; | 
 | 2409 |                                 } else { | 
 | 2410 |                                         u132_endp_queue_work(u132, endp, 0); | 
 | 2411 |                                         return 0; | 
 | 2412 |                                 } | 
 | 2413 |                         } else if (u132->num_endpoints == MAX_U132_ENDPS) { | 
 | 2414 |                                 return -EINVAL; | 
 | 2415 |                         } else | 
 | 2416 |                                 return create_endpoint_and_queue_control(u132, | 
 | 2417 |                                         hep, urb, usb_dev, usb_addr, usb_endp, | 
 | 2418 |                                         mem_flags); | 
 | 2419 |                 } | 
 | 2420 |         } | 
 | 2421 | } | 
 | 2422 |  | 
 | 2423 | static int dequeue_from_overflow_chain(struct u132 *u132, | 
 | 2424 |         struct u132_endp *endp, struct urb *urb) | 
 | 2425 | { | 
 | 2426 |         struct list_head *scan; | 
 | 2427 |         struct list_head *head = &endp->urb_more; | 
 | 2428 |         list_for_each(scan, head) { | 
 | 2429 |                 struct u132_urbq *urbq = list_entry(scan, struct u132_urbq, | 
 | 2430 |                         urb_more); | 
 | 2431 |                 if (urbq->urb == urb) { | 
 | 2432 |                         struct usb_hcd *hcd = u132_to_hcd(u132); | 
 | 2433 |                         list_del(scan); | 
 | 2434 |                         endp->queue_size -= 1; | 
 | 2435 |                         urb->error_count = 0; | 
 | 2436 |                         urb->hcpriv = NULL; | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 2437 |                         usb_hcd_giveback_urb(hcd, urb); | 
| Tony Olech | d774efe | 2006-09-13 11:27:35 +0100 | [diff] [blame] | 2438 |                         return 0; | 
 | 2439 |                 } else | 
 | 2440 |                         continue; | 
 | 2441 |         } | 
 | 2442 |         dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]=%p ring" | 
 | 2443 |                 "[%d] %c%c usb_endp=%d usb_addr=%d size=%d next=%04X last=%04X" | 
 | 2444 |                 "\n", urb, endp->endp_number, endp, endp->ring->number, | 
 | 2445 |                 endp->input ? 'I' : ' ', endp->output ? 'O' : ' ', | 
 | 2446 |                 endp->usb_endp, endp->usb_addr, endp->queue_size, | 
 | 2447 |                 endp->queue_next, endp->queue_last); | 
 | 2448 |         return -EINVAL; | 
 | 2449 | } | 
 | 2450 |  | 
 | 2451 | static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp, | 
 | 2452 |         struct urb *urb) | 
 | 2453 | { | 
 | 2454 |         unsigned long irqs; | 
 | 2455 |         spin_lock_irqsave(&endp->queue_lock.slock, irqs); | 
 | 2456 |         if (endp->queue_size == 0) { | 
 | 2457 |                 dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]" | 
 | 2458 |                         "=%p ring[%d] %c%c usb_endp=%d usb_addr=%d\n", urb, | 
 | 2459 |                         endp->endp_number, endp, endp->ring->number, | 
 | 2460 |                         endp->input ? 'I' : ' ', endp->output ? 'O' : ' ', | 
 | 2461 |                         endp->usb_endp, endp->usb_addr); | 
 | 2462 |                 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | 
 | 2463 |                 return -EINVAL; | 
 | 2464 |         } | 
 | 2465 |         if (urb == endp->urb_list[ENDP_QUEUE_MASK & endp->queue_next]) { | 
 | 2466 |                 if (endp->active) { | 
 | 2467 |                         endp->dequeueing = 1; | 
 | 2468 |                         endp->edset_flush = 1; | 
 | 2469 |                         u132_endp_queue_work(u132, endp, 0); | 
 | 2470 |                         spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | 
 | 2471 |                         urb->hcpriv = NULL; | 
 | 2472 |                         return 0; | 
 | 2473 |                 } else { | 
 | 2474 |                         spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | 
 | 2475 |                         u132_hcd_abandon_urb(u132, endp, urb, urb->status); | 
 | 2476 |                         return 0; | 
 | 2477 |                 } | 
 | 2478 |         } else { | 
 | 2479 |                 u16 queue_list = 0; | 
 | 2480 |                 u16 queue_size = endp->queue_size; | 
 | 2481 |                 u16 queue_scan = endp->queue_next; | 
 | 2482 |                 struct urb **urb_slot = NULL; | 
 | 2483 |                 while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) { | 
 | 2484 |                         if (urb == endp->urb_list[ENDP_QUEUE_MASK & | 
 | 2485 |                                 ++queue_scan]) { | 
 | 2486 |                                 urb_slot = &endp->urb_list[ENDP_QUEUE_MASK & | 
 | 2487 |                                         queue_scan]; | 
 | 2488 |                                 break; | 
 | 2489 |                         } else | 
 | 2490 |                                 continue; | 
 | 2491 |                 } | 
 | 2492 |                 while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) { | 
 | 2493 |                         *urb_slot = endp->urb_list[ENDP_QUEUE_MASK & | 
 | 2494 |                                 ++queue_scan]; | 
 | 2495 |                         urb_slot = &endp->urb_list[ENDP_QUEUE_MASK & | 
 | 2496 |                                 queue_scan]; | 
 | 2497 |                 } | 
 | 2498 |                 if (urb_slot) { | 
 | 2499 |                         struct usb_hcd *hcd = u132_to_hcd(u132); | 
 | 2500 |                         endp->queue_size -= 1; | 
 | 2501 |                         if (list_empty(&endp->urb_more)) { | 
 | 2502 |                                 spin_unlock_irqrestore(&endp->queue_lock.slock, | 
 | 2503 |                                         irqs); | 
 | 2504 |                         } else { | 
 | 2505 |                                 struct list_head *next = endp->urb_more.next; | 
 | 2506 |                                 struct u132_urbq *urbq = list_entry(next, | 
 | 2507 |                                         struct u132_urbq, urb_more); | 
 | 2508 |                                 list_del(next); | 
 | 2509 |                                 *urb_slot = urbq->urb; | 
 | 2510 |                                 spin_unlock_irqrestore(&endp->queue_lock.slock, | 
 | 2511 |                                         irqs); | 
 | 2512 |                                 kfree(urbq); | 
 | 2513 |                         } urb->error_count = 0; | 
 | 2514 |                         urb->hcpriv = NULL; | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 2515 |                         usb_hcd_giveback_urb(hcd, urb); | 
| Tony Olech | d774efe | 2006-09-13 11:27:35 +0100 | [diff] [blame] | 2516 |                         return 0; | 
 | 2517 |                 } else if (list_empty(&endp->urb_more)) { | 
 | 2518 |                         dev_err(&u132->platform_dev->dev, "urb=%p not found in " | 
 | 2519 |                                 "endp[%d]=%p ring[%d] %c%c usb_endp=%d usb_addr" | 
 | 2520 |                                 "=%d size=%d next=%04X last=%04X\n", urb, | 
 | 2521 |                                 endp->endp_number, endp, endp->ring->number, | 
 | 2522 |                                 endp->input ? 'I' : ' ', | 
 | 2523 |                                 endp->output ? 'O' : ' ', endp->usb_endp, | 
 | 2524 |                                 endp->usb_addr, endp->queue_size, | 
 | 2525 |                                 endp->queue_next, endp->queue_last); | 
 | 2526 |                         spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | 
 | 2527 |                         return -EINVAL; | 
 | 2528 |                 } else { | 
 | 2529 |                         int retval = dequeue_from_overflow_chain(u132, endp, | 
 | 2530 |                                 urb); | 
 | 2531 |                         spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | 
 | 2532 |                         return retval; | 
 | 2533 |                 } | 
 | 2534 |         } | 
 | 2535 | } | 
 | 2536 |  | 
 | 2537 | static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | 
 | 2538 | { | 
 | 2539 |         struct u132 *u132 = hcd_to_u132(hcd); | 
 | 2540 |         if (u132->going > 2) { | 
 | 2541 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 2542 |                         , u132->going); | 
 | 2543 |                 return -ENODEV; | 
 | 2544 |         } else { | 
 | 2545 |                 u8 usb_addr = usb_pipedevice(urb->pipe); | 
 | 2546 |                 u8 usb_endp = usb_pipeendpoint(urb->pipe); | 
 | 2547 |                 u8 address = u132->addr[usb_addr].address; | 
 | 2548 |                 struct u132_udev *udev = &u132->udev[address]; | 
 | 2549 |                 if (usb_pipein(urb->pipe)) { | 
 | 2550 |                         u8 endp_number = udev->endp_number_in[usb_endp]; | 
 | 2551 |                         struct u132_endp *endp = u132->endp[endp_number - 1]; | 
 | 2552 |                         return u132_endp_urb_dequeue(u132, endp, urb); | 
 | 2553 |                 } else { | 
 | 2554 |                         u8 endp_number = udev->endp_number_out[usb_endp]; | 
 | 2555 |                         struct u132_endp *endp = u132->endp[endp_number - 1]; | 
 | 2556 |                         return u132_endp_urb_dequeue(u132, endp, urb); | 
 | 2557 |                 } | 
 | 2558 |         } | 
 | 2559 | } | 
 | 2560 |  | 
 | 2561 | static void u132_endpoint_disable(struct usb_hcd *hcd, | 
 | 2562 |         struct usb_host_endpoint *hep) | 
 | 2563 | { | 
 | 2564 |         struct u132 *u132 = hcd_to_u132(hcd); | 
 | 2565 |         if (u132->going > 2) { | 
 | 2566 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 2567 |                         , u132->going); | 
 | 2568 |         } else { | 
 | 2569 |                 struct u132_endp *endp = hep->hcpriv; | 
 | 2570 |                 if (endp) | 
 | 2571 |                         u132_endp_put_kref(u132, endp); | 
 | 2572 |         } | 
 | 2573 | } | 
 | 2574 |  | 
 | 2575 | static int u132_get_frame(struct usb_hcd *hcd) | 
 | 2576 | { | 
 | 2577 |         struct u132 *u132 = hcd_to_u132(hcd); | 
 | 2578 |         if (u132->going > 1) { | 
 | 2579 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 2580 |                         , u132->going); | 
 | 2581 |                 return -ENODEV; | 
 | 2582 |         } else if (u132->going > 0) { | 
 | 2583 |                 dev_err(&u132->platform_dev->dev, "device is being removed\n"); | 
 | 2584 |                 return -ESHUTDOWN; | 
 | 2585 |         } else { | 
 | 2586 |                 int frame = 0; | 
 | 2587 |                 dev_err(&u132->platform_dev->dev, "TODO: u132_get_frame\n"); | 
 | 2588 |                 msleep(100); | 
 | 2589 |                 return frame; | 
 | 2590 |         } | 
 | 2591 | } | 
 | 2592 |  | 
 | 2593 | static int u132_roothub_descriptor(struct u132 *u132, | 
 | 2594 |         struct usb_hub_descriptor *desc) | 
 | 2595 | { | 
 | 2596 |         int retval; | 
 | 2597 |         u16 temp; | 
 | 2598 |         u32 rh_a = -1; | 
 | 2599 |         u32 rh_b = -1; | 
 | 2600 |         retval = u132_read_pcimem(u132, roothub.a, &rh_a); | 
 | 2601 |         if (retval) | 
 | 2602 |                 return retval; | 
 | 2603 |         desc->bDescriptorType = 0x29; | 
 | 2604 |         desc->bPwrOn2PwrGood = (rh_a & RH_A_POTPGT) >> 24; | 
 | 2605 |         desc->bHubContrCurrent = 0; | 
 | 2606 |         desc->bNbrPorts = u132->num_ports; | 
 | 2607 |         temp = 1 + (u132->num_ports / 8); | 
 | 2608 |         desc->bDescLength = 7 + 2 *temp; | 
 | 2609 |         temp = 0; | 
 | 2610 |         if (rh_a & RH_A_NPS) | 
 | 2611 |                 temp |= 0x0002; | 
 | 2612 |         if (rh_a & RH_A_PSM) | 
 | 2613 |                 temp |= 0x0001; | 
 | 2614 |         if (rh_a & RH_A_NOCP) { | 
 | 2615 |                 temp |= 0x0010; | 
 | 2616 |         } else if (rh_a & RH_A_OCPM) | 
 | 2617 |                 temp |= 0x0008; | 
 | 2618 |         desc->wHubCharacteristics = cpu_to_le16(temp); | 
 | 2619 |         retval = u132_read_pcimem(u132, roothub.b, &rh_b); | 
 | 2620 |         if (retval) | 
 | 2621 |                 return retval; | 
 | 2622 |         memset(desc->bitmap, 0xff, sizeof(desc->bitmap)); | 
 | 2623 |         desc->bitmap[0] = rh_b & RH_B_DR; | 
 | 2624 |         if (u132->num_ports > 7) { | 
 | 2625 |                 desc->bitmap[1] = (rh_b & RH_B_DR) >> 8; | 
 | 2626 |                 desc->bitmap[2] = 0xff; | 
 | 2627 |         } else | 
 | 2628 |                 desc->bitmap[1] = 0xff; | 
 | 2629 |         return 0; | 
 | 2630 | } | 
 | 2631 |  | 
 | 2632 | static int u132_roothub_status(struct u132 *u132, __le32 *desc) | 
 | 2633 | { | 
 | 2634 |         u32 rh_status = -1; | 
 | 2635 |         int ret_status = u132_read_pcimem(u132, roothub.status, &rh_status); | 
 | 2636 |         *desc = cpu_to_le32(rh_status); | 
 | 2637 |         return ret_status; | 
 | 2638 | } | 
 | 2639 |  | 
 | 2640 | static int u132_roothub_portstatus(struct u132 *u132, __le32 *desc, u16 wIndex) | 
 | 2641 | { | 
 | 2642 |         if (wIndex == 0 || wIndex > u132->num_ports) { | 
 | 2643 |                 return -EINVAL; | 
 | 2644 |         } else { | 
 | 2645 |                 int port = wIndex - 1; | 
 | 2646 |                 u32 rh_portstatus = -1; | 
 | 2647 |                 int ret_portstatus = u132_read_pcimem(u132, | 
 | 2648 |                         roothub.portstatus[port], &rh_portstatus); | 
 | 2649 |                 *desc = cpu_to_le32(rh_portstatus); | 
 | 2650 |                 if (*(u16 *) (desc + 2)) { | 
 | 2651 |                         dev_info(&u132->platform_dev->dev, "Port %d Status Chan" | 
 | 2652 |                                 "ge = %08X\n", port, *desc); | 
 | 2653 |                 } | 
 | 2654 |                 return ret_portstatus; | 
 | 2655 |         } | 
 | 2656 | } | 
 | 2657 |  | 
 | 2658 |  | 
 | 2659 | /* this timer value might be vendor-specific ... */ | 
 | 2660 | #define PORT_RESET_HW_MSEC 10 | 
 | 2661 | #define PORT_RESET_MSEC 10 | 
 | 2662 | /* wrap-aware logic morphed from <linux/jiffies.h> */ | 
 | 2663 | #define tick_before(t1, t2) ((s16)(((s16)(t1))-((s16)(t2))) < 0) | 
 | 2664 | static int u132_roothub_portreset(struct u132 *u132, int port_index) | 
 | 2665 | { | 
 | 2666 |         int retval; | 
 | 2667 |         u32 fmnumber; | 
 | 2668 |         u16 now; | 
 | 2669 |         u16 reset_done; | 
 | 2670 |         retval = u132_read_pcimem(u132, fmnumber, &fmnumber); | 
 | 2671 |         if (retval) | 
 | 2672 |                 return retval; | 
 | 2673 |         now = fmnumber; | 
 | 2674 |         reset_done = now + PORT_RESET_MSEC; | 
 | 2675 |         do { | 
 | 2676 |                 u32 portstat; | 
 | 2677 |                 do { | 
 | 2678 |                         retval = u132_read_pcimem(u132, | 
 | 2679 |                                 roothub.portstatus[port_index], &portstat); | 
 | 2680 |                         if (retval) | 
 | 2681 |                                 return retval; | 
 | 2682 |                         if (RH_PS_PRS & portstat) { | 
 | 2683 |                                 continue; | 
 | 2684 |                         } else | 
 | 2685 |                                 break; | 
 | 2686 |                 } while (tick_before(now, reset_done)); | 
 | 2687 |                 if (RH_PS_PRS & portstat) | 
 | 2688 |                         return -ENODEV; | 
 | 2689 |                 if (RH_PS_CCS & portstat) { | 
 | 2690 |                         if (RH_PS_PRSC & portstat) { | 
 | 2691 |                                 retval = u132_write_pcimem(u132, | 
 | 2692 |                                         roothub.portstatus[port_index], | 
 | 2693 |                                         RH_PS_PRSC); | 
 | 2694 |                                 if (retval) | 
 | 2695 |                                         return retval; | 
 | 2696 |                         } | 
 | 2697 |                 } else | 
 | 2698 |                         break;        /* start the next reset, | 
 | 2699 |                                 sleep till it's probably done */ | 
 | 2700 |                 retval = u132_write_pcimem(u132, roothub.portstatus[port_index], | 
 | 2701 |                          RH_PS_PRS); | 
 | 2702 |                 if (retval) | 
 | 2703 |                         return retval; | 
 | 2704 |                 msleep(PORT_RESET_HW_MSEC); | 
 | 2705 |                 retval = u132_read_pcimem(u132, fmnumber, &fmnumber); | 
 | 2706 |                 if (retval) | 
 | 2707 |                         return retval; | 
 | 2708 |                 now = fmnumber; | 
 | 2709 |         } while (tick_before(now, reset_done)); | 
 | 2710 |         return 0; | 
 | 2711 | } | 
 | 2712 |  | 
 | 2713 | static int u132_roothub_setportfeature(struct u132 *u132, u16 wValue, | 
 | 2714 |         u16 wIndex) | 
 | 2715 | { | 
 | 2716 |         if (wIndex == 0 || wIndex > u132->num_ports) { | 
 | 2717 |                 return -EINVAL; | 
 | 2718 |         } else { | 
 | 2719 |                 int retval; | 
 | 2720 |                 int port_index = wIndex - 1; | 
 | 2721 |                 struct u132_port *port = &u132->port[port_index]; | 
 | 2722 |                 port->Status &= ~(1 << wValue); | 
 | 2723 |                 switch (wValue) { | 
 | 2724 |                 case USB_PORT_FEAT_SUSPEND: | 
 | 2725 |                         retval = u132_write_pcimem(u132, | 
 | 2726 |                                 roothub.portstatus[port_index], RH_PS_PSS); | 
 | 2727 |                         if (retval) | 
 | 2728 |                                 return retval; | 
 | 2729 |                         return 0; | 
 | 2730 |                 case USB_PORT_FEAT_POWER: | 
 | 2731 |                         retval = u132_write_pcimem(u132, | 
 | 2732 |                                 roothub.portstatus[port_index], RH_PS_PPS); | 
 | 2733 |                         if (retval) | 
 | 2734 |                                 return retval; | 
 | 2735 |                         return 0; | 
 | 2736 |                 case USB_PORT_FEAT_RESET: | 
 | 2737 |                         retval = u132_roothub_portreset(u132, port_index); | 
 | 2738 |                         if (retval) | 
 | 2739 |                                 return retval; | 
 | 2740 |                         return 0; | 
 | 2741 |                 default: | 
 | 2742 |                         return -EPIPE; | 
 | 2743 |                 } | 
 | 2744 |         } | 
 | 2745 | } | 
 | 2746 |  | 
 | 2747 | static int u132_roothub_clearportfeature(struct u132 *u132, u16 wValue, | 
 | 2748 |         u16 wIndex) | 
 | 2749 | { | 
 | 2750 |         if (wIndex == 0 || wIndex > u132->num_ports) { | 
 | 2751 |                 return -EINVAL; | 
 | 2752 |         } else { | 
 | 2753 |                 int port_index = wIndex - 1; | 
 | 2754 |                 u32 temp; | 
 | 2755 |                 int retval; | 
 | 2756 |                 struct u132_port *port = &u132->port[port_index]; | 
 | 2757 |                 port->Status &= ~(1 << wValue); | 
 | 2758 |                 switch (wValue) { | 
 | 2759 |                 case USB_PORT_FEAT_ENABLE: | 
 | 2760 |                         temp = RH_PS_CCS; | 
 | 2761 |                         break; | 
 | 2762 |                 case USB_PORT_FEAT_C_ENABLE: | 
 | 2763 |                         temp = RH_PS_PESC; | 
 | 2764 |                         break; | 
 | 2765 |                 case USB_PORT_FEAT_SUSPEND: | 
 | 2766 |                         temp = RH_PS_POCI; | 
 | 2767 |                         if ((u132->hc_control & OHCI_CTRL_HCFS) | 
 | 2768 |                                 != OHCI_USB_OPER) { | 
 | 2769 |                                 dev_err(&u132->platform_dev->dev, "TODO resume_" | 
 | 2770 |                                         "root_hub\n"); | 
 | 2771 |                         } | 
 | 2772 |                         break; | 
 | 2773 |                 case USB_PORT_FEAT_C_SUSPEND: | 
 | 2774 |                         temp = RH_PS_PSSC; | 
 | 2775 |                         break; | 
 | 2776 |                 case USB_PORT_FEAT_POWER: | 
 | 2777 |                         temp = RH_PS_LSDA; | 
 | 2778 |                         break; | 
 | 2779 |                 case USB_PORT_FEAT_C_CONNECTION: | 
 | 2780 |                         temp = RH_PS_CSC; | 
 | 2781 |                         break; | 
 | 2782 |                 case USB_PORT_FEAT_C_OVER_CURRENT: | 
 | 2783 |                         temp = RH_PS_OCIC; | 
 | 2784 |                         break; | 
 | 2785 |                 case USB_PORT_FEAT_C_RESET: | 
 | 2786 |                         temp = RH_PS_PRSC; | 
 | 2787 |                         break; | 
 | 2788 |                 default: | 
 | 2789 |                         return -EPIPE; | 
 | 2790 |                 } | 
 | 2791 |                 retval = u132_write_pcimem(u132, roothub.portstatus[port_index], | 
 | 2792 |                          temp); | 
 | 2793 |                 if (retval) | 
 | 2794 |                         return retval; | 
 | 2795 |                 return 0; | 
 | 2796 |         } | 
 | 2797 | } | 
 | 2798 |  | 
 | 2799 |  | 
 | 2800 | /* the virtual root hub timer IRQ checks for hub status*/ | 
 | 2801 | static int u132_hub_status_data(struct usb_hcd *hcd, char *buf) | 
 | 2802 | { | 
 | 2803 |         struct u132 *u132 = hcd_to_u132(hcd); | 
 | 2804 |         if (u132->going > 1) { | 
 | 2805 |                 dev_err(&u132->platform_dev->dev, "device hcd=%p has been remov" | 
 | 2806 |                         "ed %d\n", hcd, u132->going); | 
 | 2807 |                 return -ENODEV; | 
 | 2808 |         } else if (u132->going > 0) { | 
 | 2809 |                 dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov" | 
 | 2810 |                         "ed\n", hcd); | 
 | 2811 |                 dump_stack(); | 
 | 2812 |                 return -ESHUTDOWN; | 
 | 2813 |         } else { | 
 | 2814 |                 int i, changed = 0, length = 1; | 
 | 2815 |                 if (u132->flags & OHCI_QUIRK_AMD756) { | 
 | 2816 |                         if ((u132->hc_roothub_a & RH_A_NDP) > MAX_ROOT_PORTS) { | 
 | 2817 |                                 dev_err(&u132->platform_dev->dev, "bogus NDP, r" | 
 | 2818 |                                         "ereads as NDP=%d\n", | 
 | 2819 |                                         u132->hc_roothub_a & RH_A_NDP); | 
 | 2820 |                                 goto done; | 
 | 2821 |                         } | 
 | 2822 |                 } | 
 | 2823 |                 if (u132->hc_roothub_status & (RH_HS_LPSC | RH_HS_OCIC)) { | 
 | 2824 |                         buf[0] = changed = 1; | 
 | 2825 |                 } else | 
 | 2826 |                         buf[0] = 0; | 
 | 2827 |                 if (u132->num_ports > 7) { | 
 | 2828 |                         buf[1] = 0; | 
 | 2829 |                         length++; | 
 | 2830 |                 } | 
 | 2831 |                 for (i = 0; i < u132->num_ports; i++) { | 
 | 2832 |                         if (u132->hc_roothub_portstatus[i] & (RH_PS_CSC | | 
 | 2833 |                                 RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC | | 
 | 2834 |                                 RH_PS_PRSC)) { | 
 | 2835 |                                 changed = 1; | 
 | 2836 |                                 if (i < 7) { | 
 | 2837 |                                         buf[0] |= 1 << (i + 1); | 
 | 2838 |                                 } else | 
 | 2839 |                                         buf[1] |= 1 << (i - 7); | 
 | 2840 |                                 continue; | 
 | 2841 |                         } | 
 | 2842 |                         if (!(u132->hc_roothub_portstatus[i] & RH_PS_CCS)) { | 
 | 2843 |                                 continue; | 
 | 2844 |                         } | 
 | 2845 |                         if ((u132->hc_roothub_portstatus[i] & RH_PS_PSS)) { | 
 | 2846 |                                 continue; | 
 | 2847 |                         } | 
 | 2848 |                 } | 
 | 2849 |               done:return changed ? length : 0; | 
 | 2850 |         } | 
 | 2851 | } | 
 | 2852 |  | 
 | 2853 | static int u132_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | 
 | 2854 |         u16 wIndex, char *buf, u16 wLength) | 
 | 2855 | { | 
 | 2856 |         struct u132 *u132 = hcd_to_u132(hcd); | 
 | 2857 |         if (u132->going > 1) { | 
 | 2858 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 2859 |                         , u132->going); | 
 | 2860 |                 return -ENODEV; | 
 | 2861 |         } else if (u132->going > 0) { | 
 | 2862 |                 dev_err(&u132->platform_dev->dev, "device is being removed\n"); | 
 | 2863 |                 return -ESHUTDOWN; | 
 | 2864 |         } else { | 
 | 2865 |                 int retval = 0; | 
 | 2866 |                 down(&u132->sw_lock); | 
 | 2867 |                 switch (typeReq) { | 
 | 2868 |                 case ClearHubFeature: | 
 | 2869 |                         switch (wValue) { | 
 | 2870 |                         case C_HUB_OVER_CURRENT: | 
 | 2871 |                         case C_HUB_LOCAL_POWER: | 
 | 2872 |                                 break; | 
 | 2873 |                         default: | 
 | 2874 |                                 goto stall; | 
 | 2875 |                         } | 
 | 2876 |                         break; | 
 | 2877 |                 case SetHubFeature: | 
 | 2878 |                         switch (wValue) { | 
 | 2879 |                         case C_HUB_OVER_CURRENT: | 
 | 2880 |                         case C_HUB_LOCAL_POWER: | 
 | 2881 |                                 break; | 
 | 2882 |                         default: | 
 | 2883 |                                 goto stall; | 
 | 2884 |                         } | 
 | 2885 |                         break; | 
 | 2886 |                 case ClearPortFeature:{ | 
 | 2887 |                                 retval = u132_roothub_clearportfeature(u132, | 
 | 2888 |                                         wValue, wIndex); | 
 | 2889 |                                 if (retval) | 
 | 2890 |                                         goto error; | 
 | 2891 |                                 break; | 
 | 2892 |                         } | 
 | 2893 |                 case GetHubDescriptor:{ | 
 | 2894 |                                 retval = u132_roothub_descriptor(u132, | 
 | 2895 |                                         (struct usb_hub_descriptor *)buf); | 
 | 2896 |                                 if (retval) | 
 | 2897 |                                         goto error; | 
 | 2898 |                                 break; | 
 | 2899 |                         } | 
 | 2900 |                 case GetHubStatus:{ | 
 | 2901 |                                 retval = u132_roothub_status(u132, | 
 | 2902 |                                         (__le32 *) buf); | 
 | 2903 |                                 if (retval) | 
 | 2904 |                                         goto error; | 
 | 2905 |                                 break; | 
 | 2906 |                         } | 
 | 2907 |                 case GetPortStatus:{ | 
 | 2908 |                                 retval = u132_roothub_portstatus(u132, | 
 | 2909 |                                         (__le32 *) buf, wIndex); | 
 | 2910 |                                 if (retval) | 
 | 2911 |                                         goto error; | 
 | 2912 |                                 break; | 
 | 2913 |                         } | 
 | 2914 |                 case SetPortFeature:{ | 
 | 2915 |                                 retval = u132_roothub_setportfeature(u132, | 
 | 2916 |                                         wValue, wIndex); | 
 | 2917 |                                 if (retval) | 
 | 2918 |                                         goto error; | 
 | 2919 |                                 break; | 
 | 2920 |                         } | 
 | 2921 |                 default: | 
 | 2922 |                         goto stall; | 
 | 2923 |                       error:u132_disable(u132); | 
 | 2924 |                         u132->going = 1; | 
 | 2925 |                         break; | 
 | 2926 |                       stall:retval = -EPIPE; | 
 | 2927 |                         break; | 
 | 2928 |                 } | 
 | 2929 |                 up(&u132->sw_lock); | 
 | 2930 |                 return retval; | 
 | 2931 |         } | 
 | 2932 | } | 
 | 2933 |  | 
 | 2934 | static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num) | 
 | 2935 | { | 
 | 2936 |         struct u132 *u132 = hcd_to_u132(hcd); | 
 | 2937 |         if (u132->going > 1) { | 
 | 2938 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 2939 |                         , u132->going); | 
 | 2940 |                 return -ENODEV; | 
 | 2941 |         } else if (u132->going > 0) { | 
 | 2942 |                 dev_err(&u132->platform_dev->dev, "device is being removed\n"); | 
 | 2943 |                 return -ESHUTDOWN; | 
 | 2944 |         } else | 
 | 2945 |                 return 0; | 
 | 2946 | } | 
 | 2947 |  | 
 | 2948 | static void u132_hub_irq_enable(struct usb_hcd *hcd) | 
 | 2949 | { | 
 | 2950 |         struct u132 *u132 = hcd_to_u132(hcd); | 
 | 2951 |         if (u132->going > 1) { | 
 | 2952 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 2953 |                         , u132->going); | 
 | 2954 |         } else if (u132->going > 0) | 
 | 2955 |                 dev_err(&u132->platform_dev->dev, "device is being removed\n"); | 
 | 2956 | } | 
 | 2957 |  | 
 | 2958 |  | 
 | 2959 | #ifdef CONFIG_PM | 
 | 2960 | static int u132_hcd_suspend(struct usb_hcd *hcd, pm_message_t message) | 
 | 2961 | { | 
 | 2962 |         struct u132 *u132 = hcd_to_u132(hcd); | 
 | 2963 |         if (u132->going > 1) { | 
 | 2964 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 2965 |                         , u132->going); | 
 | 2966 |                 return -ENODEV; | 
 | 2967 |         } else if (u132->going > 0) { | 
 | 2968 |                 dev_err(&u132->platform_dev->dev, "device is being removed\n"); | 
 | 2969 |                 return -ESHUTDOWN; | 
 | 2970 |         } else | 
 | 2971 |                 return 0; | 
 | 2972 | } | 
 | 2973 |  | 
 | 2974 | static int u132_hcd_resume(struct usb_hcd *hcd) | 
 | 2975 | { | 
 | 2976 |         struct u132 *u132 = hcd_to_u132(hcd); | 
 | 2977 |         if (u132->going > 1) { | 
 | 2978 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 2979 |                         , u132->going); | 
 | 2980 |                 return -ENODEV; | 
 | 2981 |         } else if (u132->going > 0) { | 
 | 2982 |                 dev_err(&u132->platform_dev->dev, "device is being removed\n"); | 
 | 2983 |                 return -ESHUTDOWN; | 
 | 2984 |         } else | 
 | 2985 |                 return 0; | 
 | 2986 | } | 
 | 2987 |  | 
 | 2988 | static int u132_bus_suspend(struct usb_hcd *hcd) | 
 | 2989 | { | 
 | 2990 |         struct u132 *u132 = hcd_to_u132(hcd); | 
 | 2991 |         if (u132->going > 1) { | 
 | 2992 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 2993 |                         , u132->going); | 
 | 2994 |                 return -ENODEV; | 
 | 2995 |         } else if (u132->going > 0) { | 
 | 2996 |                 dev_err(&u132->platform_dev->dev, "device is being removed\n"); | 
 | 2997 |                 return -ESHUTDOWN; | 
 | 2998 |         } else | 
 | 2999 |                 return 0; | 
 | 3000 | } | 
 | 3001 |  | 
 | 3002 | static int u132_bus_resume(struct usb_hcd *hcd) | 
 | 3003 | { | 
 | 3004 |         struct u132 *u132 = hcd_to_u132(hcd); | 
 | 3005 |         if (u132->going > 1) { | 
 | 3006 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 3007 |                         , u132->going); | 
 | 3008 |                 return -ENODEV; | 
 | 3009 |         } else if (u132->going > 0) { | 
 | 3010 |                 dev_err(&u132->platform_dev->dev, "device is being removed\n"); | 
 | 3011 |                 return -ESHUTDOWN; | 
 | 3012 |         } else | 
 | 3013 |                 return 0; | 
 | 3014 | } | 
 | 3015 |  | 
 | 3016 | #else | 
 | 3017 | #define u132_hcd_suspend NULL | 
 | 3018 | #define u132_hcd_resume NULL | 
 | 3019 | #define u132_bus_suspend NULL | 
 | 3020 | #define u132_bus_resume NULL | 
 | 3021 | #endif | 
 | 3022 | static struct hc_driver u132_hc_driver = { | 
 | 3023 |         .description = hcd_name, | 
 | 3024 |         .hcd_priv_size = sizeof(struct u132), | 
 | 3025 |         .irq = NULL, | 
 | 3026 |         .flags = HCD_USB11 | HCD_MEMORY, | 
 | 3027 |         .reset = u132_hcd_reset, | 
 | 3028 |         .start = u132_hcd_start, | 
 | 3029 |         .suspend = u132_hcd_suspend, | 
 | 3030 |         .resume = u132_hcd_resume, | 
 | 3031 |         .stop = u132_hcd_stop, | 
 | 3032 |         .urb_enqueue = u132_urb_enqueue, | 
 | 3033 |         .urb_dequeue = u132_urb_dequeue, | 
 | 3034 |         .endpoint_disable = u132_endpoint_disable, | 
 | 3035 |         .get_frame_number = u132_get_frame, | 
 | 3036 |         .hub_status_data = u132_hub_status_data, | 
 | 3037 |         .hub_control = u132_hub_control, | 
 | 3038 |         .bus_suspend = u132_bus_suspend, | 
 | 3039 |         .bus_resume = u132_bus_resume, | 
 | 3040 |         .start_port_reset = u132_start_port_reset, | 
 | 3041 |         .hub_irq_enable = u132_hub_irq_enable, | 
 | 3042 | }; | 
 | 3043 |  | 
 | 3044 | /* | 
 | 3045 | * This function may be called by the USB core whilst the "usb_all_devices_rwsem" | 
 | 3046 | * is held for writing, thus this module must not call usb_remove_hcd() | 
 | 3047 | * synchronously - but instead should immediately stop activity to the | 
 | 3048 | * device and ansynchronously call usb_remove_hcd() | 
 | 3049 | */ | 
 | 3050 | static int __devexit u132_remove(struct platform_device *pdev) | 
 | 3051 | { | 
 | 3052 |         struct usb_hcd *hcd = platform_get_drvdata(pdev); | 
 | 3053 |         if (hcd) { | 
 | 3054 |                 struct u132 *u132 = hcd_to_u132(hcd); | 
 | 3055 |                 dump_stack(); | 
 | 3056 |                 if (u132->going++ > 1) { | 
 | 3057 |                         return -ENODEV; | 
 | 3058 |                 } else { | 
 | 3059 |                         int rings = MAX_U132_RINGS; | 
 | 3060 |                         int endps = MAX_U132_ENDPS; | 
 | 3061 |                         msleep(100); | 
 | 3062 |                         down(&u132->sw_lock); | 
 | 3063 |                         u132_monitor_cancel_work(u132); | 
 | 3064 |                         while (rings-- > 0) { | 
 | 3065 |                                 struct u132_ring *ring = &u132->ring[rings]; | 
 | 3066 |                                 u132_ring_cancel_work(u132, ring); | 
 | 3067 |                         } while (endps-- > 0) { | 
 | 3068 |                                 struct u132_endp *endp = u132->endp[endps]; | 
 | 3069 |                                 if (endp) | 
 | 3070 |                                         u132_endp_cancel_work(u132, endp); | 
 | 3071 |                         } | 
 | 3072 |                         u132->going += 1; | 
 | 3073 |                         printk(KERN_INFO "removing device u132.%d\n", | 
 | 3074 |                                 u132->sequence_num); | 
 | 3075 |                         up(&u132->sw_lock); | 
 | 3076 |                         usb_remove_hcd(hcd); | 
 | 3077 |                         u132_u132_put_kref(u132); | 
 | 3078 |                         return 0; | 
 | 3079 |                 } | 
 | 3080 |         } else | 
 | 3081 |                 return 0; | 
 | 3082 | } | 
 | 3083 |  | 
 | 3084 | static void u132_initialise(struct u132 *u132, struct platform_device *pdev) | 
 | 3085 | { | 
 | 3086 |         int rings = MAX_U132_RINGS; | 
 | 3087 |         int ports = MAX_U132_PORTS; | 
 | 3088 |         int addrs = MAX_U132_ADDRS; | 
 | 3089 |         int udevs = MAX_U132_UDEVS; | 
 | 3090 |         int endps = MAX_U132_ENDPS; | 
 | 3091 |         u132->board = pdev->dev.platform_data; | 
 | 3092 |         u132->platform_dev = pdev; | 
 | 3093 |         u132->power = 0; | 
 | 3094 |         u132->reset = 0; | 
 | 3095 |         init_MUTEX(&u132->sw_lock); | 
 | 3096 |         init_MUTEX(&u132->scheduler_lock); | 
 | 3097 |         while (rings-- > 0) { | 
 | 3098 |                 struct u132_ring *ring = &u132->ring[rings]; | 
 | 3099 |                 ring->u132 = u132; | 
 | 3100 |                 ring->number = rings + 1; | 
 | 3101 |                 ring->length = 0; | 
 | 3102 |                 ring->curr_endp = NULL; | 
 | 3103 |                 INIT_WORK(&ring->scheduler, u132_hcd_ring_work_scheduler, | 
 | 3104 |                         (void *)ring); | 
 | 3105 |         } down(&u132->sw_lock); | 
 | 3106 |         INIT_WORK(&u132->monitor, u132_hcd_monitor_work, (void *)u132); | 
 | 3107 |         while (ports-- > 0) { | 
 | 3108 |                 struct u132_port *port = &u132->port[ports]; | 
 | 3109 |                 port->u132 = u132; | 
 | 3110 |                 port->reset = 0; | 
 | 3111 |                 port->enable = 0; | 
 | 3112 |                 port->power = 0; | 
 | 3113 |                 port->Status = 0; | 
 | 3114 |         } while (addrs-- > 0) { | 
 | 3115 |                 struct u132_addr *addr = &u132->addr[addrs]; | 
 | 3116 |                 addr->address = 0; | 
 | 3117 |         } while (udevs-- > 0) { | 
 | 3118 |                 struct u132_udev *udev = &u132->udev[udevs]; | 
 | 3119 |                 int i = ARRAY_SIZE(udev->endp_number_in); | 
 | 3120 |                 int o = ARRAY_SIZE(udev->endp_number_out); | 
 | 3121 |                 udev->usb_device = NULL; | 
 | 3122 |                 udev->udev_number = 0; | 
 | 3123 |                 udev->usb_addr = 0; | 
 | 3124 |                 udev->portnumber = 0; | 
 | 3125 |                 while (i-- > 0) { | 
 | 3126 |                         udev->endp_number_in[i] = 0; | 
 | 3127 |                 } | 
 | 3128 |                 while (o-- > 0) { | 
 | 3129 |                         udev->endp_number_out[o] = 0; | 
 | 3130 |                 } | 
 | 3131 |         } | 
 | 3132 |         while (endps-- > 0) { | 
 | 3133 |                 u132->endp[endps] = NULL; | 
 | 3134 |         } | 
 | 3135 |         up(&u132->sw_lock); | 
 | 3136 |         return; | 
 | 3137 | } | 
 | 3138 |  | 
 | 3139 | static int __devinit u132_probe(struct platform_device *pdev) | 
 | 3140 | { | 
 | 3141 |         struct usb_hcd *hcd; | 
 | 3142 |         msleep(100); | 
 | 3143 |         if (u132_exiting > 0) { | 
 | 3144 |                 return -ENODEV; | 
 | 3145 |         }                        /* refuse to confuse usbcore */ | 
 | 3146 |         if (pdev->dev.dma_mask) { | 
 | 3147 |                 return -EINVAL; | 
 | 3148 |         } | 
 | 3149 |         hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, pdev->dev.bus_id); | 
 | 3150 |         if (!hcd) { | 
 | 3151 |                 printk(KERN_ERR "failed to create the usb hcd struct for U132\n" | 
 | 3152 |                         ); | 
 | 3153 |                 ftdi_elan_gone_away(pdev); | 
 | 3154 |                 return -ENOMEM; | 
 | 3155 |         } else { | 
 | 3156 |                 int retval = 0; | 
 | 3157 |                 struct u132 *u132 = hcd_to_u132(hcd); | 
 | 3158 |                 hcd->rsrc_start = 0; | 
 | 3159 |                 down(&u132_module_lock); | 
 | 3160 |                 list_add_tail(&u132->u132_list, &u132_static_list); | 
 | 3161 |                 u132->sequence_num = ++u132_instances; | 
 | 3162 |                 up(&u132_module_lock); | 
 | 3163 |                 u132_u132_init_kref(u132); | 
 | 3164 |                 u132_initialise(u132, pdev); | 
 | 3165 |                 hcd->product_desc = "ELAN U132 Host Controller"; | 
 | 3166 |                 retval = usb_add_hcd(hcd, 0, 0); | 
 | 3167 |                 if (retval != 0) { | 
 | 3168 |                         dev_err(&u132->platform_dev->dev, "init error %d\n", | 
 | 3169 |                                 retval); | 
 | 3170 |                         u132_u132_put_kref(u132); | 
 | 3171 |                         return retval; | 
 | 3172 |                 } else { | 
 | 3173 |                         u132_monitor_queue_work(u132, 100); | 
 | 3174 |                         return 0; | 
 | 3175 |                 } | 
 | 3176 |         } | 
 | 3177 | } | 
 | 3178 |  | 
 | 3179 |  | 
 | 3180 | #ifdef CONFIG_PM | 
 | 3181 | /* for this device there's no useful distinction between the controller | 
 | 3182 | * and its root hub, except that the root hub only gets direct PM calls | 
 | 3183 | * when CONFIG_USB_SUSPEND is enabled. | 
 | 3184 | */ | 
 | 3185 | static int u132_suspend(struct platform_device *pdev, pm_message_t state) | 
 | 3186 | { | 
 | 3187 |         struct usb_hcd *hcd = platform_get_drvdata(pdev); | 
 | 3188 |         struct u132 *u132 = hcd_to_u132(hcd); | 
 | 3189 |         if (u132->going > 1) { | 
 | 3190 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 3191 |                         , u132->going); | 
 | 3192 |                 return -ENODEV; | 
 | 3193 |         } else if (u132->going > 0) { | 
 | 3194 |                 dev_err(&u132->platform_dev->dev, "device is being removed\n"); | 
 | 3195 |                 return -ESHUTDOWN; | 
 | 3196 |         } else { | 
 | 3197 |                 int retval = 0; | 
 | 3198 |                 if (state.event == PM_EVENT_FREEZE) { | 
 | 3199 |                         retval = u132_bus_suspend(hcd); | 
 | 3200 |                 } else if (state.event == PM_EVENT_SUSPEND) { | 
 | 3201 |                         int ports = MAX_U132_PORTS; | 
 | 3202 |                         while (ports-- > 0) { | 
 | 3203 |                                 port_power(u132, ports, 0); | 
 | 3204 |                         } | 
 | 3205 |                 } | 
 | 3206 |                 if (retval == 0) | 
 | 3207 |                         pdev->dev.power.power_state = state; | 
 | 3208 |                 return retval; | 
 | 3209 |         } | 
 | 3210 | } | 
 | 3211 |  | 
 | 3212 | static int u132_resume(struct platform_device *pdev) | 
 | 3213 | { | 
 | 3214 |         struct usb_hcd *hcd = platform_get_drvdata(pdev); | 
 | 3215 |         struct u132 *u132 = hcd_to_u132(hcd); | 
 | 3216 |         if (u132->going > 1) { | 
 | 3217 |                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 
 | 3218 |                         , u132->going); | 
 | 3219 |                 return -ENODEV; | 
 | 3220 |         } else if (u132->going > 0) { | 
 | 3221 |                 dev_err(&u132->platform_dev->dev, "device is being removed\n"); | 
 | 3222 |                 return -ESHUTDOWN; | 
 | 3223 |         } else { | 
 | 3224 |                 int retval = 0; | 
 | 3225 |                 if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { | 
 | 3226 |                         int ports = MAX_U132_PORTS; | 
 | 3227 |                         while (ports-- > 0) { | 
 | 3228 |                                 port_power(u132, ports, 1); | 
 | 3229 |                         } | 
 | 3230 |                         retval = 0; | 
 | 3231 |                 } else { | 
 | 3232 |                         pdev->dev.power.power_state = PMSG_ON; | 
 | 3233 |                         retval = u132_bus_resume(hcd); | 
 | 3234 |                 } | 
 | 3235 |                 return retval; | 
 | 3236 |         } | 
 | 3237 | } | 
 | 3238 |  | 
 | 3239 | #else | 
 | 3240 | #define u132_suspend NULL | 
 | 3241 | #define u132_resume NULL | 
 | 3242 | #endif | 
 | 3243 | /* | 
 | 3244 | * this driver is loaded explicitely by ftdi_u132 | 
 | 3245 | * | 
 | 3246 | * the platform_driver struct is static because it is per type of module | 
 | 3247 | */ | 
 | 3248 | static struct platform_driver u132_platform_driver = { | 
 | 3249 |         .probe = u132_probe, | 
 | 3250 |         .remove = __devexit_p(u132_remove), | 
 | 3251 |         .suspend = u132_suspend, | 
 | 3252 |         .resume = u132_resume, | 
 | 3253 |         .driver = { | 
 | 3254 |                    .name = (char *)hcd_name, | 
 | 3255 |                    .owner = THIS_MODULE, | 
 | 3256 |                    }, | 
 | 3257 | }; | 
 | 3258 | static int __init u132_hcd_init(void) | 
 | 3259 | { | 
 | 3260 |         int retval; | 
 | 3261 |         INIT_LIST_HEAD(&u132_static_list); | 
 | 3262 |         u132_instances = 0; | 
 | 3263 |         u132_exiting = 0; | 
 | 3264 |         init_MUTEX(&u132_module_lock); | 
 | 3265 |         if (usb_disabled()) | 
 | 3266 |                 return -ENODEV; | 
 | 3267 |         printk(KERN_INFO "driver %s built at %s on %s\n", hcd_name, __TIME__, | 
 | 3268 |                 __DATE__); | 
 | 3269 |         workqueue = create_singlethread_workqueue("u132"); | 
 | 3270 |         retval = platform_driver_register(&u132_platform_driver); | 
 | 3271 |         return retval; | 
 | 3272 | } | 
 | 3273 |  | 
 | 3274 |  | 
 | 3275 | module_init(u132_hcd_init); | 
 | 3276 | static void __exit u132_hcd_exit(void) | 
 | 3277 | { | 
 | 3278 |         struct u132 *u132; | 
 | 3279 |         struct u132 *temp; | 
 | 3280 |         down(&u132_module_lock); | 
 | 3281 |         u132_exiting += 1; | 
 | 3282 |         up(&u132_module_lock); | 
 | 3283 |         list_for_each_entry_safe(u132, temp, &u132_static_list, u132_list) { | 
 | 3284 |                 platform_device_unregister(u132->platform_dev); | 
 | 3285 |         } platform_driver_unregister(&u132_platform_driver); | 
 | 3286 |         printk(KERN_INFO "u132-hcd driver deregistered\n"); | 
 | 3287 |         wait_event(u132_hcd_wait, u132_instances == 0); | 
 | 3288 |         flush_workqueue(workqueue); | 
 | 3289 |         destroy_workqueue(workqueue); | 
 | 3290 | } | 
 | 3291 |  | 
 | 3292 |  | 
 | 3293 | module_exit(u132_hcd_exit); | 
 | 3294 | MODULE_LICENSE("GPL"); |