Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 96323d2 in mainline


Ignore:
Timestamp:
2015-07-01T02:56:08Z (6 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master
Children:
b303275
Parents:
c4ba645d
Message:

usbhub: Handle device disappearing during reset

Rework reset status handling (should probably include all of port status handling).
Improve logging.

Location:
uspace/drv/bus/usb/usbhub
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/usbhub/main.c

    rc4ba645d r96323d2  
    3636#include <async.h>
    3737#include <stdio.h>
     38#include <io/logctl.h>
    3839
    3940#include <usb/dev/driver.h>
     
    6768        printf(NAME ": HelenOS USB hub driver.\n");
    6869        log_init(NAME);
    69 
     70        logctl_set_log_level(NAME, LVL_DEBUG);
    7071        return usb_driver_main(&usb_hub_driver);
    7172}
  • uspace/drv/bus/usb/usbhub/port.c

    rc4ba645d r96323d2  
    122122        assert(port);
    123123        fibril_mutex_lock(&port->mutex);
    124         port->reset_completed = true;
    125         port->reset_okay = false;
     124        if (port->reset_status == IN_RESET)
     125                port->reset_status = RESET_FAIL;
    126126        fibril_condvar_broadcast(&port->reset_cv);
    127127        fibril_mutex_unlock(&port->mutex);
     
    139139        assert(port);
    140140        assert(hub);
    141         usb_log_debug("Interrupt at port %u\n", port->port_number);
     141        usb_log_debug2("(%p-%u): Interrupt.\n", hub, port->port_number);
    142142
    143143        usb_port_status_t status = 0;
    144144        const int opResult = get_port_status(port, &status);
    145145        if (opResult != EOK) {
    146                 usb_log_error("Failed to get port %u status: %s.\n",
     146                usb_log_error("(%p-%u): Failed to get port status: %s.\n", hub,
    147147                    port->port_number, str_error(opResult));
    148148                return;
     
    153153                const bool connected =
    154154                    (status & USB_HUB_PORT_STATUS_CONNECTION) != 0;
    155                 usb_log_debug("Connection change on port %u: device %s.\n",
     155                usb_log_debug("(%p-%u): Connection change: device %s.\n", hub,
    156156                    port->port_number, connected ? "attached" : "removed");
    157157
     
    160160                    USB_HUB_FEATURE_C_PORT_CONNECTION);
    161161                if (opResult != EOK) {
    162                         usb_log_warning("Failed to clear port-change-connection"
    163                             " flag: %s.\n", str_error(opResult));
     162                        usb_log_warning("(%p-%u): Failed to clear "
     163                            "port-change-connection flag: %s.\n", hub,
     164                            port->port_number, str_error(opResult));
    164165                }
    165166
     
    168169                            usb_port_speed(status));
    169170                        if (opResult != EOK) {
    170                                 usb_log_error(
    171                                     "Cannot handle change on port %u: %s.\n",
    172                                     port->port_number, str_error(opResult));
     171                                usb_log_error("(%p-%u): Cannot handle change on"
     172                                   " port: %s.\n", hub, port->port_number,
     173                                   str_error(opResult));
    173174                        }
    174175                } else {
     176                        /* Handle the case we were in reset */
     177                        usb_hub_port_reset_fail(port);
    175178                        /* If enabled change was reported leave the removal
    176179                         * to that handler, it shall ACK the change too. */
     
    183186        /* Enable change, ports are automatically disabled on errors. */
    184187        if (status & USB_HUB_PORT_C_STATUS_ENABLED) {
    185                 usb_log_info("Port %u, disabled because of errors.\n",
     188                //TODO: maybe HS reset failed?
     189                usb_log_info("(%p-%u): Port disabled because of errors.\n", hub,
    186190                   port->port_number);
    187191                usb_hub_port_device_gone(port, hub);
     
    189193                        USB_HUB_FEATURE_C_PORT_ENABLE);
    190194                if (rc != EOK) {
    191                         usb_log_error(
    192                             "Failed to clear port %u enable change feature: "
    193                             "%s.\n", port->port_number, str_error(rc));
     195                        usb_log_error("(%p-%u): Failed to clear port enable "
     196                            "change feature: %s.", hub, port->port_number,
     197                            str_error(rc));
    194198                }
    195199
     
    198202        /* Suspend change */
    199203        if (status & USB_HUB_PORT_C_STATUS_SUSPEND) {
    200                 usb_log_error("Port %u went to suspend state, this should"
    201                     "NOT happen as we do not support suspend state!",
     204                usb_log_error("(%p-%u): Port went to suspend state, this should"
     205                    " NOT happen as we do not support suspend state!", hub,
    202206                    port->port_number);
    203207                const int rc = usb_hub_port_clear_feature(port,
    204208                        USB_HUB_FEATURE_C_PORT_SUSPEND);
    205209                if (rc != EOK) {
    206                         usb_log_error(
    207                             "Failed to clear port %u suspend change feature: "
    208                             "%s.\n", port->port_number, str_error(rc));
     210                        usb_log_error("(%p-%u): Failed to clear port suspend "
     211                            "change feature: %s.", hub, port->port_number,
     212                            str_error(rc));
    209213                }
    210214        }
     
    212216        /* Over current */
    213217        if (status & USB_HUB_PORT_C_STATUS_OC) {
     218                usb_log_debug("(%p-%u): Port OC reported!.", hub,
     219                    port->port_number);
    214220                /* According to the USB specs:
    215221                 * 11.13.5 Over-current Reporting and Recovery
     
    220226                    USB_HUB_FEATURE_C_PORT_OVER_CURRENT);
    221227                if (rc != EOK) {
    222                         usb_log_error(
    223                             "Failed to clear port %u OC change feature: %s.\n",
    224                             port->port_number, str_error(rc));
     228                        usb_log_error("(%p-%u): Failed to clear port OC change "
     229                            "feature: %s.\n", hub, port->port_number,
     230                            str_error(rc));
    225231                }
    226232                if (!(status & ~USB_HUB_PORT_STATUS_OC)) {
     
    228234                            port, USB_HUB_FEATURE_PORT_POWER);
    229235                        if (rc != EOK) {
    230                                 usb_log_error(
    231                                     "Failed to set port %u power after OC:"
    232                                     " %s.\n", port->port_number, str_error(rc));
     236                                usb_log_error("(%p-%u): Failed to set port "
     237                                    "power after OC: %s.", hub,
     238                                    port->port_number, str_error(rc));
    233239                        }
    234240                }
     
    240246        }
    241247
    242         usb_log_debug("Port %u status %#08" PRIx32 "\n",
     248        usb_log_debug2("(%p-%u): Port status %#08" PRIx32, hub,
    243249            port->port_number, status);
    244250}
     
    281287        assert(port);
    282288        fibril_mutex_lock(&port->mutex);
     289        const bool enabled = (status & USB_HUB_PORT_STATUS_ENABLED) != 0;
    283290        /* Finalize device adding. */
    284         port->reset_completed = true;
    285         port->reset_okay = (status & USB_HUB_PORT_STATUS_ENABLED) != 0;
    286 
    287         if (port->reset_okay) {
     291
     292        if (enabled) {
     293                port->reset_status = RESET_OK;
    288294                usb_log_debug("Port %u reset complete.\n", port->port_number);
    289295        } else {
    290                 usb_log_warning(
    291                     "Port %u reset complete but port not enabled.\n",
     296                port->reset_status = RESET_FAIL;
     297                usb_log_warning("Port %u reset complete but port not enabled.",
    292298                    port->port_number);
    293299        }
     
    298304        int rc = usb_hub_port_clear_feature(port, USB_HUB_FEATURE_C_PORT_RESET);
    299305        if (rc != EOK) {
    300                 usb_log_error(
    301                     "Failed to clear port %u reset change feature: %s.\n",
     306                usb_log_error("Failed to clear port %u reset change: %s.",
    302307                    port->port_number, str_error(rc));
    303308        }
     
    352357                        usb_log_error("Port reset failed: %s.\n",
    353358                            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;
     359                        return rc;
     360                }
     361                /* Wait until reset completes. */
     362                fibril_mutex_lock(&port->mutex);
     363                port->reset_status = IN_RESET;
     364                while (port->reset_status == IN_RESET) {
     365                        fibril_condvar_wait(&port->reset_cv,
     366                            &port->mutex);
     367                }
     368                fibril_mutex_unlock(&port->mutex);
     369                return port->reset_status == RESET_OK ? EOK : ESTALL;
    364370        } else {
    365371                return usb_hub_port_clear_feature(port,
     
    387393        free(arg);
    388394
     395        usb_log_debug("(%p-%u): New device detected.", hub,
     396            port->port_number);
     397
    389398        async_exch_t *exch = usb_device_bus_exchange_begin(hub->usb_device);
    390399        if (!exch) {
    391                 usb_log_error("Failed to begin bus exchange\n");
     400                usb_log_error("(%p-%u): Failed to begin bus exchange.", hub,
     401                    port->port_number);
    392402                ret = ENOMEM;
    393403                goto out;
     
    399409        }
    400410        if (ret != EOK) {
    401                 usb_log_error("Failed to reserve default address: %s\n",
    402                     str_error(ret));
     411                usb_log_error("(%p-%u): Failed to reserve default address: %s",
     412                    hub, port->port_number, str_error(ret));
    403413                goto out;
    404414        }
    405415
     416        usb_log_debug("(%p-%u): Got default address reseting port.", hub,
     417            port->port_number);
    406418        /* Reset port */
    407         port_enable(port, true);
    408         if (!port->reset_completed || !port->reset_okay) {
     419        ret = port_enable(port, true);
     420        if (ret != EOK) {
    409421                usb_log_error("Failed to reset port %u\n", port->port_number);
    410422                if (usb_release_default_address(exch) != EOK)
     
    413425                goto out;
    414426        }
     427        usb_log_debug("(%p-%u): Port reset, enumerating device", hub,
     428            port->port_number);
    415429
    416430        ret = usb_device_enumerate(exch, port->port_number);
    417431        if (ret != EOK) {
    418                 usb_log_error("Failed to enumerate device on port %u: %s",
     432                usb_log_error("(%p-%u): Failed to enumerate device: %s", hub,
    419433                    port->port_number, str_error(ret));
    420434                const int ret = port_enable(port, false);
    421435                if (ret != EOK) {
    422                         usb_log_warning("Failed to disable port %u (%s), NOT "
    423                             "releasing default address.", port->port_number,
    424                             str_error(ret));
     436                        usb_log_warning("(%p-%u)Failed to disable port (%s), "
     437                            "NOT releasing default address.", hub,
     438                            port->port_number, str_error(ret));
    425439                } else {
    426440                        const int ret = usb_release_default_address(exch);
    427441                        if (ret != EOK)
    428                                 usb_log_warning("Failed to release default "
    429                                     "address: %s", str_error(ret));
     442                                usb_log_warning("(%p-%u): Failed to release "
     443                                    "default address: %s", hub,
     444                                    port->port_number, str_error(ret));
    430445                }
    431446        } else {
     447                usb_log_debug("(%p-%u): Device enumerated", hub,
     448                    port->port_number);
    432449                port->device_attached = true;
    433450                if (usb_release_default_address(exch) != EOK)
    434                         usb_log_warning("Failed to release default address\n");
     451                        usb_log_warning("(%p-%u): Failed to release default "
     452                            "address", hub, port->port_number);
    435453        }
    436454out:
     
    469487        data->speed = speed;
    470488
    471         fibril_mutex_lock(&port->mutex);
    472         port->reset_completed = false;
    473         fibril_mutex_unlock(&port->mutex);
    474 
    475489        fid_t fibril = fibril_create(add_device_phase1_worker_fibril, data);
    476490        if (fibril == 0) {
  • uspace/drv/bus/usb/usbhub/port.h

    rc4ba645d r96323d2  
    5252        /** CV for waiting to port reset completion. */
    5353        fibril_condvar_t reset_cv;
    54         /** Whether port reset is completed.
     54        /** Port reset status.
    5555         * Guarded by @c reset_mutex.
    5656         */
    57         bool reset_completed;
    58         /** Whether to announce the port reset as successful. */
    59         bool reset_okay;
     57        enum {
     58                NO_RESET,
     59                IN_RESET,
     60                RESET_OK,
     61                RESET_FAIL,
     62        } reset_status;
    6063        /** Device reported to USB bus driver */
    6164        bool device_attached;
     
    7275        port->port_number = port_number;
    7376        port->control_pipe = control_pipe;
    74         port->reset_completed = false;
    75         port->reset_okay = false;
     77        port->reset_status = NO_RESET;
    7678        port->device_attached = false;
    7779        fibril_mutex_initialize(&port->mutex);
Note: See TracChangeset for help on using the changeset viewer.