Changeset a825eeb0 in mainline


Ignore:
Timestamp:
2011-10-13T12:55:34Z (12 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
22a2b763
Parents:
3875af65
Message:

usbhub: Remove connected devices before confirming device gone.

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

Legend:

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

    r3875af65 ra825eeb0  
    5555};
    5656
    57 static void usb_hub_port_removed_device(usb_hub_port_t *port,
    58     usb_hub_dev_t *hub);
     57static int usb_hub_port_device_gone(usb_hub_port_t *port, usb_hub_dev_t *hub);
    5958static void usb_hub_port_reset_completed(usb_hub_port_t *port,
    6059    usb_port_status_t status);
     
    6564    usb_speed_t speed);
    6665
     66int usb_hub_port_fini(usb_hub_port_t *port, usb_hub_dev_t *hub)
     67{
     68        assert(port);
     69        if (port->attached_device.fun)
     70                return usb_hub_port_device_gone(port, hub);
     71        return EOK;
     72}
     73/*----------------------------------------------------------------------------*/
    6774/**
    6875 * Clear feature on hub port.
    6976 *
    70  * @param hc Host controller telephone
    71  * @param address Hub address
    72  * @param port_index Port
    73  * @param feature Feature selector
     77 * @param port Port structure.
     78 * @param feature Feature selector.
    7479 * @return Operation result
    7580 */
     
    7883{
    7984        assert(port);
    80         usb_device_request_setup_packet_t clear_request = {
     85        const usb_device_request_setup_packet_t clear_request = {
    8186                .request_type = USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE,
    8287                .request = USB_DEVREQ_CLEAR_FEATURE,
     
    9095/*----------------------------------------------------------------------------*/
    9196/**
    92  * Clear feature on hub port.
    93  *
    94  * @param hc Host controller telephone
    95  * @param address Hub address
    96  * @param port_index Port
    97  * @param feature Feature selector
     97 * Set feature on hub port.
     98 *
     99 * @param port Port structure.
     100 * @param feature Feature selector.
    98101 * @return Operation result
    99102 */
     
    102105{
    103106        assert(port);
    104         usb_device_request_setup_packet_t clear_request = {
     107        const usb_device_request_setup_packet_t clear_request = {
    105108                .request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE,
    106109                .request = USB_DEVREQ_SET_FEATURE,
     
    113116}
    114117/*----------------------------------------------------------------------------*/
     118/**
     119 * Mark reset process as failed due to external reasons
     120 *
     121 * @param port Port structure
     122 */
    115123void usb_hub_port_reset_fail(usb_hub_port_t *port)
    116124{
     
    124132/*----------------------------------------------------------------------------*/
    125133/**
    126  * Process interrupts on given hub port
     134 * Process interrupts on given port
    127135 *
    128136 * Accepts connection, over current and port reset change.
     137 * @param port port structure
    129138 * @param hub hub representation
    130  * @param port port number, starting from 1
    131139 */
    132140void usb_hub_port_process_interrupt(usb_hub_port_t *port, usb_hub_dev_t *hub)
     
    171179                         * to that handler, it shall ACK the change too. */
    172180                        if (!(status & USB_HUB_PORT_C_STATUS_ENABLED)) {
    173                                 usb_hub_port_removed_device(port, hub);
     181                                usb_hub_port_device_gone(port, hub);
    174182                        }
    175183                }
     
    180188                usb_log_info("Port %zu, disabled because of errors.\n",
    181189                   port->port_number);
    182                 usb_hub_port_removed_device(port, hub);
     190                usb_hub_port_device_gone(port, hub);
    183191                const int rc = usb_hub_port_clear_feature(port,
    184192                        USB_HUB_FEATURE_C_PORT_ENABLE);
     
    238246            port->port_number, status);
    239247}
    240 
     248/*----------------------------------------------------------------------------*/
    241249/**
    242250 * routine called when a device on port has been removed
     
    245253 * Otherwise does not do anything, because DDF does not allow to remove device
    246254 * from it`s device tree.
     255 * @param port port structure
    247256 * @param hub hub representation
    248  * @param port port number, starting from 1
    249  */
    250 static void usb_hub_port_removed_device(usb_hub_port_t *port,
    251     usb_hub_dev_t *hub)
     257 */
     258int usb_hub_port_device_gone(usb_hub_port_t *port, usb_hub_dev_t *hub)
    252259{
    253260        assert(port);
    254261        assert(hub);
    255         if (port->attached_device.address >= 0) {
    256                 fibril_mutex_lock(&port->mutex);
    257                 usb_log_debug("Removing device on port %zu.\n",
    258                     port->port_number);
    259                 const int ret = ddf_fun_unbind(port->attached_device.fun);
    260                 if (ret == EOK) {
    261                         ddf_fun_destroy(port->attached_device.fun);
    262                         const int ret =
    263                             usb_hc_unregister_device(&hub->connection,
    264                                 port->attached_device.address);
    265                         if (ret != EOK) {
    266                                 usb_log_error("Failed to unregister "
    267                                    "address of removed device: %s.\n",
    268                                    str_error(ret));
    269                         }
    270                 } else {
    271                         usb_log_error("Failed to unbind child function on port"
    272                            " %zu: %s.\n", port->port_number, str_error(ret));
    273                 }
    274                 port->attached_device.address = -1;
    275                 port->attached_device.fun = NULL;
    276                 fibril_mutex_unlock(&port->mutex);
    277                 usb_log_info("Removed device on port %zu.\n",
    278                     port->port_number);
    279         } else {
     262        if (port->attached_device.address < 0) {
    280263                usb_log_warning(
    281264                    "Device on port %zu removed before being registered.\n",
     
    288271                 */
    289272                usb_hub_port_reset_fail(port);
    290         }
    291 }
    292 
     273                return EOK;
     274        }
     275
     276        fibril_mutex_lock(&port->mutex);
     277        assert(port->attached_device.fun);
     278        usb_log_debug("Removing device on port %zu.\n", port->port_number);
     279        int ret = ddf_fun_unbind(port->attached_device.fun);
     280        if (ret != EOK) {
     281                usb_log_error("Failed to unbind child function on port"
     282                    " %zu: %s.\n", port->port_number, str_error(ret));
     283                fibril_mutex_unlock(&port->mutex);
     284                return ret;
     285        }
     286
     287        ddf_fun_destroy(port->attached_device.fun);
     288        port->attached_device.fun = NULL;
     289
     290        ret = usb_hc_unregister_device(&hub->connection,
     291            port->attached_device.address);
     292        if (ret != EOK) {
     293                usb_log_warning("Failed to unregister address of the removed "
     294                    "device: %s.\n", str_error(ret));
     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;
     300}
     301/*----------------------------------------------------------------------------*/
    293302/**
    294303 * Process port reset change
     
    296305 * After this change port should be enabled, unless some problem occurred.
    297306 * This functions triggers second phase of enabling new device.
    298  * @param hub
    299  * @param port
    300  * @param status
    301  */
    302 static void usb_hub_port_reset_completed(usb_hub_port_t *port,
     307 * @param port Port structure
     308 * @param status Port status mask
     309 */
     310void usb_hub_port_reset_completed(usb_hub_port_t *port,
    303311    usb_port_status_t status)
    304312{
     
    330338/** Retrieve port status.
    331339 *
    332  * @param[in] ctrl_pipe Control pipe to use.
    333  * @param[in] port Port number (starting at 1).
     340 * @param[in] port Port structure
    334341 * @param[out] status Where to store the port status.
    335342 * @return Error code.
     
    397404        fibril_mutex_unlock(&port->mutex);
    398405
    399         if (port->reset_okay) {
    400                 return EOK;
    401         } else {
    402                 return ESTALL;
    403         }
    404 }
    405 
     406        return port->reset_okay ? EOK : ESTALL;
     407}
     408/*----------------------------------------------------------------------------*/
    406409/** Fibril for adding a new device.
    407410 *
     
    412415 * @return 0 Always.
    413416 */
    414 static int add_device_phase1_worker_fibril(void *arg)
     417int add_device_phase1_worker_fibril(void *arg)
    415418{
    416419        struct add_device_phase1 *data = arg;
     
    449452        free(arg);
    450453
    451         return EOK;
    452 }
    453 
     454        return rc;
     455}
     456/*----------------------------------------------------------------------------*/
    454457/** Start device adding when connection change is detected.
    455458 *
  • uspace/drv/bus/usb/usbhub/port.h

    r3875af65 ra825eeb0  
    7676        fibril_condvar_initialize(&port->reset_cv);
    7777}
    78 
    79 void usb_hub_port_reset_fail(usb_hub_port_t *port);
    80 void usb_hub_port_process_interrupt(usb_hub_port_t *port, usb_hub_dev_t *hub);
     78int usb_hub_port_fini(usb_hub_port_t *port, usb_hub_dev_t *hub);
    8179int usb_hub_port_clear_feature(
    8280    usb_hub_port_t *port, usb_hub_class_feature_t feature);
    8381int usb_hub_port_set_feature(
    8482    usb_hub_port_t *port, usb_hub_class_feature_t feature);
     83void usb_hub_port_reset_fail(usb_hub_port_t *port);
     84void usb_hub_port_process_interrupt(usb_hub_port_t *port, usb_hub_dev_t *hub);
    8585
    8686#endif
  • uspace/drv/bus/usb/usbhub/usbhub.c

    r3875af65 ra825eeb0  
    9898
    9999        assert(!hub->running);
     100
     101        for (size_t port = 0; port < hub->port_count; ++port) {
     102                if (hub->ports[port].attached_device.fun) {
     103                        const int ret =
     104                            usb_hub_port_fini(&hub->ports[port], hub);
     105                        if (ret != EOK)
     106                                return ret;
     107                }
     108        }
     109        free(hub->ports);
     110
    100111        const int ret = ddf_fun_unbind(hub->hub_fun);
    101112        if (ret != EOK) {
     
    105116        }
    106117        ddf_fun_destroy(hub->hub_fun);
    107         free(hub->ports);
     118
    108119        free(hub);
    109120        usb_dev->driver_data = NULL;
Note: See TracChangeset for help on using the changeset viewer.