Changes in uspace/drv/bus/usb/usbhub/port.c [c4f7bf6:0918382f] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/usbhub/port.c
rc4f7bf6 r0918382f 41 41 42 42 #include <usb/debug.h> 43 #include <usb/dev/hub.h>44 43 45 44 #include "port.h" … … 58 57 usb_port_status_t status); 59 58 static int get_port_status(usb_hub_port_t *port, usb_port_status_t *status); 60 static int enable_port_callback(void *arg);61 59 static int add_device_phase1_worker_fibril(void *arg); 62 60 static int create_add_device_fibril(usb_hub_port_t *port, usb_hub_dev_t *hub, … … 66 64 { 67 65 assert(port); 68 if (port-> attached_device.fun)66 if (port->device_attached) 69 67 return usb_hub_port_device_gone(port, hub); 70 68 return EOK; … … 141 139 assert(port); 142 140 assert(hub); 143 usb_log_debug("Interrupt at port % zu\n", port->port_number);141 usb_log_debug("Interrupt at port %u\n", port->port_number); 144 142 145 143 usb_port_status_t status = 0; 146 144 const int opResult = get_port_status(port, &status); 147 145 if (opResult != EOK) { 148 usb_log_error("Failed to get port % zu status: %s.\n",146 usb_log_error("Failed to get port %u status: %s.\n", 149 147 port->port_number, str_error(opResult)); 150 148 return; … … 155 153 const bool connected = 156 154 (status & USB_HUB_PORT_STATUS_CONNECTION) != 0; 157 usb_log_debug("Connection change on port % zu: device %s.\n",155 usb_log_debug("Connection change on port %u: device %s.\n", 158 156 port->port_number, connected ? "attached" : "removed"); 159 157 … … 171 169 if (opResult != EOK) { 172 170 usb_log_error( 173 "Cannot handle change on port % zu: %s.\n",171 "Cannot handle change on port %u: %s.\n", 174 172 port->port_number, str_error(opResult)); 175 173 } … … 185 183 /* Enable change, ports are automatically disabled on errors. */ 186 184 if (status & USB_HUB_PORT_C_STATUS_ENABLED) { 187 usb_log_info("Port % zu, disabled because of errors.\n",185 usb_log_info("Port %u, disabled because of errors.\n", 188 186 port->port_number); 189 187 usb_hub_port_device_gone(port, hub); … … 192 190 if (rc != EOK) { 193 191 usb_log_error( 194 "Failed to clear port % zu enable change feature: "192 "Failed to clear port %u enable change feature: " 195 193 "%s.\n", port->port_number, str_error(rc)); 196 194 } … … 200 198 /* Suspend change */ 201 199 if (status & USB_HUB_PORT_C_STATUS_SUSPEND) { 202 usb_log_error("Port % zu went to suspend state, this should"200 usb_log_error("Port %u went to suspend state, this should" 203 201 "NOT happen as we do not support suspend state!", 204 202 port->port_number); … … 207 205 if (rc != EOK) { 208 206 usb_log_error( 209 "Failed to clear port % zu suspend change feature: "207 "Failed to clear port %u suspend change feature: " 210 208 "%s.\n", port->port_number, str_error(rc)); 211 209 } … … 223 221 if (rc != EOK) { 224 222 usb_log_error( 225 "Failed to clear port % zu OC change feature: %s.\n",223 "Failed to clear port %u OC change feature: %s.\n", 226 224 port->port_number, str_error(rc)); 227 225 } … … 231 229 if (rc != EOK) { 232 230 usb_log_error( 233 "Failed to set port % zu power after OC:"231 "Failed to set port %u power after OC:" 234 232 " %s.\n", port->port_number, str_error(rc)); 235 233 } … … 242 240 } 243 241 244 usb_log_debug("Port % zu status 0x%08" PRIx32 "\n",242 usb_log_debug("Port %u status %#08" PRIx32 "\n", 245 243 port->port_number, status); 246 244 } … … 259 257 assert(port); 260 258 assert(hub); 261 if (port->attached_device.address < 0) { 262 usb_log_warning( 263 "Device on port %zu removed before being registered.\n", 264 port->port_number); 265 266 /* 267 * Device was removed before port reset completed. 268 * We will announce a failed port reset to unblock the 269 * port reset callback from new device wrapper. 270 */ 271 usb_hub_port_reset_fail(port); 272 return EOK; 273 } 274 275 fibril_mutex_lock(&port->mutex); 276 assert(port->attached_device.fun); 277 usb_log_debug("Removing device on port %zu.\n", port->port_number); 278 int ret = ddf_fun_unbind(port->attached_device.fun); 279 if (ret != EOK) { 280 usb_log_error("Failed to unbind child function on port" 281 " %zu: %s.\n", port->port_number, str_error(ret)); 282 fibril_mutex_unlock(&port->mutex); 283 return ret; 284 } 285 286 ddf_fun_destroy(port->attached_device.fun); 287 port->attached_device.fun = NULL; 288 289 ret = usb_hub_unregister_device(&hub->usb_device->hc_conn, 290 &port->attached_device); 291 if (ret != EOK) { 292 usb_log_warning("Failed to unregister address of the " 293 "removed device: %s.\n", str_error(ret)); 294 } 295 296 port->attached_device.address = -1; 297 fibril_mutex_unlock(&port->mutex); 298 usb_log_info("Removed device on port %zu.\n", port->port_number); 299 return EOK; 259 async_exch_t *exch = usb_device_bus_exchange_begin(hub->usb_device); 260 if (!exch) 261 return ENOMEM; 262 const int rc = usb_device_remove(exch, port->port_number); 263 usb_device_bus_exchange_end(exch); 264 if (rc == EOK) 265 port->device_attached = false; 266 return rc; 267 300 268 } 301 269 … … 318 286 319 287 if (port->reset_okay) { 320 usb_log_debug("Port % zu reset complete.\n", port->port_number);288 usb_log_debug("Port %u reset complete.\n", port->port_number); 321 289 } else { 322 290 usb_log_warning( 323 "Port % zu reset complete but port not enabled.\n",291 "Port %u reset complete but port not enabled.\n", 324 292 port->port_number); 325 293 } … … 331 299 if (rc != EOK) { 332 300 usb_log_error( 333 "Failed to clear port % zu reset change feature: %s.\n",301 "Failed to clear port %u reset change feature: %s.\n", 334 302 port->port_number, str_error(rc)); 335 303 } … … 376 344 } 377 345 378 /** Callback for enabling a specific port. 379 * 380 * We wait on a CV until port is reseted. 381 * That is announced via change on interrupt pipe. 382 * 383 * @param port_no Port number (starting at 1). 384 * @param arg Custom argument, points to @c usb_hub_dev_t. 385 * @return Error code. 386 */ 387 static int enable_port_callback(void *arg) 388 { 389 usb_hub_port_t *port = arg; 390 assert(port); 391 const int rc = 392 usb_hub_port_set_feature(port, USB_HUB_FEATURE_PORT_RESET); 393 if (rc != EOK) { 394 usb_log_warning("Port reset failed: %s.\n", str_error(rc)); 395 return rc; 396 } 397 398 /* 399 * Wait until reset completes. 400 */ 401 fibril_mutex_lock(&port->mutex); 402 while (!port->reset_completed) { 403 fibril_condvar_wait(&port->reset_cv, &port->mutex); 404 } 405 fibril_mutex_unlock(&port->mutex); 406 407 return port->reset_okay ? EOK : ESTALL; 346 static int port_enable(usb_hub_port_t *port, bool enable) 347 { 348 if (enable) { 349 const int rc = 350 usb_hub_port_set_feature(port, USB_HUB_FEATURE_PORT_RESET); 351 if (rc != EOK) { 352 usb_log_error("Port reset failed: %s.\n", 353 str_error(rc)); 354 } else { 355 /* Wait until reset completes. */ 356 fibril_mutex_lock(&port->mutex); 357 while (!port->reset_completed) { 358 fibril_condvar_wait(&port->reset_cv, 359 &port->mutex); 360 } 361 fibril_mutex_unlock(&port->mutex); 362 } 363 return port->reset_okay ? EOK : ESTALL; 364 } else { 365 return usb_hub_port_clear_feature(port, 366 USB_HUB_FEATURE_PORT_ENABLE); 367 } 408 368 } 409 369 … … 418 378 int add_device_phase1_worker_fibril(void *arg) 419 379 { 420 struct add_device_phase1 *data = arg; 421 assert(data); 422 423 usb_address_t new_address; 424 ddf_fun_t *child_fun; 425 426 const int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev, 427 &data->hub->usb_device->hc_conn, data->speed, enable_port_callback, 428 data->port, &new_address, NULL, NULL, &child_fun); 429 430 if (rc == EOK) { 431 fibril_mutex_lock(&data->port->mutex); 432 data->port->attached_device.fun = child_fun; 433 data->port->attached_device.address = new_address; 434 fibril_mutex_unlock(&data->port->mutex); 435 436 usb_log_info("Detected new device on `%s' (port %zu), " 437 "address %d (handle %" PRIun ").\n", 438 ddf_dev_get_name(data->hub->usb_device->ddf_dev), 439 data->port->port_number, new_address, 440 ddf_fun_get_handle(child_fun)); 380 struct add_device_phase1 *params = arg; 381 assert(params); 382 383 int ret = EOK; 384 usb_hub_dev_t *hub = params->hub; 385 usb_hub_port_t *port = params->port; 386 const usb_speed_t speed = params->speed; 387 free(arg); 388 389 async_exch_t *exch = usb_device_bus_exchange_begin(hub->usb_device); 390 if (!exch) { 391 usb_log_error("Failed to begin bus exchange\n"); 392 ret = ENOMEM; 393 goto out; 394 } 395 396 /* Reserve default address */ 397 while ((ret = usb_reserve_default_address(exch, speed)) == ENOENT) { 398 async_usleep(1000000); 399 } 400 if (ret != EOK) { 401 usb_log_error("Failed to reserve default address: %s\n", 402 str_error(ret)); 403 goto out; 404 } 405 406 /* Reset port */ 407 port_enable(port, true); 408 if (!port->reset_completed || !port->reset_okay) { 409 usb_log_error("Failed to reset port %u\n", port->port_number); 410 if (usb_release_default_address(exch) != EOK) 411 usb_log_warning("Failed to release default address\n"); 412 ret = EIO; 413 goto out; 414 } 415 416 ret = usb_device_enumerate(exch, port->port_number); 417 if (ret != EOK) { 418 usb_log_error("Failed to enumerate device on port %u\n", 419 port->port_number); 420 if (port_enable(port, false) != EOK) { 421 usb_log_warning("Failed to disable port %u, NOT " 422 "releasing default address.\n", port->port_number); 423 } else { 424 if (usb_release_default_address(exch) != EOK) 425 usb_log_warning( 426 "Failed to release default address\n"); 427 } 441 428 } else { 442 usb_log_error("Failed registering device on port %zu: %s.\n",443 data->port->port_number, str_error(rc));444 }445 446 447 fibril_mutex_lock(&data->hub->pending_ops_mutex);448 assert(data->hub->pending_ops_count > 0); 449 --data->hub->pending_ops_count;450 fibril_condvar_signal(&data->hub->pending_ops_cv);451 fibril_mutex_unlock(&data->hub->pending_ops_mutex);452 453 f ree(arg);454 455 return r c;429 port->device_attached = true; 430 if (usb_release_default_address(exch) != EOK) 431 usb_log_warning("Failed to release default address\n"); 432 } 433 out: 434 usb_device_bus_exchange_end(exch); 435 436 fibril_mutex_lock(&hub->pending_ops_mutex); 437 assert(hub->pending_ops_count > 0); 438 --hub->pending_ops_count; 439 fibril_condvar_signal(&hub->pending_ops_cv); 440 fibril_mutex_unlock(&hub->pending_ops_mutex); 441 442 return ret; 456 443 } 457 444
Note:
See TracChangeset
for help on using the changeset viewer.