Changeset 17873ac7 in mainline
- Timestamp:
- 2017-10-31T19:06:57Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 479e32d
- Parents:
- a312d8f
- Location:
- uspace
- Files:
-
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/uhci/hc.c
ra312d8f r17873ac7 177 177 uhci_transfer_batch_t *batch = 178 178 uhci_transfer_batch_from_link(current); 179 u hci_transfer_batch_finish(batch);179 usb_transfer_batch_finish(&batch->base); 180 180 } 181 181 } -
uspace/drv/bus/usb/uhci/transfer_list.c
ra312d8f r17873ac7 115 115 assert(instance); 116 116 assert(uhci_batch); 117 118 endpoint_t *ep = uhci_batch->base.ep; 119 120 /* First, wait until the endpoint is free to use */ 121 fibril_mutex_lock(&ep->guard); 122 endpoint_activate_locked(ep, &uhci_batch->base); 123 fibril_mutex_unlock(&ep->guard); 124 117 125 usb_log_debug2("Batch %p adding to queue %s.\n", 118 126 uhci_batch, instance->name); … … 189 197 uhci_transfer_batch_from_link(current); 190 198 transfer_list_remove_batch(instance, batch); 191 uhci_transfer_batch_abort(batch);199 endpoint_abort(batch->base.ep); 192 200 } 193 201 fibril_mutex_unlock(&instance->guard); -
uspace/drv/bus/usb/uhci/uhci_batch.c
ra312d8f r17873ac7 64 64 } 65 65 66 void uhci_transfer_batch_finish(uhci_transfer_batch_t *batch)67 {68 if (batch->base.dir == USB_DIRECTION_IN) {69 assert(batch->base.transfered_size <= batch->base.buffer_size);70 memcpy(batch->base.buffer, uhci_transfer_batch_data_buffer(batch), batch->base.transfered_size);71 }72 usb_transfer_batch_finish(&batch->base);73 }74 75 66 /** Allocate memory and initialize internal data structure. 76 67 * … … 113 104 } 114 105 115 const size_t setup_size = (u hci_batch->base.ep->transfer_type == USB_TRANSFER_CONTROL)106 const size_t setup_size = (usb_batch->ep->transfer_type == USB_TRANSFER_CONTROL) 116 107 ? USB_SETUP_PACKET_SIZE 117 108 : 0; … … 165 156 { 166 157 assert(uhci_batch); 158 usb_transfer_batch_t *batch = &uhci_batch->base; 167 159 168 160 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT 169 161 " checking %zu transfer(s) for completion.\n", 170 uhci_batch, USB_TRANSFER_BATCH_ARGS( uhci_batch->base),162 uhci_batch, USB_TRANSFER_BATCH_ARGS(*batch), 171 163 uhci_batch->td_count); 172 uhci_batch->base.transfered_size = 0;164 batch->transfered_size = 0; 173 165 174 166 for (size_t i = 0;i < uhci_batch->td_count; ++i) { … … 177 169 } 178 170 179 uhci_batch->base.error = td_status(&uhci_batch->tds[i]);180 if ( uhci_batch->base.error != EOK) {181 assert( uhci_batch->base.ep != NULL);171 batch->error = td_status(&uhci_batch->tds[i]); 172 if (batch->error != EOK) { 173 assert(batch->ep != NULL); 182 174 183 175 usb_log_debug("Batch %p found error TD(%zu->%p):%" … … 186 178 td_print_status(&uhci_batch->tds[i]); 187 179 188 endpoint_toggle_set( uhci_batch->base.ep,180 endpoint_toggle_set(batch->ep, 189 181 td_toggle(&uhci_batch->tds[i])); 190 182 if (i > 0) … … 193 185 } 194 186 195 uhci_batch->base.transfered_size187 batch->transfered_size 196 188 += td_act_size(&uhci_batch->tds[i]); 197 189 if (td_is_short(&uhci_batch->tds[i])) … … 199 191 } 200 192 substract_ret: 201 if (uhci_batch->base.ep->transfer_type == USB_TRANSFER_CONTROL) 202 uhci_batch->base.transfered_size -= USB_SETUP_PACKET_SIZE; 193 if (batch->ep->transfer_type == USB_TRANSFER_CONTROL) 194 batch->transfered_size -= USB_SETUP_PACKET_SIZE; 195 196 fibril_mutex_lock(&batch->ep->guard); 197 usb_transfer_batch_reset_toggle(batch); 198 endpoint_deactivate_locked(batch->ep); 199 fibril_mutex_unlock(&batch->ep->guard); 200 201 if (batch->dir == USB_DIRECTION_IN) { 202 assert(batch->transfered_size <= batch->buffer_size); 203 memcpy(batch->buffer, 204 uhci_transfer_batch_data_buffer(uhci_batch), 205 batch->transfered_size); 206 } 207 203 208 return true; 204 209 } -
uspace/drv/bus/usb/uhci/uhci_batch.h
ra312d8f r17873ac7 98 98 } 99 99 100 /** Aborts the batch.101 * Sets error to EINTR and size off transferd data to 0, before finishing the102 * batch.103 * @param uhci_batch Batch to abort.104 */105 static inline void uhci_transfer_batch_abort(uhci_transfer_batch_t *uhci_batch)106 {107 assert(uhci_batch);108 uhci_batch->base.error = EINTR;109 uhci_batch->base.transfered_size = 0;110 usb_transfer_batch_finish(&uhci_batch->base);111 }112 113 100 /** Linked list conversion wrapper. 114 101 * @param l Linked list link. -
uspace/drv/bus/usb/xhci/bus.c
ra312d8f r17873ac7 198 198 for (size_t i = 0; i < ARRAY_SIZE(xhci_dev->endpoints); ++i) { 199 199 xhci_endpoint_t *ep = xhci_dev->endpoints[i]; 200 if (!ep || !ep->base.active)200 if (!ep) 201 201 continue; 202 202 203 /* FIXME: This is racy. */ 204 if ((err = xhci_transfer_abort(&ep->active_transfer))) { 205 usb_log_warning("Failed to abort active transfer to " 206 " endpoint " XHCI_EP_FMT ": %s", XHCI_EP_ARGS(*ep), 207 str_error(err)); 208 } 203 endpoint_abort(&ep->base); 209 204 } 210 205 … … 454 449 } 455 450 456 static int reset_toggle(bus_t *bus_base, usb_target_t target, bool all)451 static int reset_toggle(bus_t *bus_base, usb_target_t target, toggle_reset_mode_t mode) 457 452 { 458 453 // TODO: Implement me! -
uspace/drv/bus/usb/xhci/endpoint.h
ra312d8f r17873ac7 68 68 /** Main transfer ring (unused if streams are enabled) */ 69 69 xhci_trb_ring_t ring; 70 71 /** There shall be only one transfer active on an endpoint. The72 * synchronization is performed using the active flag in base73 * endpoint_t */74 xhci_transfer_t active_transfer;75 70 76 71 /** Primary stream context array (or NULL if endpoint doesn't use streams). */ -
uspace/drv/bus/usb/xhci/transfers.c
ra312d8f r17873ac7 101 101 xhci_transfer_t* xhci_transfer_create(endpoint_t* ep) 102 102 { 103 xhci_endpoint_t *xhci_ep = xhci_endpoint_get(ep); 104 xhci_transfer_t *transfer = &xhci_ep->active_transfer; 105 106 /* Do not access the transfer yet, it may be still in use. */ 103 xhci_transfer_t *transfer = calloc(1, sizeof(xhci_transfer_t)); 104 if (!transfer) 105 return NULL; 107 106 108 107 usb_transfer_batch_init(&transfer->batch, ep); 109 assert(ep->active);110 111 /* Clean just our data. */112 memset(((void *) transfer) + sizeof(usb_transfer_batch_t), 0,113 sizeof(xhci_transfer_t) - sizeof(usb_transfer_batch_t));114 115 108 return transfer; 116 109 } … … 246 239 usb_log_error("Isochronous transfers are not yet implemented!"); 247 240 return ENOTSUP; 248 }249 250 int xhci_transfer_abort(xhci_transfer_t *transfer)251 {252 usb_transfer_batch_t *batch = &transfer->batch;253 batch->error = EAGAIN;254 batch->transfered_size = 0;255 usb_transfer_batch_finish(batch);256 return EOK;257 241 } 258 242 … … 277 261 } 278 262 279 xhci_transfer_t *transfer = &ep->active_transfer; 280 281 /** FIXME: This is racy. Do we care? */ 263 /* FIXME: This is racy. Do we care? */ 282 264 ep->ring.dequeue = addr; 283 265 284 usb_transfer_batch_t *batch = &transfer->batch; 266 fibril_mutex_lock(&ep->base.guard); 267 usb_transfer_batch_t *batch = ep->base.active_batch; 268 if (!batch) { 269 fibril_mutex_unlock(&ep->base.guard); 270 return ENOENT; 271 } 285 272 286 273 batch->error = (TRB_COMPLETION_CODE(*trb) == XHCI_TRBC_SUCCESS) ? EOK : ENAK; 287 274 batch->transfered_size = batch->buffer_size - TRB_TRANSFER_LENGTH(*trb); 275 usb_transfer_batch_reset_toggle(batch); 276 endpoint_deactivate_locked(&ep->base); 277 fibril_mutex_unlock(&ep->base.guard); 278 279 xhci_transfer_t *transfer = xhci_transfer_from_batch(batch); 288 280 289 281 if (batch->dir == USB_DIRECTION_IN) { … … 309 301 { 310 302 assert(hc); 303 endpoint_t *ep = batch->ep; 311 304 312 305 xhci_transfer_t *transfer = xhci_transfer_from_batch(batch); 313 xhci_endpoint_t *xhci_ep = xhci_endpoint_get(batch->ep); 314 assert(xhci_ep); 315 306 xhci_endpoint_t *xhci_ep = xhci_endpoint_get(ep); 316 307 xhci_device_t *xhci_dev = xhci_ep_to_dev(xhci_ep); 317 308 318 309 /* Offline devices don't schedule transfers other than on EP0. */ 319 if (!xhci_dev->online && xhci_ep->base.endpoint) {310 if (!xhci_dev->online && ep->endpoint > 0) { 320 311 return EAGAIN; 321 312 } … … 334 325 if (batch->buffer_size > 0) { 335 326 transfer->hc_buffer = malloc32(batch->buffer_size); 336 } 337 327 if (!transfer->hc_buffer) 328 return ENOMEM; 329 } 338 330 339 331 if (batch->dir != USB_DIRECTION_IN) { … … 342 334 } 343 335 336 fibril_mutex_lock(&ep->guard); 337 endpoint_activate_locked(ep, batch); 344 338 const int err = transfer_handlers[batch->ep->transfer_type](hc, transfer); 345 if (err) 339 340 if (err) { 341 endpoint_deactivate_locked(ep); 342 fibril_mutex_unlock(&ep->guard); 346 343 return err; 344 } 345 346 /* After the critical section, the transfer can already be finished or aborted. */ 347 transfer = NULL; batch = NULL; 348 fibril_mutex_unlock(&ep->guard); 347 349 348 350 const uint8_t slot_id = xhci_dev->slot_id; -
uspace/drv/bus/usb/xhci/transfers.h
ra312d8f r17873ac7 58 58 xhci_transfer_t* xhci_transfer_create(endpoint_t *); 59 59 int xhci_transfer_schedule(xhci_hc_t *, usb_transfer_batch_t *); 60 int xhci_transfer_abort(xhci_transfer_t *);61 60 int xhci_handle_transfer_event(xhci_hc_t *, xhci_trb_t *); 62 61 void xhci_transfer_destroy(xhci_transfer_t *); -
uspace/lib/usb/include/usb/request.h
ra312d8f r17873ac7 109 109 int assert[(sizeof(usb_device_request_setup_packet_t) == 8) ? 1: -1]; 110 110 111 /** How m uch toggles needsto be reset */111 /** How many toggles need to be reset */ 112 112 typedef enum { 113 113 RESET_NONE, -
uspace/lib/usbhost/include/usb/host/bus.h
ra312d8f r17873ac7 44 44 45 45 #include <usb/usb.h> 46 #include <usb/request.h> 46 47 47 48 #include <assert.h> … … 97 98 int (*release_address)(bus_t *, usb_address_t); 98 99 99 int (*reset_toggle)(bus_t *, usb_target_t, bool);100 int (*reset_toggle)(bus_t *, usb_target_t, toggle_reset_mode_t); 100 101 101 102 size_t (*count_bw) (endpoint_t *, size_t); -
uspace/lib/usbhost/include/usb/host/endpoint.h
ra312d8f r17873ac7 52 52 /** Host controller side endpoint structure. */ 53 53 typedef struct endpoint { 54 /** Part of linked list. */ 55 link_t link; 54 56 /** Managing bus */ 55 57 bus_t *bus; 56 58 /** Reference count. */ 57 59 atomic_t refcnt; 58 /** Part of linked list. */59 link_t link;60 60 /** USB device */ 61 61 device_t *device; … … 76 76 /** Value of the toggle bit. */ 77 77 unsigned toggle:1; 78 /** T rue if there is a batch using this scheduled for this endpoint. */79 bool active;78 /** The currently active transfer batch. Write using methods, read under guard. */ 79 usb_transfer_batch_t *active_batch; 80 80 /** Protects resources and active status changes. */ 81 81 fibril_mutex_t guard; … … 91 91 extern void endpoint_del_ref(endpoint_t *); 92 92 93 extern void endpoint_use(endpoint_t *); 94 extern void endpoint_release(endpoint_t *); 93 /* Pay atention to synchronization of batch access wrt to aborting & finishing from another fibril. */ 94 95 /* Set currently active batch. The common case is to activate in the same 96 * critical section as scheduling to HW. 97 */ 98 extern void endpoint_activate_locked(endpoint_t *, usb_transfer_batch_t *); 99 100 /* Deactivate the endpoint, allowing others to activate it again. Batch shall 101 * already have an error set. */ 102 extern void endpoint_deactivate_locked(endpoint_t *); 103 104 /* Abort the currenty active batch. */ 105 void endpoint_abort(endpoint_t *); 95 106 96 107 extern int endpoint_toggle_get(endpoint_t *); 97 extern void endpoint_toggle_set(endpoint_t *, unsigned);108 extern void endpoint_toggle_set(endpoint_t *, bool); 98 109 99 110 /** list_get_instance wrapper. -
uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h
ra312d8f r17873ac7 40 40 #include <usb/request.h> 41 41 42 #include <atomic.h> 42 43 #include <stddef.h> 44 #include <errno.h> 43 45 #include <stdint.h> 44 46 #include <usbhc_iface.h> … … 86 88 /** Size of memory pointed to by buffer member */ 87 89 size_t buffer_size; 88 89 90 /** Actually used portion of the buffer */ 90 91 size_t transfered_size; 92 91 93 /** Indicates success/failure of the communication */ 92 94 int error; … … 106 108 (batch).buffer_size, (batch).ep->max_packet_size 107 109 110 /** Wrapper for bus operation. */ 111 usb_transfer_batch_t *usb_transfer_batch_create(endpoint_t *); 112 113 /** Batch initializer. */ 108 114 void usb_transfer_batch_init(usb_transfer_batch_t *, endpoint_t *); 115 116 /** Call after status is known, but before releasing endpoint */ 117 int usb_transfer_batch_reset_toggle(usb_transfer_batch_t *); 118 119 /** Batch finalization. */ 120 void usb_transfer_batch_abort(usb_transfer_batch_t *); 109 121 void usb_transfer_batch_finish(usb_transfer_batch_t *); 110 122 111 usb_transfer_batch_t *usb_transfer_batch_create(endpoint_t *); 123 /** To be called from outside only when the transfer is not going to be finished 124 * (i.o.w. until successfuly scheduling) 125 */ 112 126 void usb_transfer_batch_destroy(usb_transfer_batch_t *); 113 127 -
uspace/lib/usbhost/src/endpoint.c
ra312d8f r17873ac7 36 36 37 37 #include <usb/host/endpoint.h> 38 #include <usb/host/usb_transfer_batch.h> 38 39 #include <usb/host/bus.h> 39 40 … … 68 69 } 69 70 else { 70 assert( !ep->active);71 assert(ep->active_batch == NULL); 71 72 72 73 /* Assume mostly the eps will be allocated by malloc. */ … … 79 80 * @param ep endpoint_t structure. 80 81 */ 81 void endpoint_ use(endpoint_t *ep)82 void endpoint_activate_locked(endpoint_t *ep, usb_transfer_batch_t *batch) 82 83 { 83 84 assert(ep); 84 /* Add reference for active endpoint. */ 85 endpoint_add_ref(ep); 86 fibril_mutex_lock(&ep->guard); 87 while (ep->active) 85 assert(batch); 86 assert(batch->ep == ep); 87 assert(fibril_mutex_is_locked(&ep->guard)); 88 89 while (ep->active_batch != NULL) 88 90 fibril_condvar_wait(&ep->avail, &ep->guard); 89 ep->active = true; 90 fibril_mutex_unlock(&ep->guard); 91 ep->active_batch = batch; 91 92 } 92 93 … … 94 95 * @param ep endpoint_t structure. 95 96 */ 96 void endpoint_ release(endpoint_t *ep)97 void endpoint_deactivate_locked(endpoint_t *ep) 97 98 { 98 99 assert(ep); 100 assert(fibril_mutex_is_locked(&ep->guard)); 101 102 if (ep->active_batch && ep->active_batch->error == EOK) 103 usb_transfer_batch_reset_toggle(ep->active_batch); 104 105 ep->active_batch = NULL; 106 fibril_condvar_signal(&ep->avail); 107 } 108 109 /** Abort an active batch on endpoint, if any. 110 * 111 * @param[in] ep endpoint_t structure. 112 */ 113 void endpoint_abort(endpoint_t *ep) 114 { 115 assert(ep); 116 99 117 fibril_mutex_lock(&ep->guard); 100 ep->active = false; 118 usb_transfer_batch_t *batch = ep->active_batch; 119 endpoint_deactivate_locked(ep); 101 120 fibril_mutex_unlock(&ep->guard); 102 fibril_condvar_signal(&ep->avail); 103 /* Drop reference for active endpoint. */104 endpoint_del_ref(ep);121 122 if (batch) 123 usb_transfer_batch_abort(batch); 105 124 } 106 125 … … 112 131 { 113 132 assert(ep); 114 fibril_mutex_lock(&ep->guard); 115 const int ret =ep->bus->ops.endpoint_get_toggle133 134 return ep->bus->ops.endpoint_get_toggle 116 135 ? ep->bus->ops.endpoint_get_toggle(ep) 117 136 : ep->toggle; 118 fibril_mutex_unlock(&ep->guard);119 return ret;120 137 } 121 138 … … 124 141 * @param ep endpoint_t structure. 125 142 */ 126 void endpoint_toggle_set(endpoint_t *ep, unsignedtoggle)143 void endpoint_toggle_set(endpoint_t *ep, bool toggle) 127 144 { 128 145 assert(ep); 129 assert(toggle == 0 || toggle == 1); 130 fibril_mutex_lock(&ep->guard); 146 131 147 if (ep->bus->ops.endpoint_set_toggle) { 132 148 ep->bus->ops.endpoint_set_toggle(ep, toggle); … … 135 151 ep->toggle = toggle; 136 152 } 137 fibril_mutex_unlock(&ep->guard);138 153 } 139 154 -
uspace/lib/usbhost/src/usb2_bus.c
ra312d8f r17873ac7 367 367 } 368 368 369 static int usb2_bus_reset_toggle(bus_t *bus_base, usb_target_t target, bool all)369 static int usb2_bus_reset_toggle(bus_t *bus_base, usb_target_t target, toggle_reset_mode_t mode) 370 370 { 371 371 usb2_bus_t *bus = bus_to_usb2_bus(bus_base); … … 374 374 return EINVAL; 375 375 376 if (mode == RESET_NONE) 377 return EOK; 378 376 379 int ret = ENOENT; 377 380 … … 379 382 assert(ep->device->address == target.address); 380 383 381 if ( all|| ep->endpoint == target.endpoint) {384 if (mode == RESET_ALL || ep->endpoint == target.endpoint) { 382 385 endpoint_toggle_set(ep, 0); 383 386 ret = EOK; -
uspace/lib/usbhost/src/usb_transfer_batch.c
ra312d8f r17873ac7 63 63 void usb_transfer_batch_init(usb_transfer_batch_t *batch, endpoint_t *ep) 64 64 { 65 endpoint_use(ep);66 67 65 memset(batch, 0, sizeof(*batch)); 68 66 batch->ep = ep; 69 67 } 70 68 71 /** Call the handler of the batch.69 /** Resolve resetting toggle. 72 70 * 73 71 * @param[in] batch Batch structure to use. 74 72 */ 75 static int batch_complete(usb_transfer_batch_t *batch)73 int usb_transfer_batch_reset_toggle(usb_transfer_batch_t *batch) 76 74 { 77 75 assert(batch); 78 76 79 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " completed.\n",80 batch, USB_TRANSFER_BATCH_ARGS(*batch));77 if (batch->error != EOK || batch->toggle_reset_mode == RESET_NONE) 78 return EOK; 81 79 82 if (batch->error == EOK && batch->toggle_reset_mode != RESET_NONE) { 83 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " resets %s", 84 batch, USB_TRANSFER_BATCH_ARGS(*batch), 85 batch->toggle_reset_mode == RESET_ALL ? "all EPs toggle" : "EP toggle"); 86 bus_reset_toggle(batch->ep->bus, 87 batch->target, batch->toggle_reset_mode == RESET_ALL); 88 } 80 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " resets %s", 81 batch, USB_TRANSFER_BATCH_ARGS(*batch), 82 batch->toggle_reset_mode == RESET_ALL ? "all EPs toggle" : "EP toggle"); 89 83 90 return batch->on_complete 91 ? batch->on_complete(batch) 92 : EOK; 84 return bus_reset_toggle(batch->ep->bus, batch->target, batch->toggle_reset_mode); 93 85 } 94 86 … … 114 106 free(batch); 115 107 } 116 117 endpoint_release(batch->ep);118 108 } 119 109 … … 126 116 void usb_transfer_batch_finish(usb_transfer_batch_t *batch) 127 117 { 128 const int err = batch_complete(batch); 129 if (err) 130 usb_log_warning("batch %p failed to complete: %s", batch, str_error(err)); 118 assert(batch); 119 assert(batch->ep); 120 121 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " finishing.\n", 122 batch, USB_TRANSFER_BATCH_ARGS(*batch)); 123 124 if (batch->on_complete) { 125 const int err = batch->on_complete(batch); 126 if (err) 127 usb_log_warning("batch %p failed to complete: %s", 128 batch, str_error(err)); 129 } 131 130 132 131 usb_transfer_batch_destroy(batch); 132 } 133 134 /** Finish a transfer batch as an aborted one. 135 * 136 * @param[in] batch Batch structure to use. 137 */ 138 void usb_transfer_batch_abort(usb_transfer_batch_t *batch) 139 { 140 assert(batch); 141 assert(batch->ep); 142 143 batch->error = EAGAIN; 144 usb_transfer_batch_finish(batch); 133 145 } 134 146
Note:
See TracChangeset
for help on using the changeset viewer.