Message ID | 1676586588-25989-2-git-send-email-quic_eserrao@quicinc.com |
---|---|
State | Superseded |
Headers | show |
Series | Add function suspend/resume and remote wakeup support | expand |
Hi Elson, https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Elson-Roy-Serrao/usb-gadget-Properly-configure-the-device-for-remote-wakeup/20230217-063114 base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing patch link: https://lore.kernel.org/r/1676586588-25989-2-git-send-email-quic_eserrao%40quicinc.com patch subject: [PATCH v5 1/5] usb: gadget: Properly configure the device for remote wakeup config: x86_64-randconfig-m001 (https://download.01.org/0day-ci/archive/20230217/202302172243.hKUsQl2q-lkp@intel.com/config) compiler: gcc-11 (Debian 11.3.0-8) 11.3.0 If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> | Reported-by: Dan Carpenter <error27@gmail.com> | Link: https://lore.kernel.org/r/202302172243.hKUsQl2q-lkp@intel.com/ smatch warnings: drivers/usb/gadget/composite.c:1016 set_config() error: we previously assumed 'c' could be null (see line 946) vim +/c +1016 drivers/usb/gadget/composite.c 40982be52d8f64 David Brownell 2008-06-19 910 static int set_config(struct usb_composite_dev *cdev, 40982be52d8f64 David Brownell 2008-06-19 911 const struct usb_ctrlrequest *ctrl, unsigned number) 40982be52d8f64 David Brownell 2008-06-19 912 { 40982be52d8f64 David Brownell 2008-06-19 913 struct usb_gadget *gadget = cdev->gadget; d6f4663664cbd5 Jakob Koschel 2022-03-08 914 struct usb_configuration *c = NULL, *iter; 40982be52d8f64 David Brownell 2008-06-19 915 int result = -EINVAL; 40982be52d8f64 David Brownell 2008-06-19 916 unsigned power = gadget_is_otg(gadget) ? 8 : 100; 40982be52d8f64 David Brownell 2008-06-19 917 int tmp; 40982be52d8f64 David Brownell 2008-06-19 918 40982be52d8f64 David Brownell 2008-06-19 919 if (number) { d6f4663664cbd5 Jakob Koschel 2022-03-08 920 list_for_each_entry(iter, &cdev->configs, list) { d6f4663664cbd5 Jakob Koschel 2022-03-08 921 if (iter->bConfigurationValue != number) d6f4663664cbd5 Jakob Koschel 2022-03-08 922 continue; bdb64d727216b4 Tatyana Brokhman 2011-06-29 923 /* bdb64d727216b4 Tatyana Brokhman 2011-06-29 924 * We disable the FDs of the previous bdb64d727216b4 Tatyana Brokhman 2011-06-29 925 * configuration only if the new configuration bdb64d727216b4 Tatyana Brokhman 2011-06-29 926 * is a valid one bdb64d727216b4 Tatyana Brokhman 2011-06-29 927 */ bdb64d727216b4 Tatyana Brokhman 2011-06-29 928 if (cdev->config) bdb64d727216b4 Tatyana Brokhman 2011-06-29 929 reset_config(cdev); d6f4663664cbd5 Jakob Koschel 2022-03-08 930 c = iter; 40982be52d8f64 David Brownell 2008-06-19 931 result = 0; 40982be52d8f64 David Brownell 2008-06-19 932 break; 40982be52d8f64 David Brownell 2008-06-19 933 } 40982be52d8f64 David Brownell 2008-06-19 934 if (result < 0) 40982be52d8f64 David Brownell 2008-06-19 935 goto done; bdb64d727216b4 Tatyana Brokhman 2011-06-29 936 } else { /* Zero configuration value - need to reset the config */ bdb64d727216b4 Tatyana Brokhman 2011-06-29 937 if (cdev->config) bdb64d727216b4 Tatyana Brokhman 2011-06-29 938 reset_config(cdev); 40982be52d8f64 David Brownell 2008-06-19 939 result = 0; bdb64d727216b4 Tatyana Brokhman 2011-06-29 940 } 40982be52d8f64 David Brownell 2008-06-19 941 1cbfb8c4f62d66 Joel Stanley 2019-09-30 942 DBG(cdev, "%s config #%d: %s\n", e538dfdae85244 Michal Nazarewicz 2011-08-30 943 usb_speed_string(gadget->speed), e538dfdae85244 Michal Nazarewicz 2011-08-30 944 number, c ? c->label : "unconfigured"); ^ 40982be52d8f64 David Brownell 2008-06-19 945 40982be52d8f64 David Brownell 2008-06-19 @946 if (!c) ^ Check for NULL 40982be52d8f64 David Brownell 2008-06-19 947 goto done; 40982be52d8f64 David Brownell 2008-06-19 948 6027f3173e797b Peter Chen 2014-04-29 949 usb_gadget_set_state(gadget, USB_STATE_CONFIGURED); 40982be52d8f64 David Brownell 2008-06-19 950 cdev->config = c; 40982be52d8f64 David Brownell 2008-06-19 951 40982be52d8f64 David Brownell 2008-06-19 952 /* Initialize all interfaces by setting them to altsetting zero. */ 40982be52d8f64 David Brownell 2008-06-19 953 for (tmp = 0; tmp < MAX_CONFIG_INTERFACES; tmp++) { 40982be52d8f64 David Brownell 2008-06-19 954 struct usb_function *f = c->interface[tmp]; 5242658d1b9777 Laurent Pinchart 2009-10-21 955 struct usb_descriptor_header **descriptors; 40982be52d8f64 David Brownell 2008-06-19 956 40982be52d8f64 David Brownell 2008-06-19 957 if (!f) 40982be52d8f64 David Brownell 2008-06-19 958 break; 40982be52d8f64 David Brownell 2008-06-19 959 5242658d1b9777 Laurent Pinchart 2009-10-21 960 /* 5242658d1b9777 Laurent Pinchart 2009-10-21 961 * Record which endpoints are used by the function. This is used 5242658d1b9777 Laurent Pinchart 2009-10-21 962 * to dispatch control requests targeted at that endpoint to the 5242658d1b9777 Laurent Pinchart 2009-10-21 963 * function's setup callback instead of the current 5242658d1b9777 Laurent Pinchart 2009-10-21 964 * configuration's setup callback. 5242658d1b9777 Laurent Pinchart 2009-10-21 965 */ f3bdbe36682631 John Youn 2016-02-05 966 descriptors = function_descriptors(f, gadget->speed); 5242658d1b9777 Laurent Pinchart 2009-10-21 967 5242658d1b9777 Laurent Pinchart 2009-10-21 968 for (; *descriptors; ++descriptors) { 5242658d1b9777 Laurent Pinchart 2009-10-21 969 struct usb_endpoint_descriptor *ep; 5242658d1b9777 Laurent Pinchart 2009-10-21 970 int addr; 5242658d1b9777 Laurent Pinchart 2009-10-21 971 5242658d1b9777 Laurent Pinchart 2009-10-21 972 if ((*descriptors)->bDescriptorType != USB_DT_ENDPOINT) 5242658d1b9777 Laurent Pinchart 2009-10-21 973 continue; 5242658d1b9777 Laurent Pinchart 2009-10-21 974 5242658d1b9777 Laurent Pinchart 2009-10-21 975 ep = (struct usb_endpoint_descriptor *)*descriptors; 5242658d1b9777 Laurent Pinchart 2009-10-21 976 addr = ((ep->bEndpointAddress & 0x80) >> 3) 5242658d1b9777 Laurent Pinchart 2009-10-21 977 | (ep->bEndpointAddress & 0x0f); 5242658d1b9777 Laurent Pinchart 2009-10-21 978 set_bit(addr, f->endpoints); 5242658d1b9777 Laurent Pinchart 2009-10-21 979 } 5242658d1b9777 Laurent Pinchart 2009-10-21 980 40982be52d8f64 David Brownell 2008-06-19 981 result = f->set_alt(f, tmp, 0); 40982be52d8f64 David Brownell 2008-06-19 982 if (result < 0) { 40982be52d8f64 David Brownell 2008-06-19 983 DBG(cdev, "interface %d (%s/%p) alt 0 --> %d\n", 40982be52d8f64 David Brownell 2008-06-19 984 tmp, f->name, f, result); 40982be52d8f64 David Brownell 2008-06-19 985 40982be52d8f64 David Brownell 2008-06-19 986 reset_config(cdev); 40982be52d8f64 David Brownell 2008-06-19 987 goto done; 40982be52d8f64 David Brownell 2008-06-19 988 } 1b9ba000177ee4 Roger Quadros 2011-05-09 989 1b9ba000177ee4 Roger Quadros 2011-05-09 990 if (result == USB_GADGET_DELAYED_STATUS) { 1b9ba000177ee4 Roger Quadros 2011-05-09 991 DBG(cdev, 1b9ba000177ee4 Roger Quadros 2011-05-09 992 "%s: interface %d (%s) requested delayed status\n", 1b9ba000177ee4 Roger Quadros 2011-05-09 993 __func__, tmp, f->name); 1b9ba000177ee4 Roger Quadros 2011-05-09 994 cdev->delayed_status++; 1b9ba000177ee4 Roger Quadros 2011-05-09 995 DBG(cdev, "delayed_status count %d\n", 1b9ba000177ee4 Roger Quadros 2011-05-09 996 cdev->delayed_status); 1b9ba000177ee4 Roger Quadros 2011-05-09 997 } 40982be52d8f64 David Brownell 2008-06-19 998 } 40982be52d8f64 David Brownell 2008-06-19 999 40982be52d8f64 David Brownell 2008-06-19 1000 /* when we return, be sure our power usage is valid */ bcacbf06c89137 Jack Pham 2021-07-20 1001 if (c->MaxPower || (c->bmAttributes & USB_CONFIG_ATT_SELFPOWER)) bcacbf06c89137 Jack Pham 2021-07-20 1002 power = c->MaxPower; bcacbf06c89137 Jack Pham 2021-07-20 1003 else bcacbf06c89137 Jack Pham 2021-07-20 1004 power = CONFIG_USB_GADGET_VBUS_DRAW; bcacbf06c89137 Jack Pham 2021-07-20 1005 a2035411fa1d12 Jack Pham 2020-01-30 1006 if (gadget->speed < USB_SPEED_SUPER) a2035411fa1d12 Jack Pham 2020-01-30 1007 power = min(power, 500U); a2035411fa1d12 Jack Pham 2020-01-30 1008 else a2035411fa1d12 Jack Pham 2020-01-30 1009 power = min(power, 900U); 40982be52d8f64 David Brownell 2008-06-19 1010 done: 5e5caf4fa8d303 Thinh Nguyen 2020-02-03 1011 if (power <= USB_SELF_POWER_VBUS_MAX_DRAW) 5e5caf4fa8d303 Thinh Nguyen 2020-02-03 1012 usb_gadget_set_selfpowered(gadget); 5e5caf4fa8d303 Thinh Nguyen 2020-02-03 1013 else 5e5caf4fa8d303 Thinh Nguyen 2020-02-03 1014 usb_gadget_clear_selfpowered(gadget); 5e5caf4fa8d303 Thinh Nguyen 2020-02-03 1015 24ee47b2693b2d Elson Roy Serrao 2023-02-16 @1016 if (USB_CONFIG_ATT_WAKEUP & c->bmAttributes) ^^^^^^^^^^^^^^^ Unchecked dereference 24ee47b2693b2d Elson Roy Serrao 2023-02-16 1017 usb_gadget_set_remote_wakeup(gadget, 1); 24ee47b2693b2d Elson Roy Serrao 2023-02-16 1018 else 24ee47b2693b2d Elson Roy Serrao 2023-02-16 1019 usb_gadget_set_remote_wakeup(gadget, 0); 24ee47b2693b2d Elson Roy Serrao 2023-02-16 1020 40982be52d8f64 David Brownell 2008-06-19 1021 usb_gadget_vbus_draw(gadget, power); 1b9ba000177ee4 Roger Quadros 2011-05-09 1022 if (result >= 0 && cdev->delayed_status) 1b9ba000177ee4 Roger Quadros 2011-05-09 1023 result = USB_GADGET_DELAYED_STATUS; 40982be52d8f64 David Brownell 2008-06-19 1024 return result; 40982be52d8f64 David Brownell 2008-06-19 1025 }
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index fa7dd6c..a37a8f4 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -513,6 +513,19 @@ static u8 encode_bMaxPower(enum usb_device_speed speed, return min(val, 900U) / 8; } +void check_remote_wakeup_config(struct usb_gadget *g, + struct usb_configuration *c) +{ + if (USB_CONFIG_ATT_WAKEUP & c->bmAttributes) { + /* Reset the rw bit if gadget is not capable of it */ + if (!g->wakeup_capable && g->ops->set_remote_wakeup) { + WARN(c->cdev, "Clearing wakeup bit for config c.%d\n", + c->bConfigurationValue); + c->bmAttributes &= ~USB_CONFIG_ATT_WAKEUP; + } + } +} + static int config_buf(struct usb_configuration *config, enum usb_device_speed speed, void *buf, u8 type) { @@ -1000,6 +1013,11 @@ static int set_config(struct usb_composite_dev *cdev, else usb_gadget_clear_selfpowered(gadget); + if (USB_CONFIG_ATT_WAKEUP & c->bmAttributes) + usb_gadget_set_remote_wakeup(gadget, 1); + else + usb_gadget_set_remote_wakeup(gadget, 0); + usb_gadget_vbus_draw(gadget, power); if (result >= 0 && cdev->delayed_status) result = USB_GADGET_DELAYED_STATUS; diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index b9f1136..4c639e9 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -1761,6 +1761,9 @@ static int configfs_composite_bind(struct usb_gadget *gadget, if (gadget_is_otg(gadget)) c->descriptors = otg_desc; + /* Properly configure the bmAttributes wakeup bit */ + check_remote_wakeup_config(gadget, c); + cfg = container_of(c, struct config_usb_cfg, c); if (!list_empty(&cfg->string_list)) { i = 0; diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 23b0629..3dcbba7 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -514,6 +514,33 @@ int usb_gadget_wakeup(struct usb_gadget *gadget) EXPORT_SYMBOL_GPL(usb_gadget_wakeup); /** + * usb_gadget_set_remote_wakeup - configures the device remote wakeup feature. + * @gadget:the device being configured for remote wakeup + * @set:value to be configured. + * + * set to one to enable remote wakeup feature and zero to disable it. + * + * returns zero on success, else negative errno. + */ +int usb_gadget_set_remote_wakeup(struct usb_gadget *gadget, int set) +{ + int ret = 0; + + if (!gadget->ops->set_remote_wakeup) { + ret = -EOPNOTSUPP; + goto out; + } + + ret = gadget->ops->set_remote_wakeup(gadget, set); + +out: + trace_usb_gadget_set_remote_wakeup(gadget, ret); + + return ret; +} +EXPORT_SYMBOL_GPL(usb_gadget_set_remote_wakeup); + +/** * usb_gadget_set_selfpowered - sets the device selfpowered feature. * @gadget:the device being declared as self-powered * diff --git a/drivers/usb/gadget/udc/trace.h b/drivers/usb/gadget/udc/trace.h index abdbcb1..a5ed26f 100644 --- a/drivers/usb/gadget/udc/trace.h +++ b/drivers/usb/gadget/udc/trace.h @@ -91,6 +91,11 @@ DEFINE_EVENT(udc_log_gadget, usb_gadget_wakeup, TP_ARGS(g, ret) ); +DEFINE_EVENT(udc_log_gadget, usb_gadget_set_remote_wakeup, + TP_PROTO(struct usb_gadget *g, int ret), + TP_ARGS(g, ret) +); + DEFINE_EVENT(udc_log_gadget, usb_gadget_set_selfpowered, TP_PROTO(struct usb_gadget *g, int ret), TP_ARGS(g, ret) diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 608dc96..d949e91 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -413,6 +413,8 @@ extern int composite_dev_prepare(struct usb_composite_driver *composite, extern int composite_os_desc_req_prepare(struct usb_composite_dev *cdev, struct usb_ep *ep0); void composite_dev_cleanup(struct usb_composite_dev *cdev); +void check_remote_wakeup_config(struct usb_gadget *g, + struct usb_configuration *c); static inline struct usb_composite_driver *to_cdriver( struct usb_gadget_driver *gdrv) diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 00750f7..1d79612 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -310,6 +310,7 @@ struct usb_udc; struct usb_gadget_ops { int (*get_frame)(struct usb_gadget *); int (*wakeup)(struct usb_gadget *); + int (*set_remote_wakeup)(struct usb_gadget *, int set); int (*set_selfpowered) (struct usb_gadget *, int is_selfpowered); int (*vbus_session) (struct usb_gadget *, int is_active); int (*vbus_draw) (struct usb_gadget *, unsigned mA); @@ -384,6 +385,8 @@ struct usb_gadget_ops { * @connected: True if gadget is connected. * @lpm_capable: If the gadget max_speed is FULL or HIGH, this flag * indicates that it supports LPM as per the LPM ECN & errata. + * @wakeup_capable: True if gadget is capable of sending remote wakeup. + * @wakeup_armed: True if gadget is armed by the host for remote wakeup. * @irq: the interrupt number for device controller. * @id_number: a unique ID number for ensuring that gadget names are distinct * @@ -445,6 +448,8 @@ struct usb_gadget { unsigned deactivated:1; unsigned connected:1; unsigned lpm_capable:1; + unsigned wakeup_capable:1; + unsigned wakeup_armed:1; int irq; int id_number; }; @@ -601,6 +606,7 @@ static inline int gadget_is_otg(struct usb_gadget *g) #if IS_ENABLED(CONFIG_USB_GADGET) int usb_gadget_frame_number(struct usb_gadget *gadget); int usb_gadget_wakeup(struct usb_gadget *gadget); +int usb_gadget_set_remote_wakeup(struct usb_gadget *gadget, int set); int usb_gadget_set_selfpowered(struct usb_gadget *gadget); int usb_gadget_clear_selfpowered(struct usb_gadget *gadget); int usb_gadget_vbus_connect(struct usb_gadget *gadget); @@ -616,6 +622,8 @@ static inline int usb_gadget_frame_number(struct usb_gadget *gadget) { return 0; } static inline int usb_gadget_wakeup(struct usb_gadget *gadget) { return 0; } +static inline int usb_gadget_set_remote_wakeup(struct usb_gadget *gadget, int set) +{ return 0; } static inline int usb_gadget_set_selfpowered(struct usb_gadget *gadget) { return 0; } static inline int usb_gadget_clear_selfpowered(struct usb_gadget *gadget)