Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: usb: cdc-ether: unify error handling in probe

usbnet_generic_cdc_bind() is duplicating the error handling
multiple times. That is bad. Unify it with jumps.

V2: Update error logging with every cause a unique message

Signed-off-by: Oliver Neukum <oneukum@suse.com>
Link: https://patch.msgid.link/20260312084612.1469853-1-oneukum@suse.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Oliver Neukum and committed by
Jakub Kicinski
a99f06e5 b87249aa

+30 -24
+30 -24
drivers/net/usb/cdc_ether.c
··· 115 115 int len = intf->cur_altsetting->extralen; 116 116 struct usb_interface_descriptor *d; 117 117 struct cdc_state *info = (void *) &dev->data; 118 - int status; 118 + int status = -ENODEV; 119 119 int rndis; 120 120 bool android_rndis_quirk = false; 121 121 struct usb_driver *driver = driver_of(intf); ··· 169 169 info->header = header.usb_cdc_header_desc; 170 170 info->ether = header.usb_cdc_ether_desc; 171 171 if (!info->u) { 172 - if (rndis) 172 + if (rndis) { 173 173 goto skip; 174 - else /* in that case a quirk is mandatory */ 174 + } else { 175 + /* in that case a quirk is mandatory */ 176 + dev_err(&dev->udev->dev, "No union descriptors\n"); 175 177 goto bad_desc; 178 + } 176 179 } 177 180 /* we need a master/control interface (what we're 178 181 * probed with) and a slave/data interface; union ··· 195 192 android_rndis_quirk = true; 196 193 goto skip; 197 194 } 195 + dev_err(&intf->dev, "bad CDC descriptors\n"); 198 196 goto bad_desc; 199 197 } 200 198 if (info->control != intf) { 201 - dev_dbg(&intf->dev, "bogus CDC Union\n"); 202 199 /* Ambit USB Cable Modem (and maybe others) 203 200 * interchanges master and slave interface. 204 201 */ 205 202 if (info->data == intf) { 206 203 info->data = info->control; 207 204 info->control = intf; 208 - } else 205 + } else { 206 + dev_err(&intf->dev, "bogus CDC Union\n"); 209 207 goto bad_desc; 208 + } 210 209 } 211 210 212 211 /* some devices merge these - skip class check */ ··· 218 213 /* a data interface altsetting does the real i/o */ 219 214 d = &info->data->cur_altsetting->desc; 220 215 if (d->bInterfaceClass != USB_CLASS_CDC_DATA) { 221 - dev_dbg(&intf->dev, "slave class %u\n", d->bInterfaceClass); 216 + dev_err(&intf->dev, "slave class %u\n", d->bInterfaceClass); 222 217 goto bad_desc; 223 218 } 224 219 skip: ··· 232 227 if (rndis && is_rndis(&intf->cur_altsetting->desc) && 233 228 header.usb_cdc_acm_descriptor && 234 229 header.usb_cdc_acm_descriptor->bmCapabilities) { 235 - dev_dbg(&intf->dev, 230 + dev_err(&intf->dev, 236 231 "ACM capabilities %02x, not really RNDIS?\n", 237 232 header.usb_cdc_acm_descriptor->bmCapabilities); 238 233 goto bad_desc; ··· 247 242 248 243 if (header.usb_cdc_mdlm_desc && 249 244 memcmp(header.usb_cdc_mdlm_desc->bGUID, mbm_guid, 16)) { 250 - dev_dbg(&intf->dev, "GUID doesn't match\n"); 245 + dev_err(&intf->dev, "GUID doesn't match\n"); 251 246 goto bad_desc; 252 247 } 253 248 254 249 if (header.usb_cdc_mdlm_detail_desc && 255 250 header.usb_cdc_mdlm_detail_desc->bLength < 256 251 (sizeof(struct usb_cdc_mdlm_detail_desc) + 1)) { 257 - dev_dbg(&intf->dev, "Descriptor too short\n"); 252 + dev_err(&intf->dev, "Descriptor too short\n"); 258 253 goto bad_desc; 259 254 } 260 255 ··· 272 267 info->control = usb_ifnum_to_if(dev->udev, 0); 273 268 info->data = usb_ifnum_to_if(dev->udev, 1); 274 269 if (!info->control || !info->data || info->control != intf) { 275 - dev_dbg(&intf->dev, 270 + dev_err(&intf->dev, 276 271 "rndis: master #0/%p slave #1/%p\n", 277 272 info->control, 278 273 info->data); ··· 280 275 } 281 276 282 277 } else if (!info->header || (!rndis && !info->ether)) { 283 - dev_dbg(&intf->dev, "missing cdc %s%s%sdescriptor\n", 278 + dev_err(&intf->dev, "missing cdc %s%s%sdescriptor\n", 284 279 info->header ? "" : "header ", 285 280 info->u ? "" : "union ", 286 281 info->ether ? "" : "ether "); ··· 292 287 */ 293 288 if (info->data != info->control) { 294 289 status = usb_driver_claim_interface(driver, info->data, dev); 295 - if (status < 0) 296 - return status; 290 + if (status < 0) { 291 + dev_err(&intf->dev, "Second interface unclaimable\n"); 292 + goto bad_desc; 293 + } 297 294 } 298 295 status = usbnet_get_endpoints(dev, info->data); 299 296 if (status < 0) { 300 - /* ensure immediate exit from usbnet_disconnect */ 301 - usb_set_intfdata(info->data, NULL); 302 - if (info->data != info->control) 303 - usb_driver_release_interface(driver, info->data); 304 - return status; 297 + dev_dbg(&intf->dev, "Mandatory endpoints missing\n"); 298 + goto bail_out_and_release; 305 299 } 306 300 307 301 /* status endpoint: optional for CDC Ethernet, not RNDIS (or ACM) */ ··· 320 316 } 321 317 } 322 318 if (rndis && !dev->status) { 323 - dev_dbg(&intf->dev, "missing RNDIS status endpoint\n"); 324 - usb_set_intfdata(info->data, NULL); 325 - usb_driver_release_interface(driver, info->data); 326 - return -ENODEV; 319 + dev_err(&intf->dev, "missing RNDIS status endpoint\n"); 320 + status = -ENODEV; 321 + goto bail_out_and_release; 327 322 } 328 323 329 324 /* override ethtool_ops */ ··· 330 327 331 328 return 0; 332 329 330 + bail_out_and_release: 331 + usb_set_intfdata(info->data, NULL); 332 + if (info->data != info->control) 333 + usb_driver_release_interface(driver, info->data); 333 334 bad_desc: 334 - dev_info(&dev->udev->dev, "bad CDC descriptors\n"); 335 - return -ENODEV; 335 + return status; 336 336 } 337 337 EXPORT_SYMBOL_GPL(usbnet_generic_cdc_bind); 338 338