Fix USB devices not being detected when requested

due to delayed attach.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2013-03-19 20:35:21 +01:00
parent e744219bb6
commit d745dda77e
9 changed files with 48 additions and 15 deletions

View File

@ -1,3 +1,8 @@
2013-03-19 Vladimir Serbinenko <phcoder@gmail.com>
Fix USB devices not being detected when requested
due to delayed attach.
2013-03-19 Vladimir Serbinenko <phcoder@gmail.com> 2013-03-19 Vladimir Serbinenko <phcoder@gmail.com>
Implement boot time analysis framework. Implement boot time analysis framework.

View File

@ -29,6 +29,7 @@
static struct grub_usb_device *grub_usb_devs[GRUB_USBHUB_MAX_DEVICES]; static struct grub_usb_device *grub_usb_devs[GRUB_USBHUB_MAX_DEVICES];
static int rescan = 0; static int rescan = 0;
static int npending = 0;
struct grub_usb_hub 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) if (current_speed == GRUB_USB_SPEED_NONE)
i = 0; i = 0;
} }
grub_boot_time ("After the stable power wait portno=%d", portno);
grub_dprintf ("usb", "total=%d\n", total); grub_dprintf ("usb", "total=%d\n", total);
if (total >= 2000) if (total >= 2000)
return; {
grub_boot_time ("Root port timeout");
return;
}
grub_boot_time ("After detect_dev");
/* Enable the port. */ /* Enable the port. */
err = hub->controller->dev->portstatus (hub->controller, portno, 1); err = hub->controller->dev->portstatus (hub->controller, portno, 1);
if (err) if (err)
return; return;
hub->controller->dev->pending_reset = grub_get_time_ms () + 5000; hub->controller->dev->pending_reset = grub_get_time_ms () + 5000;
npending++;
grub_millisleep (10); grub_millisleep (10);
grub_boot_time ("Port enabled");
/* Enable the port and create a device. */ /* Enable the port and create a device. */
dev = grub_usb_hub_add_dev (hub->controller, speed, portno, 0); dev = grub_usb_hub_add_dev (hub->controller, speed, portno, 0);
hub->controller->dev->pending_reset = 0; hub->controller->dev->pending_reset = 0;
npending--;
if (! dev) if (! dev)
return; return;
@ -475,6 +488,7 @@ poll_nonroot_hub (grub_usb_device_t dev)
* anywhere on the same OHCI controller until * anywhere on the same OHCI controller until
* we will finish addressing of reseted device ! */ * we will finish addressing of reseted device ! */
dev->controller.dev->pending_reset = grub_get_time_ms () + 5000; dev->controller.dev->pending_reset = grub_get_time_ms () + 5000;
npending++;
return; return;
} }
} }
@ -510,7 +524,11 @@ poll_nonroot_hub (grub_usb_device_t dev)
/* Add the device and assign a device address to it. */ /* Add the device and assign a device address to it. */
next_dev = grub_usb_hub_add_dev (&dev->controller, speed, i, dev->addr); 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) if (! next_dev)
continue; continue;
@ -525,7 +543,7 @@ poll_nonroot_hub (grub_usb_device_t dev)
} }
void void
grub_usb_poll_devices (void) grub_usb_poll_devices (int wait_for_completion)
{ {
struct grub_usb_hub *hub; struct grub_usb_hub *hub;
int i; int i;
@ -539,7 +557,7 @@ grub_usb_poll_devices (void)
grub_usb_speed_t speed = GRUB_USB_SPEED_NONE; grub_usb_speed_t speed = GRUB_USB_SPEED_NONE;
int changed = 0; int changed = 0;
if (!hub->controller->dev->pending_reset) if (hub->controller->dev->pending_reset)
{ {
/* Check for possible timeout */ /* Check for possible timeout */
if (grub_get_time_ms () > hub->controller->dev->pending_reset) 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 /* Something went wrong, reset device was not
* addressed properly, timeout happened */ * addressed properly, timeout happened */
hub->controller->dev->pending_reset = 0; hub->controller->dev->pending_reset = 0;
npending--;
speed = hub->controller->dev->detect_dev (hub->controller, speed = hub->controller->dev->detect_dev (hub->controller,
i, &changed); i, &changed);
} }
@ -573,7 +592,7 @@ grub_usb_poll_devices (void)
if (dev && dev->descdev.class == 0x09) if (dev && dev->descdev.class == 0x09)
poll_nonroot_hub (dev); poll_nonroot_hub (dev);
} }
if (!rescan) if (!(rescan || (npending && wait_for_completion)))
break; break;
grub_millisleep (50); grub_millisleep (50);
} }

