usb: check usb_hub_to_struct_hub() return value
usb_hub_to_struct_hub() can return NULL in some unlikely cases. Add checks where appropriate, or pass the hub pointer as an additional argument if it's known to be valid. The places it makes sense to check usb_hub_to_struct_hub() are picked based on feedback from Alan Stern. Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
025f880cb2
commit
41341261aa
@ -718,18 +718,18 @@ static void hub_tt_work(struct work_struct *work)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* usb_hub_set_port_power - control hub port's power state
|
* usb_hub_set_port_power - control hub port's power state
|
||||||
* @hdev: target hub
|
* @hdev: USB device belonging to the usb hub
|
||||||
|
* @hub: target hub
|
||||||
* @port1: port index
|
* @port1: port index
|
||||||
* @set: expected status
|
* @set: expected status
|
||||||
*
|
*
|
||||||
* call this function to control port's power via setting or
|
* call this function to control port's power via setting or
|
||||||
* clearing the port's PORT_POWER feature.
|
* clearing the port's PORT_POWER feature.
|
||||||
*/
|
*/
|
||||||
int usb_hub_set_port_power(struct usb_device *hdev, int port1,
|
int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
|
||||||
bool set)
|
int port1, bool set)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
|
|
||||||
struct usb_port *port_dev = hub->ports[port1 - 1];
|
struct usb_port *port_dev = hub->ports[port1 - 1];
|
||||||
|
|
||||||
if (set)
|
if (set)
|
||||||
@ -1769,15 +1769,17 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
|
|||||||
static int find_port_owner(struct usb_device *hdev, unsigned port1,
|
static int find_port_owner(struct usb_device *hdev, unsigned port1,
|
||||||
struct dev_state ***ppowner)
|
struct dev_state ***ppowner)
|
||||||
{
|
{
|
||||||
|
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
|
||||||
|
|
||||||
if (hdev->state == USB_STATE_NOTATTACHED)
|
if (hdev->state == USB_STATE_NOTATTACHED)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
if (port1 == 0 || port1 > hdev->maxchild)
|
if (port1 == 0 || port1 > hdev->maxchild)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* This assumes that devices not managed by the hub driver
|
/* Devices not managed by the hub driver
|
||||||
* will always have maxchild equal to 0.
|
* will always have maxchild equal to 0.
|
||||||
*/
|
*/
|
||||||
*ppowner = &(usb_hub_to_struct_hub(hdev)->ports[port1 - 1]->port_owner);
|
*ppowner = &(hub->ports[port1 - 1]->port_owner);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5323,7 +5325,8 @@ void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1,
|
|||||||
{
|
{
|
||||||
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
|
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
|
||||||
|
|
||||||
hub->ports[port1 - 1]->connect_type = type;
|
if (hub)
|
||||||
|
hub->ports[port1 - 1]->connect_type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -5339,6 +5342,9 @@ usb_get_hub_port_connect_type(struct usb_device *hdev, int port1)
|
|||||||
{
|
{
|
||||||
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
|
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
|
||||||
|
|
||||||
|
if (!hub)
|
||||||
|
return USB_PORT_CONNECT_TYPE_UNKNOWN;
|
||||||
|
|
||||||
return hub->ports[port1 - 1]->connect_type;
|
return hub->ports[port1 - 1]->connect_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5397,6 +5403,9 @@ acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev,
|
|||||||
{
|
{
|
||||||
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
|
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
|
||||||
|
|
||||||
|
if (!hub)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
return DEVICE_ACPI_HANDLE(&hub->ports[port1 - 1]->dev);
|
return DEVICE_ACPI_HANDLE(&hub->ports[port1 - 1]->dev);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -100,7 +100,7 @@ extern int usb_hub_create_port_device(struct usb_hub *hub,
|
|||||||
int port1);
|
int port1);
|
||||||
extern void usb_hub_remove_port_device(struct usb_hub *hub,
|
extern void usb_hub_remove_port_device(struct usb_hub *hub,
|
||||||
int port1);
|
int port1);
|
||||||
extern int usb_hub_set_port_power(struct usb_device *hdev,
|
extern int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
|
||||||
int port1, bool set);
|
int port1, bool set);
|
||||||
extern struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev);
|
extern struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev);
|
||||||
extern int hub_port_debounce(struct usb_hub *hub, int port1,
|
extern int hub_port_debounce(struct usb_hub *hub, int port1,
|
||||||
|
@ -86,7 +86,7 @@ static int usb_port_runtime_resume(struct device *dev)
|
|||||||
usb_autopm_get_interface(intf);
|
usb_autopm_get_interface(intf);
|
||||||
set_bit(port1, hub->busy_bits);
|
set_bit(port1, hub->busy_bits);
|
||||||
|
|
||||||
retval = usb_hub_set_port_power(hdev, port1, true);
|
retval = usb_hub_set_port_power(hdev, hub, port1, true);
|
||||||
if (port_dev->child && !retval) {
|
if (port_dev->child && !retval) {
|
||||||
/*
|
/*
|
||||||
* Wait for usb hub port to be reconnected in order to make
|
* Wait for usb hub port to be reconnected in order to make
|
||||||
@ -128,7 +128,7 @@ static int usb_port_runtime_suspend(struct device *dev)
|
|||||||
|
|
||||||
usb_autopm_get_interface(intf);
|
usb_autopm_get_interface(intf);
|
||||||
set_bit(port1, hub->busy_bits);
|
set_bit(port1, hub->busy_bits);
|
||||||
retval = usb_hub_set_port_power(hdev, port1, false);
|
retval = usb_hub_set_port_power(hdev, hub, port1, false);
|
||||||
usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION);
|
usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION);
|
||||||
usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE);
|
usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE);
|
||||||
clear_bit(port1, hub->busy_bits);
|
clear_bit(port1, hub->busy_bits);
|
||||||
|
Loading…
Reference in New Issue
Block a user