Changeset 49e62998 in mainline
- Timestamp:
- 2018-01-11T23:06:57Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 50be3c6
- Parents:
- f3baab1
- git-author:
- Ondřej Hlavatý <aearsis@…> (2018-01-11 23:01:08)
- git-committer:
- Ondřej Hlavatý <aearsis@…> (2018-01-11 23:06:57)
- Location:
- uspace/drv/bus/usb/xhci
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/xhci/rh.c
rf3baab1 r49e62998 81 81 rh->device.tier = 0; 82 82 83 fibril_mutex_initialize(&rh->event_guard); 84 fibril_condvar_initialize(&rh->event_ready); 85 fibril_condvar_initialize(&rh->event_handled); 86 83 87 return EOK; 84 88 } … … 92 96 free(rh->devices_by_port); 93 97 return EOK; 98 } 99 100 static int rh_event_wait_timeout(xhci_rh_t *rh, suseconds_t timeout) 101 { 102 assert(fibril_mutex_is_locked(&rh->event_guard)); 103 104 ++rh->event_readers_waiting; 105 const int r = fibril_condvar_wait_timeout(&rh->event_ready, &rh->event_guard, timeout); 106 --rh->event_readers_waiting; 107 if (--rh->event_readers_to_go == 0) 108 fibril_condvar_broadcast(&rh->event_handled); 109 return r; 110 } 111 112 static void rh_event_run_handlers(xhci_rh_t *rh) 113 { 114 fibril_mutex_lock(&rh->event_guard); 115 assert(rh->event_readers_to_go == 0); 116 117 rh->event_readers_to_go = rh->event_readers_waiting; 118 fibril_condvar_broadcast(&rh->event_ready); 119 while (rh->event_readers_to_go) 120 fibril_condvar_wait(&rh->event_handled, &rh->event_guard); 121 fibril_mutex_unlock(&rh->event_guard); 94 122 } 95 123 … … 147 175 } 148 176 177 178 static int rh_port_reset_sync(xhci_rh_t *rh, uint8_t port_id) 179 { 180 int r; 181 xhci_port_regs_t *regs = &rh->hc->op_regs->portrs[port_id - 1]; 182 183 fibril_mutex_lock(&rh->event_guard); 184 XHCI_REG_SET(regs, XHCI_PORT_PR, 1); 185 186 while (true) { 187 r = rh_event_wait_timeout(rh, 0); 188 if (r != EOK) 189 break; 190 if (rh->event.port_id == port_id 191 && rh->event.events & XHCI_REG_MASK(XHCI_PORT_PRC)) 192 break; 193 } 194 fibril_mutex_unlock(&rh->event_guard); 195 196 return r; 197 } 198 149 199 /** 150 200 * Handle a device connection. USB 3+ devices are set up directly, USB 2 and … … 177 227 else { 178 228 usb_log_debug("USB 2 device attached, issuing reset."); 179 xhci_rh_reset_port(rh, port_id); 229 const int err = rh_port_reset_sync(rh, port_id); 230 if (err) 231 return err; 232 233 rh_setup_device(rh, port_id); 180 234 return EOK; 181 235 } … … 229 283 } 230 284 285 typedef int (*rh_event_handler_t)(xhci_rh_t *, uint8_t); 286 287 typedef struct rh_event_args { 288 xhci_rh_t *rh; 289 uint8_t port_id; 290 rh_event_handler_t handler; 291 } rh_event_args_t; 292 293 static int rh_event_handler_fibril(void *arg) { 294 rh_event_args_t *rh_args = arg; 295 xhci_rh_t *rh = rh_args->rh; 296 uint8_t port_id = rh_args->port_id; 297 rh_event_handler_t handler = rh_args->handler; 298 299 free(rh_args); 300 301 return handler(rh, port_id); 302 } 303 304 static fid_t handle_in_fibril(xhci_rh_t *rh, uint8_t port_id, rh_event_handler_t handler) 305 { 306 rh_event_args_t *args = malloc(sizeof(*args)); 307 *args = (rh_event_args_t) { 308 .rh = rh, 309 .port_id = port_id, 310 .handler = handler, 311 }; 312 313 const fid_t fid = fibril_create(rh_event_handler_fibril, args); 314 fibril_add_ready(fid); 315 return fid; 316 } 317 231 318 /** 232 319 * Handle all changes on all ports. … … 248 335 bool connected = XHCI_REG_RD(regs, XHCI_PORT_CCS); 249 336 if (connected) { 250 handle_ connected_device(rh, i);337 handle_in_fibril(rh, i, handle_connected_device); 251 338 } else { 252 handle_ disconnected_device(rh, i);339 handle_in_fibril(rh, i, handle_disconnected_device); 253 340 } 254 341 } 255 342 256 if (events & XHCI_REG_MASK(XHCI_PORT_PEC)) { 257 usb_log_info("Port enabled changed on port %u.", i); 258 events &= ~XHCI_REG_MASK(XHCI_PORT_PEC); 259 } 260 261 if (events & XHCI_REG_MASK(XHCI_PORT_WRC)) { 262 usb_log_info("Warm port reset on port %u completed.", i); 263 events &= ~XHCI_REG_MASK(XHCI_PORT_WRC); 264 } 265 266 if (events & XHCI_REG_MASK(XHCI_PORT_OCC)) { 267 usb_log_info("Over-current change on port %u.", i); 268 events &= ~XHCI_REG_MASK(XHCI_PORT_OCC); 269 } 270 271 if (events & XHCI_REG_MASK(XHCI_PORT_PRC)) { 272 usb_log_info("Port reset on port %u completed.", i); 273 events &= ~XHCI_REG_MASK(XHCI_PORT_PRC); 274 275 const xhci_port_speed_t *speed = xhci_rh_get_port_speed(rh, i); 276 if (speed->major != 3) { 277 /* FIXME: We probably don't want to do this 278 * every time USB2 port is reset. This is a 279 * temporary workaround. */ 280 rh_setup_device(rh, i); 281 } 282 } 283 284 if (events & XHCI_REG_MASK(XHCI_PORT_PLC)) { 285 usb_log_info("Port link state changed on port %u.", i); 286 events &= ~XHCI_REG_MASK(XHCI_PORT_PLC); 287 } 288 289 if (events & XHCI_REG_MASK(XHCI_PORT_CEC)) { 290 usb_log_info("Port %u failed to configure link.", i); 291 events &= ~XHCI_REG_MASK(XHCI_PORT_CEC); 292 } 293 294 if (events) { 295 usb_log_warning("Port change (0x%08x) ignored on port %u.", events, i); 343 if (events != 0) { 344 rh->event.port_id = i; 345 rh->event.events = events; 346 rh_event_run_handlers(rh); 296 347 } 297 348 } … … 333 384 { 334 385 usb_log_debug2("Resetting port %u.", port); 335 xhci_port_regs_t *regs = &rh->hc->op_regs->portrs[port-1];336 XHCI_REG_SET(regs, XHCI_PORT_PR, 1);337 386 338 387 return EOK; -
uspace/drv/bus/usb/xhci/rh.h
rf3baab1 r49e62998 75 75 /* Device pointers connected to RH ports or NULL. (size is `max_ports`) */ 76 76 xhci_device_t **devices_by_port; 77 78 /* Roothub events. */ 79 fibril_mutex_t event_guard; 80 fibril_condvar_t event_ready, event_handled; 81 unsigned event_readers_waiting, event_readers_to_go; 82 struct { 83 uint8_t port_id; 84 uint32_t events; 85 } event; 77 86 } xhci_rh_t; 78 87 … … 80 89 int xhci_rh_fini(xhci_rh_t *); 81 90 const xhci_port_speed_t *xhci_rh_get_port_speed(xhci_rh_t *, uint8_t); 82 int xhci_rh_reset_port(xhci_rh_t *, uint8_t);83 91 84 92 int xhci_rh_handle_port_status_change_event(xhci_hc_t *, xhci_trb_t *);
Note:
See TracChangeset
for help on using the changeset viewer.