From e8bff0306f0d095082eea159133007f1de62b169 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 19 Mar 2013 20:35:21 +0100 Subject: [PATCH 213/364] Fix USB devices not being detected when requested due to delayed attach. --- ChangeLog | 5 +++++ grub-core/bus/usb/usbhub.c | 29 ++++++++++++++++++++++++----- grub-core/commands/keystatus.c | 2 +- grub-core/commands/terminal.c | 12 ++++++++++-- grub-core/commands/usbtest.c | 2 +- grub-core/disk/usbms.c | 5 +++-- grub-core/kern/term.c | 4 ++-- include/grub/term.h | 2 +- include/grub/usb.h | 2 +- 9 files changed, 48 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 94dd5bb..725fbe2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2013-03-19 Vladimir Serbinenko + Fix USB devices not being detected when requested + due to delayed attach. + +2013-03-19 Vladimir Serbinenko + Implement boot time analysis framework. 2013-03-19 Vladimir Serbinenko diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c index f95a567..253e49f 100644 --- a/grub-core/bus/usb/usbhub.c +++ b/grub-core/bus/usb/usbhub.c @@ -29,6 +29,7 @@ static struct grub_usb_device *grub_usb_devs[GRUB_USBHUB_MAX_DEVICES]; static int rescan = 0; +static int npending = 0; struct grub_usb_hub { @@ -227,21 +228,33 @@ attach_root_port (struct grub_usb_hub *hub, int portno, if (current_speed == GRUB_USB_SPEED_NONE) i = 0; } + + grub_boot_time ("After the stable power wait portno=%d", portno); + grub_dprintf ("usb", "total=%d\n", total); if (total >= 2000) - return; + { + grub_boot_time ("Root port timeout"); + return; + } + + grub_boot_time ("After detect_dev"); /* Enable the port. */ err = hub->controller->dev->portstatus (hub->controller, portno, 1); if (err) return; hub->controller->dev->pending_reset = grub_get_time_ms () + 5000; + npending++; grub_millisleep (10); + grub_boot_time ("Port enabled"); + /* Enable the port and create a device. */ dev = grub_usb_hub_add_dev (hub->controller, speed, portno, 0); hub->controller->dev->pending_reset = 0; + npending--; if (! dev) return; @@ -475,6 +488,7 @@ poll_nonroot_hub (grub_usb_device_t dev) * anywhere on the same OHCI controller until * we will finish addressing of reseted device ! */ dev->controller.dev->pending_reset = grub_get_time_ms () + 5000; + npending++; return; } } @@ -510,7 +524,11 @@ poll_nonroot_hub (grub_usb_device_t dev) /* Add the device and assign a device address to it. */ next_dev = grub_usb_hub_add_dev (&dev->controller, speed, i, dev->addr); - dev->controller.dev->pending_reset = 0; + if (dev->controller.dev->pending_reset) + { + dev->controller.dev->pending_reset = 0; + npending--; + } if (! next_dev) continue; @@ -525,7 +543,7 @@ poll_nonroot_hub (grub_usb_device_t dev) } void -grub_usb_poll_devices (void) +grub_usb_poll_devices (int wait_for_completion) { struct grub_usb_hub *hub; int i; @@ -539,7 +557,7 @@ grub_usb_poll_devices (void) grub_usb_speed_t speed = GRUB_USB_SPEED_NONE; int changed = 0; - if (!hub->controller->dev->pending_reset) + if (hub->controller->dev->pending_reset) { /* Check for possible timeout */ if (grub_get_time_ms () > hub->controller->dev->pending_reset) @@ -547,6 +565,7 @@ grub_usb_poll_devices (void) /* Something went wrong, reset device was not * addressed properly, timeout happened */ hub->controller->dev->pending_reset = 0; + npending--; speed = hub->controller->dev->detect_dev (hub->controller, i, &changed); } @@ -573,7 +592,7 @@ grub_usb_poll_devices (void) if (dev && dev->descdev.class == 0x09) poll_nonroot_hub (dev); } - if (!rescan) + if (!(rescan || (npending && wait_for_completion))) break; grub_millisleep (50); } diff --git a/grub-core/commands/keystatus.c b/grub-core/commands/keystatus.c index 0925c6a..460cf4e 100644 --- a/grub-core/commands/keystatus.c +++ b/grub-core/commands/keystatus.c @@ -42,7 +42,7 @@ grub_getkeystatus (void) grub_term_input_t term; if (grub_term_poll_usb) - grub_term_poll_usb (); + grub_term_poll_usb (0); FOR_ACTIVE_TERM_INPUTS(term) { diff --git a/grub-core/commands/terminal.c b/grub-core/commands/terminal.c index 425a411..3002186 100644 --- a/grub-core/commands/terminal.c +++ b/grub-core/commands/terminal.c @@ -108,9 +108,9 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled, if (term) break; if (again) - return grub_error (GRUB_ERR_BAD_ARGUMENT, + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("terminal `%s' isn't found"), - args[i]); + args[i]); for (aut = autoloads; aut; aut = aut->next) if (grub_strcmp (args[i], aut->name) == 0 || (grub_strcmp (args[i], "ofconsole") == 0 @@ -126,6 +126,14 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled, grub_errno = GRUB_ERR_NONE; break; } + if (grub_memcmp (args[i], "serial_usb", + sizeof ("serial_usb") - 1) == 0 + && grub_term_poll_usb) + { + grub_term_poll_usb (1); + again = 1; + continue; + } if (!aut) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("terminal `%s' isn't found"), diff --git a/grub-core/commands/usbtest.c b/grub-core/commands/usbtest.c index af35b8c..01cdca9 100644 --- a/grub-core/commands/usbtest.c +++ b/grub-core/commands/usbtest.c @@ -196,7 +196,7 @@ grub_cmd_usbtest (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - grub_usb_poll_devices (); + grub_usb_poll_devices (1); grub_printf ("USB devices:\n\n"); grub_usb_iterate (usb_iterate, NULL); diff --git a/grub-core/disk/usbms.c b/grub-core/disk/usbms.c index 2cfc537..da01be3 100644 --- a/grub-core/disk/usbms.c +++ b/grub-core/disk/usbms.c @@ -277,7 +277,7 @@ grub_usbms_iterate (grub_scsi_dev_iterate_hook_t hook, void *hook_data, if (pull != GRUB_DISK_PULL_NONE) return 0; - grub_usb_poll_devices (); + grub_usb_poll_devices (1); for (i = 0; i < ARRAY_SIZE (grub_usbms_devices); i++) if (grub_usbms_devices[i]) @@ -611,7 +611,8 @@ grub_usbms_open (int id, int devnum, struct grub_scsi *scsi) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not USB Mass Storage device"); - grub_usb_poll_devices (); + if (!grub_usbms_devices[devnum]) + grub_usb_poll_devices (1); if (!grub_usbms_devices[devnum]) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, diff --git a/grub-core/kern/term.c b/grub-core/kern/term.c index 44ada25..66c5971 100644 --- a/grub-core/kern/term.c +++ b/grub-core/kern/term.c @@ -32,7 +32,7 @@ struct grub_term_input *grub_term_inputs; grub_uint8_t grub_term_normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR; grub_uint8_t grub_term_highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR; -void (*grub_term_poll_usb) (void) = NULL; +void (*grub_term_poll_usb) (int wait_for_completion) = NULL; void (*grub_net_poll_cards_idle) (void) = NULL; /* Put a Unicode character. */ @@ -90,7 +90,7 @@ grub_getkey_noblock (void) grub_term_input_t term; if (grub_term_poll_usb) - grub_term_poll_usb (); + grub_term_poll_usb (0); if (grub_net_poll_cards_idle) grub_net_poll_cards_idle (); diff --git a/include/grub/term.h b/include/grub/term.h index 84f5766..655a5e3 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -467,7 +467,7 @@ grub_print_spaces (struct grub_term_output *term, int number_spaces) grub_putcode (' ', term); } -extern void (*EXPORT_VAR (grub_term_poll_usb)) (void); +extern void (*EXPORT_VAR (grub_term_poll_usb)) (int wait_for_completion); #define GRUB_TERM_REPEAT_PRE_INTERVAL 400 #define GRUB_TERM_REPEAT_INTERVAL 50 diff --git a/include/grub/usb.h b/include/grub/usb.h index 32f0ecd..7164dd5 100644 --- a/include/grub/usb.h +++ b/include/grub/usb.h @@ -291,7 +291,7 @@ struct grub_usb_attach_desc void grub_usb_register_attach_hook_class (struct grub_usb_attach_desc *desc); void grub_usb_unregister_attach_hook_class (struct grub_usb_attach_desc *desc); -void grub_usb_poll_devices (void); +void grub_usb_poll_devices (int wait_for_completion); void grub_usb_device_attach (grub_usb_device_t dev); grub_usb_err_t -- 1.8.1.4