Changeset 0892663a in mainline
- Timestamp:
- 2018-01-11T04:14:37Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 9848c77
- Parents:
- bad4a05
- git-author:
- Ondřej Hlavatý <aearsis@…> (2018-01-11 03:59:03)
- git-committer:
- Ondřej Hlavatý <aearsis@…> (2018-01-11 04:14:37)
- Location:
- uspace
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ehci/ehci_bus.c
rbad4a05 r0892663a 135 135 } 136 136 137 static int ehci_device_online(device_t *device)138 {139 int err;140 141 /* Allow creation of new endpoints and transfers. */142 usb_log_info("Device(%d): Going online.", device->address);143 fibril_mutex_lock(&device->guard);144 device->online = true;145 fibril_mutex_unlock(&device->guard);146 147 if ((err = ddf_fun_online(device->fun))) {148 return err;149 }150 151 return EOK;152 }153 154 static int ehci_device_offline(device_t *device)155 {156 int err;157 158 /* Tear down all drivers working with the device. */159 if ((err = ddf_fun_offline(device->fun))) {160 return err;161 }162 163 /* At this point, all drivers are assumed to have already terminated164 * in a consistent way. The following code just cleans up hanging165 * transfers if there are any. */166 167 /* Block creation of new endpoints and transfers. */168 usb_log_info("Device(%d): Going offline.", device->address);169 fibril_mutex_lock(&device->guard);170 device->online = false;171 fibril_mutex_unlock(&device->guard);172 173 /* FIXME: Abort all transfers to all endpoints. */174 175 return EOK;176 }177 178 137 static const bus_ops_t ehci_bus_ops = { 179 138 .parent = &usb2_bus_ops, … … 190 149 .batch_destroy = ehci_destroy_batch, 191 150 .batch_schedule = ehci_hc_schedule, 192 .device_online = ehci_device_online,193 .device_offline = ehci_device_offline,194 151 }; 195 152 -
uspace/drv/bus/usb/uhci/hc.c
rbad4a05 r0892663a 321 321 } 322 322 323 static int device_online(device_t *device) 324 { 325 int err; 326 hc_t *instance = bus_to_hc(device->bus); 327 assert(instance); 328 329 /* Allow creation of new endpoints and transfers. */ 330 usb_log_info("Device(%d): Going online.", device->address); 331 fibril_mutex_lock(&device->guard); 332 device->online = true; 333 fibril_mutex_unlock(&device->guard); 334 335 if ((err = ddf_fun_online(device->fun))) { 336 return err; 337 } 338 339 return EOK; 340 } 341 342 static int device_offline(device_t *device) 343 { 344 int err; 345 hc_t *instance = bus_to_hc(device->bus); 346 assert(instance); 347 348 /* Tear down all drivers working with the device. */ 349 if ((err = ddf_fun_offline(device->fun))) { 350 return err; 351 } 352 353 /* At this point, all drivers are assumed to have already terminated 354 * in a consistent way. The following code just cleans up hanging 355 * transfers if there are any. */ 356 357 /* Block creation of new endpoints and transfers. */ 358 usb_log_info("Device(%d): Going offline.", device->address); 359 fibril_mutex_lock(&device->guard); 360 device->online = false; 361 fibril_mutex_unlock(&device->guard); 362 363 /* Abort all transfers to all endpoints. */ 364 transfer_list_abort_device(&instance->transfers_interrupt, device->address); 365 transfer_list_abort_device(&instance->transfers_control_slow, device->address); 366 transfer_list_abort_device(&instance->transfers_control_full, device->address); 367 transfer_list_abort_device(&instance->transfers_bulk_full, device->address); 368 369 return EOK; 323 static void endpoint_unregister(endpoint_t *ep) 324 { 325 usb2_bus_ops.endpoint_unregister(ep); 326 327 fibril_mutex_lock(&ep->guard); 328 if (ep->active_batch) { 329 uhci_transfer_batch_t *ub = uhci_transfer_batch_get(ep->active_batch); 330 uhci_transfer_batch_abort(ub); 331 332 assert(ep->active_batch == NULL); 333 } 334 fibril_mutex_unlock(&ep->guard); 370 335 } 371 336 … … 379 344 .status = hc_status, 380 345 346 .endpoint_unregister = endpoint_unregister, 381 347 .endpoint_count_bw = bandwidth_count_usb11, 348 382 349 .batch_create = create_transfer_batch, 383 350 .batch_schedule = hc_schedule, 384 351 .batch_destroy = destroy_transfer_batch, 385 386 .device_online = device_online,387 .device_offline = device_offline,388 352 }; 389 353 … … 522 486 static int hc_schedule(usb_transfer_batch_t *batch) 523 487 { 488 assert(batch); 524 489 hc_t *instance = bus_to_hc(endpoint_get_bus(batch->ep)); 525 assert(batch);526 490 527 491 if (batch->target.address == uhci_rh_get_address(&instance->rh)) -
uspace/drv/bus/usb/uhci/transfer_list.c
rbad4a05 r0892663a 194 194 while (!list_empty(&instance->batch_list)) { 195 195 link_t * const current = list_first(&instance->batch_list); 196 uhci_transfer_batch_t *batch = 197 uhci_transfer_batch_from_link(current); 196 uhci_transfer_batch_t *batch = uhci_transfer_batch_from_link(current); 198 197 transfer_list_remove_batch(instance, batch); 199 endpoint_abort(batch->base.ep);200 }201 fibril_mutex_unlock(&instance->guard);202 }203 204 /** Walk the list and finish all batches of a specified device with EINTR.205 *206 * @param[in] instance List to use.207 * @param[in] address Address of the specified device. Other addresses are skipped.208 */209 void transfer_list_abort_device(transfer_list_t *instance, usb_address_t address)210 {211 fibril_mutex_lock(&instance->guard);212 link_t *current = list_first(&instance->batch_list);213 while (current && current != &instance->batch_list.head && !list_empty(&instance->batch_list)) {214 link_t * const next = current->next;215 uhci_transfer_batch_t *batch =216 uhci_transfer_batch_from_link(current);217 218 if (batch->base.target.address == address) {219 transfer_list_remove_batch(instance, batch);220 endpoint_abort(batch->base.ep);221 }222 223 current = next;224 198 } 225 199 fibril_mutex_unlock(&instance->guard); -
uspace/drv/bus/usb/uhci/transfer_list.h
rbad4a05 r0892663a 63 63 void transfer_list_remove_finished(transfer_list_t *instance, list_t *done); 64 64 void transfer_list_abort_all(transfer_list_t *instance); 65 void transfer_list_abort_device(transfer_list_t *instance, usb_address_t address);66 65 67 66 #endif -
uspace/drv/bus/usb/uhci/uhci_batch.c
rbad4a05 r0892663a 64 64 } 65 65 66 /** 67 * Abort a transfer that is currently running. 68 * Call with endpoint guard locked. 69 */ 70 void uhci_transfer_batch_abort(uhci_transfer_batch_t *batch) 71 { 72 assert(batch); 73 74 endpoint_t *ep = batch->base.ep; 75 assert(ep); 76 assert(fibril_mutex_is_locked(&ep->guard)); 77 assert(ep->active_batch == &batch->base); 78 79 /* 80 * TODO: Do some magic here to remove the batch from schedule. 81 */ 82 83 /* 84 * Wait for 2 frames. If the transfer was being processed, 85 * it shall be marked as finished already after 1ms. 86 */ 87 endpoint_wait_timeout_locked(ep, 2000); 88 if (ep->active_batch != &batch->base) 89 return; 90 91 /* 92 * Now, we can be sure the transfer is not scheduled, 93 * and as such will not be completed. We now own the batch. 94 */ 95 endpoint_deactivate_locked(ep); 96 97 /* Leave the critical section for finishing the batch. */ 98 fibril_mutex_unlock(&ep->guard); 99 100 batch->base.error = EINTR; 101 batch->base.transfered_size = 0; 102 usb_transfer_batch_finish(&batch->base); 103 104 fibril_mutex_lock(&ep->guard); 105 } 106 66 107 /** Allocate memory and initialize internal data structure. 67 108 * -
uspace/drv/bus/usb/uhci/uhci_batch.h
rbad4a05 r0892663a 70 70 int uhci_transfer_batch_prepare(uhci_transfer_batch_t *); 71 71 bool uhci_transfer_batch_check_completed(uhci_transfer_batch_t *); 72 void uhci_transfer_batch_ finish(uhci_transfer_batch_t *);72 void uhci_transfer_batch_abort(uhci_transfer_batch_t *); 73 73 void uhci_transfer_batch_destroy(uhci_transfer_batch_t *); 74 74 -
uspace/drv/bus/usb/xhci/bus.c
rbad4a05 r0892663a 209 209 xhci_device_t *xhci_dev = xhci_device_get(dev); 210 210 211 /* Block creation of new endpoints and transfers. */212 usb_log_debug2("Device " XHCI_DEV_FMT " going offline.", XHCI_DEV_ARGS(*xhci_dev));213 fibril_mutex_lock(&dev->guard);214 dev->online = false;215 fibril_mutex_unlock(&dev->guard);216 217 /* Abort running transfers. */218 usb_log_debug2("Aborting all active transfers to device " XHCI_DEV_FMT ".", XHCI_DEV_ARGS(*xhci_dev));219 for (usb_endpoint_t i = 0; i < USB_ENDPOINT_MAX; ++i) {220 xhci_endpoint_t *ep = xhci_device_get_endpoint(xhci_dev, i);221 if (!ep)222 continue;223 224 endpoint_abort(&ep->base);225 }226 227 /* TODO: Figure out how to handle errors here. So far, they are reported and skipped. */228 229 /* Make DDF (and all drivers) forget about the device. */230 if ((err = ddf_fun_unbind(dev->fun))) {231 usb_log_warning("Failed to unbind DDF function of device " XHCI_DEV_FMT ": %s",232 XHCI_DEV_ARGS(*xhci_dev), str_error(err));233 }234 235 211 /* Disable the slot, dropping all endpoints. */ 236 212 const uint32_t slot_id = xhci_dev->slot_id; … … 241 217 242 218 bus->devices_by_slot[slot_id] = NULL; 243 244 /* Unregister remaining endpoints, freeing memory. */245 for (usb_endpoint_t i = 0; i < USB_ENDPOINT_MAX; ++i) {246 if (!dev->endpoints[i])247 continue;248 249 bus_endpoint_remove(dev->endpoints[i]);250 }251 252 /* Destroy DDF device. */253 /* XXX: Not a good idea, this method should not destroy devices. */254 hcd_ddf_fun_destroy(dev);255 219 } 256 220 … … 273 237 if ((err = hc_configure_device(bus->hc, dev->slot_id))) { 274 238 usb_log_warning("Failed to configure device " XHCI_DEV_FMT ".", XHCI_DEV_ARGS(*dev)); 275 }276 277 /* Allow creation of new endpoints and transfers. */278 usb_log_debug2("Device " XHCI_DEV_FMT " going online.", XHCI_DEV_ARGS(*dev));279 fibril_mutex_lock(&dev_base->guard);280 dev_base->online = true;281 fibril_mutex_unlock(&dev_base->guard);282 283 if ((err = ddf_fun_online(dev_base->fun))) {284 239 return err; 285 240 } … … 294 249 * Bus callback. 295 250 */ 296 static intdevice_offline(device_t *dev_base)251 static void device_offline(device_t *dev_base) 297 252 { 298 253 int err; … … 303 258 xhci_device_t *dev = xhci_device_get(dev_base); 304 259 assert(dev); 305 306 /* Tear down all drivers working with the device. */307 if ((err = ddf_fun_offline(dev_base->fun))) {308 return err;309 }310 311 /* Block creation of new endpoints and transfers. */312 usb_log_debug2("Device " XHCI_DEV_FMT " going offline.", XHCI_DEV_ARGS(*dev));313 fibril_mutex_lock(&dev_base->guard);314 dev_base->online = false;315 fibril_mutex_unlock(&dev_base->guard);316 317 /* We will need the endpoint array later for DS deallocation. */318 endpoint_t *endpoints[USB_ENDPOINT_MAX];319 memcpy(endpoints, dev->base.endpoints, sizeof(endpoints));320 321 for (usb_endpoint_t i = 1; i < USB_ENDPOINT_MAX; ++i) {322 /* FIXME: Asserting here that the endpoint is not active. If not, EBUSY? */323 dev->base.endpoints[i] = NULL;324 }325 260 326 261 /* Issue one HC command to simultaneously drop all endpoints except zero. */ … … 329 264 XHCI_DEV_ARGS(*dev)); 330 265 } 331 332 /* Tear down TRB ring / PSA. */333 for (unsigned i = 1; i < ARRAY_SIZE(endpoints); ++i) {334 if (!endpoints[i])335 continue;336 337 /* Bus reference */338 endpoint_del_ref(endpoints[i]);339 }340 341 return EOK;342 266 } 343 267 … … 378 302 379 303 /** 380 * Register an andpoint to the bus. Allocate its transfer ring(s) and inform 381 * xHC about it. 304 * Register an andpoint to the xHC. 382 305 * 383 306 * Bus callback. 384 307 */ 385 308 static int endpoint_register(endpoint_t *ep_base) 386 {387 int err;388 xhci_bus_t *bus = bus_to_xhci_bus(endpoint_get_bus(ep_base));389 xhci_endpoint_t *ep = xhci_endpoint_get(ep_base);390 391 xhci_device_t *dev = xhci_device_get(ep_base->device);392 393 usb_log_info("Endpoint " XHCI_EP_FMT " registered to XHCI bus.", XHCI_EP_ARGS(*ep));394 395 xhci_ep_ctx_t ep_ctx;396 xhci_setup_endpoint_context(ep, &ep_ctx);397 398 if ((err = hc_add_endpoint(bus->hc, dev->slot_id, xhci_endpoint_index(ep), &ep_ctx)))399 return err;400 401 return EOK;402 }403 404 /**405 * Unregister an endpoint. If the device is still available, inform the xHC406 * about it. Destroy resources allocated when registering.407 *408 * Bus callback.409 */410 static void endpoint_unregister(endpoint_t *ep_base)411 309 { 412 310 int err; … … 415 313 xhci_device_t *dev = xhci_device_get(ep_base->device); 416 314 417 usb_log_info("Endpoint " XHCI_EP_FMT " unregistered from XHCI bus.", XHCI_EP_ARGS(*ep)); 315 xhci_ep_ctx_t ep_ctx; 316 xhci_setup_endpoint_context(ep, &ep_ctx); 317 318 if ((err = hc_add_endpoint(bus->hc, dev->slot_id, xhci_endpoint_index(ep), &ep_ctx))) 319 return err; 320 321 return EOK; 322 } 323 324 /** 325 * Unregister an endpoint. If the device is still available, inform the xHC 326 * about it. 327 * 328 * Bus callback. 329 */ 330 static void endpoint_unregister(endpoint_t *ep_base) 331 { 332 int err; 333 xhci_bus_t *bus = bus_to_xhci_bus(endpoint_get_bus(ep_base)); 334 xhci_endpoint_t *ep = xhci_endpoint_get(ep_base); 335 xhci_device_t *dev = xhci_device_get(ep_base->device); 418 336 419 337 /* If device slot is still available, drop the endpoint. */ -
uspace/lib/usbhost/include/usb/host/bus.h
rbad4a05 r0892663a 105 105 void (*device_remove)(device_t *); 106 106 int (*device_online)(device_t *); /**< Optional */ 107 int(*device_offline)(device_t *); /**< Optional */107 void (*device_offline)(device_t *); /**< Optional */ 108 108 endpoint_t *(*endpoint_create)(device_t *, const usb_endpoint_descriptors_t *); 109 109 -
uspace/lib/usbhost/include/usb/host/endpoint.h
rbad4a05 r0892663a 44 44 #include <fibril_synch.h> 45 45 #include <stdbool.h> 46 #include <sys/time.h> 46 47 #include <usb/usb.h> 47 48 #include <usb/host/bus.h> … … 93 94 extern void endpoint_del_ref(endpoint_t *); 94 95 95 /* Pay atention to synchronization of batch access wrt to aborting & finishing from another fibril. */ 96 97 /* Set currently active batch. The common case is to activate in the same 98 * critical section as scheduling to HW. 99 */ 96 extern void endpoint_wait_timeout_locked(endpoint_t *ep, suseconds_t); 100 97 extern void endpoint_activate_locked(endpoint_t *, usb_transfer_batch_t *); 101 102 /* Deactivate the endpoint, allowing others to activate it again. Batch shall103 * already have an error set. */104 98 extern void endpoint_deactivate_locked(endpoint_t *); 105 106 /* Abort the currenty active batch. */107 void endpoint_abort(endpoint_t *);108 99 109 100 /* Calculate bandwidth */ -
uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h
rbad4a05 r0892663a 112 112 113 113 /** Batch finalization. */ 114 void usb_transfer_batch_abort(usb_transfer_batch_t *);115 114 void usb_transfer_batch_finish(usb_transfer_batch_t *); 116 115 -
uspace/lib/usbhost/src/bus.c
rbad4a05 r0892663a 43 43 #include <mem.h> 44 44 #include <stdio.h> 45 #include <str_error.h> 45 46 #include <usb/debug.h> 46 47 … … 97 98 /** 98 99 * Invoke the device_enumerate bus operation. 100 * 101 * There's no need to synchronize here, because no one knows the device yet. 99 102 */ 100 103 int bus_device_enumerate(device_t *dev) … … 106 109 return ENOTSUP; 107 110 108 return ops->device_enumerate(dev); 109 } 110 111 /** 112 * Invoke the device_remove bus operation. 111 if (dev->online) { 112 fibril_mutex_unlock(&dev->guard); 113 return EINVAL; 114 } 115 116 const int r = ops->device_enumerate(dev); 117 if (!r) { 118 dev->online = true; 119 120 fibril_mutex_lock(&dev->hub->guard); 121 list_append(&dev->link, &dev->hub->devices); 122 fibril_mutex_unlock(&dev->hub->guard); 123 } 124 125 return r; 126 } 127 128 /** 129 * Clean endpoints and children that could have been left behind after 130 * asking the driver of device to offline/remove a device. 131 * 132 * Note that EP0's lifetime is shared with the device, and as such is not 133 * touched. 134 */ 135 static void device_clean_ep_children(device_t *dev, const char *op) 136 { 137 assert(fibril_mutex_is_locked(&dev->guard)); 138 139 /* Unregister endpoints left behind. */ 140 for (usb_endpoint_t i = 1; i < USB_ENDPOINT_MAX; ++i) { 141 if (!dev->endpoints[i]) 142 continue; 143 144 usb_log_warning("USB device '%s' driver left endpoint %u registered after %s.", 145 ddf_fun_get_name(dev->fun), i, op); 146 147 endpoint_t * const ep = dev->endpoints[i]; 148 endpoint_add_ref(ep); 149 150 fibril_mutex_unlock(&dev->guard); 151 bus_endpoint_remove(ep); 152 fibril_mutex_lock(&dev->guard); 153 154 assert(dev->endpoints[i] == NULL); 155 } 156 157 /* Remove also orphaned children. */ 158 while (!list_empty(&dev->devices)) { 159 device_t * const child = list_get_instance(list_first(&dev->devices), device_t, link); 160 161 usb_log_warning("USB device '%s' driver left device '%s' behind after %s.", 162 ddf_fun_get_name(dev->fun), ddf_fun_get_name(child->fun), op); 163 /* 164 * The child node won't disappear, because its parent's driver 165 * is already dead. And the child will need the guard to remove 166 * itself from the list. 167 */ 168 fibril_mutex_unlock(&dev->guard); 169 bus_device_remove(child); 170 fibril_mutex_lock(&dev->guard); 171 } 172 assert(list_empty(&dev->devices)); 173 } 174 175 /** 176 * Resolve a USB device that is gone. 113 177 */ 114 178 void bus_device_remove(device_t *dev) 115 179 { 116 180 assert(dev); 181 assert(dev->fun == NULL); 117 182 118 183 const bus_ops_t *ops = BUS_OPS_LOOKUP(dev->bus->ops, device_remove); 119 184 assert(ops); 120 185 121 return ops->device_remove(dev); 122 } 123 124 /** 125 * Invoke the device_online bus operation. 186 /* First, block new transfers and operations. */ 187 fibril_mutex_lock(&dev->guard); 188 dev->online = false; 189 190 /* Unbinding will need guard unlocked. */ 191 fibril_mutex_unlock(&dev->guard); 192 193 /* Remove our device from our hub's children. */ 194 fibril_mutex_lock(&dev->hub->guard); 195 list_remove(&dev->link); 196 fibril_mutex_unlock(&dev->hub->guard); 197 198 /* 199 * Unbind the DDF function. That will result in dev_gone called in 200 * driver, which shall destroy its pipes and remove its children. 201 */ 202 const int err = ddf_fun_unbind(dev->fun); 203 if (err) { 204 usb_log_error("Failed to unbind USB device '%s': %s", 205 ddf_fun_get_name(dev->fun), str_error(err)); 206 return; 207 } 208 209 /* Remove what driver left behind */ 210 fibril_mutex_lock(&dev->guard); 211 device_clean_ep_children(dev, "removing"); 212 213 /* Tell the HC to release its resources. */ 214 ops->device_remove(dev); 215 216 /* Release the EP0 bus reference */ 217 endpoint_del_ref(dev->endpoints[0]); 218 219 /* Destroy the function, freeing also the device, unlocking mutex. */ 220 ddf_fun_destroy(dev->fun); 221 } 222 223 /** 224 * The user wants this device back online. 126 225 */ 127 226 int bus_device_online(device_t *dev) 128 227 { 228 int err; 129 229 assert(dev); 130 230 231 fibril_mutex_lock(&dev->guard); 232 if (dev->online) { 233 fibril_mutex_unlock(&dev->guard); 234 return EINVAL; 235 } 236 237 /* First, tell the HC driver. */ 131 238 const bus_ops_t *ops = BUS_OPS_LOOKUP(dev->bus->ops, device_online); 132 if (!ops) 133 return ENOTSUP; 134 135 return ops->device_online(dev); 136 } 137 138 /** 139 * Invoke the device_offline bus operation. 239 if (ops && (err = ops->device_online(dev))) { 240 usb_log_warning("Host controller refused to make device '%s' online: %s", 241 ddf_fun_get_name(dev->fun), str_error(err)); 242 return err; 243 } 244 245 /* Allow creation of new endpoints and communication with the device. */ 246 dev->online = true; 247 248 /* Onlining will need the guard */ 249 fibril_mutex_unlock(&dev->guard); 250 251 if ((err = ddf_fun_online(dev->fun))) { 252 usb_log_warning("Failed to take device '%s' online: %s", 253 ddf_fun_get_name(dev->fun), str_error(err)); 254 return err; 255 } 256 257 usb_log_info("USB Device '%s' offlined.", ddf_fun_get_name(dev->fun)); 258 return EOK; 259 } 260 261 /** 262 * The user requested to take this device offline. 140 263 */ 141 264 int bus_device_offline(device_t *dev) 142 265 { 266 int err; 143 267 assert(dev); 144 268 269 /* Make sure we're the one who offlines this device */ 270 if (!dev->online) 271 return ENOENT; 272 273 /* 274 * XXX: If the device is removed/offlined just now, this can fail on 275 * assertion. We most probably need some kind of enum status field to 276 * make the synchronization work. 277 */ 278 279 /* Tear down all drivers working with the device. */ 280 if ((err = ddf_fun_offline(dev->fun))) { 281 return err; 282 } 283 284 fibril_mutex_lock(&dev->guard); 285 dev->online = false; 286 device_clean_ep_children(dev, "offlining"); 287 288 /* Tell also the HC driver. */ 145 289 const bus_ops_t *ops = BUS_OPS_LOOKUP(dev->bus->ops, device_offline); 146 if (!ops) 147 return ENOTSUP; 148 149 return ops->device_offline(dev); 290 if (ops) 291 ops->device_offline(dev); 292 293 fibril_mutex_unlock(&dev->guard); 294 usb_log_info("USB Device '%s' offlined.", ddf_fun_get_name(dev->fun)); 295 return EOK; 150 296 } 151 297 … … 269 415 fibril_mutex_unlock(&device->guard); 270 416 271 /* Abort a transfer batch, if there was any */272 endpoint_abort(ep);273 274 417 /* Bus reference */ 275 418 endpoint_del_ref(ep); -
uspace/lib/usbhost/src/ddf_helpers.c
rbad4a05 r0892663a 336 336 assert(device); 337 337 338 hc_device_t *hcd = dev_to_hcd(device); 339 assert(hcd); 340 assert(hcd->bus); 338 device_t *victim = NULL; 341 339 342 340 fibril_mutex_lock(&hub->guard); 343 344 device_t *victim = NULL;345 346 341 list_foreach(hub->devices, link, device_t, it) { 347 342 if (it->port == port) { … … 350 345 } 351 346 } 352 if (victim) {353 assert(victim->fun);354 assert(victim->port == port);355 assert(victim->hub == hub);356 list_remove(&victim->link);357 fibril_mutex_unlock(&hub->guard);358 const int ret = ddf_fun_unbind(victim->fun);359 if (ret == EOK) {360 bus_device_remove(victim);361 ddf_fun_destroy(victim->fun);362 } else {363 usb_log_warning("Failed to unbind device `%s': %s\n",364 ddf_fun_get_name(victim->fun), str_error(ret));365 }366 return EOK;367 }368 347 fibril_mutex_unlock(&hub->guard); 369 return ENOENT; 348 349 if (!victim) 350 return ENOENT; 351 352 assert(victim->fun); 353 assert(victim->port == port); 354 assert(victim->hub == hub); 355 356 bus_device_remove(victim); 357 return EOK; 370 358 } 371 359 … … 477 465 } 478 466 479 fibril_mutex_lock(&hub->guard);480 list_append(&dev->link, &hub->devices);481 fibril_mutex_unlock(&hub->guard);482 483 467 return EOK; 484 468 -
uspace/lib/usbhost/src/endpoint.c
rbad4a05 r0892663a 124 124 125 125 /** 126 * Wait until the endpoint have no transfer scheduled. 127 */ 128 void endpoint_wait_timeout_locked(endpoint_t *ep, suseconds_t timeout) 129 { 130 assert(fibril_mutex_is_locked(&ep->guard)); 131 132 while (ep->active_batch != NULL) 133 fibril_condvar_wait_timeout(&ep->avail, &ep->guard, timeout); 134 } 135 136 /** 126 137 * Mark the endpoint as active and block access for further fibrils. If the 127 138 * endpoint is already active, it will block on ep->avail condvar. … … 138 149 assert(batch); 139 150 assert(batch->ep == ep); 140 assert(fibril_mutex_is_locked(&ep->guard)); 141 142 while (ep->active_batch != NULL) 143 fibril_condvar_wait(&ep->avail, &ep->guard); 151 152 endpoint_wait_timeout_locked(ep, 0); 144 153 ep->active_batch = batch; 145 154 } … … 160 169 ep->active_batch = NULL; 161 170 fibril_condvar_signal(&ep->avail); 162 }163 164 /**165 * Abort an active batch on endpoint, if any.166 *167 * @param[in] ep endpoint_t structure.168 */169 void endpoint_abort(endpoint_t *ep)170 {171 assert(ep);172 173 fibril_mutex_lock(&ep->guard);174 usb_transfer_batch_t *batch = ep->active_batch;175 endpoint_deactivate_locked(ep);176 fibril_mutex_unlock(&ep->guard);177 178 if (batch)179 usb_transfer_batch_abort(batch);180 171 } 181 172 -
uspace/lib/usbhost/src/usb_transfer_batch.c
rbad4a05 r0892663a 128 128 129 129 /** 130 * Finish a transfer batch as an aborted one.131 */132 void usb_transfer_batch_abort(usb_transfer_batch_t *batch)133 {134 assert(batch);135 assert(batch->ep);136 137 batch->error = EAGAIN;138 usb_transfer_batch_finish(batch);139 }140 141 /**142 130 * @} 143 131 */
Note:
See TracChangeset
for help on using the changeset viewer.