View File

@ -42,7 +42,7 @@ grub_getkeystatus (void)
grub_term_input_t term; grub_term_input_t term;
if (grub_term_poll_usb) if (grub_term_poll_usb)
grub_term_poll_usb (); grub_term_poll_usb (0);
FOR_ACTIVE_TERM_INPUTS(term) FOR_ACTIVE_TERM_INPUTS(term)
{ {

View File

@ -108,9 +108,9 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled,
if (term) if (term)
break; break;
if (again) if (again)
return grub_error (GRUB_ERR_BAD_ARGUMENT, return grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("terminal `%s' isn't found"), N_("terminal `%s' isn't found"),
args[i]); args[i]);
for (aut = autoloads; aut; aut = aut->next) for (aut = autoloads; aut; aut = aut->next)
if (grub_strcmp (args[i], aut->name) == 0 if (grub_strcmp (args[i], aut->name) == 0
|| (grub_strcmp (args[i], "ofconsole") == 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; grub_errno = GRUB_ERR_NONE;
break; 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) if (!aut)
return grub_error (GRUB_ERR_BAD_ARGUMENT, return grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("terminal `%s' isn't found"), N_("terminal `%s' isn't found"),

View File

@ -196,7 +196,7 @@ grub_cmd_usbtest (grub_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)), int argc __attribute__ ((unused)),
char **args __attribute__ ((unused))) char **args __attribute__ ((unused)))
{ {
grub_usb_poll_devices (); grub_usb_poll_devices (1);
grub_printf ("USB devices:\n\n"); grub_printf ("USB devices:\n\n");
grub_usb_iterate (usb_iterate, NULL); grub_usb_iterate (usb_iterate, NULL);

View File

@ -277,7 +277,7 @@ grub_usbms_iterate (grub_scsi_dev_iterate_hook_t hook, void *hook_data,
if (pull != GRUB_DISK_PULL_NONE) if (pull != GRUB_DISK_PULL_NONE)
return 0; return 0;
grub_usb_poll_devices (); grub_usb_poll_devices (1);
for (i = 0; i < ARRAY_SIZE (grub_usbms_devices); i++) for (i = 0; i < ARRAY_SIZE (grub_usbms_devices); i++)
if (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, return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"not USB Mass Storage 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]) if (!grub_usbms_devices[devnum])
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, return grub_error (GRUB_ERR_UNKNOWN_DEVICE,

View File

@ -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_normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR;
grub_uint8_t grub_term_highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_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; void (*grub_net_poll_cards_idle) (void) = NULL;
/* Put a Unicode character. */ /* Put a Unicode character. */
@ -90,7 +90,7 @@ grub_getkey_noblock (void)
grub_term_input_t term; grub_term_input_t term;
if (grub_term_poll_usb) if (grub_term_poll_usb)
grub_term_poll_usb (); grub_term_poll_usb (0);
if (grub_net_poll_cards_idle) if (grub_net_poll_cards_idle)
grub_net_poll_cards_idle (); grub_net_poll_cards_idle ();

View File

@ -467,7 +467,7 @@ grub_print_spaces (struct grub_term_output *term, int number_spaces)
grub_putcode (' ', term); 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_PRE_INTERVAL 400
#define GRUB_TERM_REPEAT_INTERVAL 50 #define GRUB_TERM_REPEAT_INTERVAL 50

View File

@ -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_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_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); void grub_usb_device_attach (grub_usb_device_t dev);
grub_usb_err_t grub_usb_err_t