quirks.c 15.0 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0
2 3 4 5 6 7 8
/*
 * USB device quirk handling logic and table
 *
 * Copyright (c) 2007 Oliver Neukum
 * Copyright (c) 2007 Greg Kroah-Hartman <gregkh@suse.de>
 */

9
#include <linux/moduleparam.h>
10 11
#include <linux/usb.h>
#include <linux/usb/quirks.h>
12
#include <linux/usb/hcd.h>
13 14
#include "usb.h"

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
struct quirk_entry {
	u16 vid;
	u16 pid;
	u32 flags;
};

static DEFINE_MUTEX(quirk_mutex);

static struct quirk_entry *quirk_list;
static unsigned int quirk_count;

static char quirks_param[128];

static int quirks_param_set(const char *val, const struct kernel_param *kp)
{
	char *p, *field;
	u16 vid, pid;
	u32 flags;
	size_t i;
34 35 36 37 38
	int err;

	err = param_set_copystring(val, kp);
	if (err)
		return err;
39 40 41

	mutex_lock(&quirk_mutex);

42
	if (!*val) {
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
		quirk_count = 0;
		kfree(quirk_list);
		quirk_list = NULL;
		goto unlock;
	}

	for (quirk_count = 1, i = 0; val[i]; i++)
		if (val[i] == ',')
			quirk_count++;

	if (quirk_list) {
		kfree(quirk_list);
		quirk_list = NULL;
	}

	quirk_list = kcalloc(quirk_count, sizeof(struct quirk_entry),
			     GFP_KERNEL);
	if (!quirk_list) {
		mutex_unlock(&quirk_mutex);
		return -ENOMEM;
	}

	for (i = 0, p = (char *)val; p && *p;) {
		/* Each entry consists of VID:PID:flags */
		field = strsep(&p, ":");
		if (!field)
			break;

		if (kstrtou16(field, 16, &vid))
			break;

		field = strsep(&p, ":");
		if (!field)
			break;

		if (kstrtou16(field, 16, &pid))
			break;

		field = strsep(&p, ",");
		if (!field || !*field)
			break;

		/* Collect the flags */
		for (flags = 0; *field; field++) {
			switch (*field) {
			case 'a':
				flags |= USB_QUIRK_STRING_FETCH_255;
				break;
			case 'b':
				flags |= USB_QUIRK_RESET_RESUME;
				break;
			case 'c':
				flags |= USB_QUIRK_NO_SET_INTF;
				break;
			case 'd':
				flags |= USB_QUIRK_CONFIG_INTF_STRINGS;
				break;
			case 'e':
				flags |= USB_QUIRK_RESET;
				break;
			case 'f':
				flags |= USB_QUIRK_HONOR_BNUMINTERFACES;
				break;
			case 'g':
				flags |= USB_QUIRK_DELAY_INIT;
				break;
			case 'h':
				flags |= USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL;
				break;
			case 'i':
				flags |= USB_QUIRK_DEVICE_QUALIFIER;
				break;
			case 'j':
				flags |= USB_QUIRK_IGNORE_REMOTE_WAKEUP;
				break;
			case 'k':
				flags |= USB_QUIRK_NO_LPM;
				break;
			case 'l':
				flags |= USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL;
				break;
			case 'm':
				flags |= USB_QUIRK_DISCONNECT_SUSPEND;
				break;
			/* Ignore unrecognized flag characters */
			}
		}

		quirk_list[i++] = (struct quirk_entry)
			{ .vid = vid, .pid = pid, .flags = flags };
	}

	if (i < quirk_count)
		quirk_count = i;

unlock:
	mutex_unlock(&quirk_mutex);

141
	return 0;
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
}

static const struct kernel_param_ops quirks_param_ops = {
	.set = quirks_param_set,
	.get = param_get_string,
};

static struct kparam_string quirks_param_string = {
	.maxlen = sizeof(quirks_param),
	.string = quirks_param,
};

module_param_cb(quirks, &quirks_param_ops, &quirks_param_string, 0644);
MODULE_PARM_DESC(quirks, "Add/modify USB quirks by specifying quirks=vendorID:productID:quirks");

157 158 159 160 161 162 163 164 165 166 167 168 169
/* Lists of quirky USB devices, split in device quirks and interface quirks.
 * Device quirks are applied at the very beginning of the enumeration process,
 * right after reading the device descriptor. They can thus only match on device
 * information.
 *
 * Interface quirks are applied after reading all the configuration descriptors.
 * They can match on both device and interface information.
 *
 * Note that the DELAY_INIT and HONOR_BNUMINTERFACES quirks do not make sense as
 * interface quirks, as they only influence the enumeration process which is run
 * before processing the interface quirks.
 *
 * Please keep the lists ordered by:
170 171 172 173 174
 * 	1) Vendor ID
 * 	2) Product ID
 * 	3) Class ID
 */
static const struct usb_device_id usb_quirk_list[] = {
O
Oliver Neukum 已提交
175 176
	/* CBM - Flash disk */
	{ USB_DEVICE(0x0204, 0x6025), .driver_info = USB_QUIRK_RESET_RESUME },
A
Alan Stern 已提交
177

178 179 180 181
	/* WORLDE easy key (easykey.25) MIDI controller  */
	{ USB_DEVICE(0x0218, 0x0401), .driver_info =
			USB_QUIRK_CONFIG_INTF_STRINGS },

182
	/* HP 5300/5370C scanner */
A
Alan Stern 已提交
183 184
	{ USB_DEVICE(0x03f0, 0x0701), .driver_info =
			USB_QUIRK_STRING_FETCH_255 },
185

186 187 188
	/* Creative SB Audigy 2 NX */
	{ USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME },

H
Hans de Goede 已提交
189 190 191
	/* USB3503 */
	{ USB_DEVICE(0x0424, 0x3503), .driver_info = USB_QUIRK_RESET_RESUME },

192 193 194
	/* Microsoft Wireless Laser Mouse 6000 Receiver */
	{ USB_DEVICE(0x045e, 0x00e1), .driver_info = USB_QUIRK_RESET_RESUME },

195 196 197
	/* Microsoft LifeCam-VX700 v2.0 */
	{ USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME },

198
	/* Logitech HD Pro Webcams C920, C920-C, C925e and C930e */
199
	{ USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT },
200
	{ USB_DEVICE(0x046d, 0x0841), .driver_info = USB_QUIRK_DELAY_INIT },
201
	{ USB_DEVICE(0x046d, 0x0843), .driver_info = USB_QUIRK_DELAY_INIT },
202
	{ USB_DEVICE(0x046d, 0x085b), .driver_info = USB_QUIRK_DELAY_INIT },
203

204 205 206 207 208 209 210
	/* Logitech ConferenceCam CC3000e */
	{ USB_DEVICE(0x046d, 0x0847), .driver_info = USB_QUIRK_DELAY_INIT },
	{ USB_DEVICE(0x046d, 0x0848), .driver_info = USB_QUIRK_DELAY_INIT },

	/* Logitech PTZ Pro Camera */
	{ USB_DEVICE(0x046d, 0x0853), .driver_info = USB_QUIRK_DELAY_INIT },

211 212
	/* Logitech Quickcam Fusion */
	{ USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME },
213

214 215
	/* Logitech Quickcam Orbit MP */
	{ USB_DEVICE(0x046d, 0x08c2), .driver_info = USB_QUIRK_RESET_RESUME },
216

217 218
	/* Logitech Quickcam Pro for Notebook */
	{ USB_DEVICE(0x046d, 0x08c3), .driver_info = USB_QUIRK_RESET_RESUME },
219

220 221
	/* Logitech Quickcam Pro 5000 */
	{ USB_DEVICE(0x046d, 0x08c5), .driver_info = USB_QUIRK_RESET_RESUME },
222

223 224
	/* Logitech Quickcam OEM Dell Notebook */
	{ USB_DEVICE(0x046d, 0x08c6), .driver_info = USB_QUIRK_RESET_RESUME },
225

226 227
	/* Logitech Quickcam OEM Cisco VT Camera II */
	{ USB_DEVICE(0x046d, 0x08c7), .driver_info = USB_QUIRK_RESET_RESUME },
228

229 230 231
	/* Logitech Harmony 700-series */
	{ USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT },

A
Alan Stern 已提交
232 233 234
	/* Philips PSC805 audio device */
	{ USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },

235 236 237 238 239 240
	/* Plantronic Audio 655 DSP */
	{ USB_DEVICE(0x047f, 0xc008), .driver_info = USB_QUIRK_RESET_RESUME },

	/* Plantronic Audio 648 USB */
	{ USB_DEVICE(0x047f, 0xc013), .driver_info = USB_QUIRK_RESET_RESUME },

241 242 243 244
	/* Artisman Watchdog Dongle */
	{ USB_DEVICE(0x04b4, 0x0526), .driver_info =
			USB_QUIRK_CONFIG_INTF_STRINGS },

245 246 247 248
	/* Microchip Joss Optical infrared touchboard device */
	{ USB_DEVICE(0x04d8, 0x000c), .driver_info =
			USB_QUIRK_CONFIG_INTF_STRINGS },

O
Oliver Neukum 已提交
249 250 251 252 253 254
	/* CarrolTouch 4000U */
	{ USB_DEVICE(0x04e7, 0x0009), .driver_info = USB_QUIRK_RESET_RESUME },

	/* CarrolTouch 4500U */
	{ USB_DEVICE(0x04e7, 0x0030), .driver_info = USB_QUIRK_RESET_RESUME },

255 256 257 258
	/* Samsung Android phone modem - ID conflict with SPH-I500 */
	{ USB_DEVICE(0x04e8, 0x6601), .driver_info =
			USB_QUIRK_CONFIG_INTF_STRINGS },

259 260 261 262
	/* Elan Touchscreen */
	{ USB_DEVICE(0x04f3, 0x0089), .driver_info =
			USB_QUIRK_DEVICE_QUALIFIER },

263 264 265
	{ USB_DEVICE(0x04f3, 0x009b), .driver_info =
			USB_QUIRK_DEVICE_QUALIFIER },

266 267 268
	{ USB_DEVICE(0x04f3, 0x010c), .driver_info =
			USB_QUIRK_DEVICE_QUALIFIER },

269 270 271
	{ USB_DEVICE(0x04f3, 0x0125), .driver_info =
			USB_QUIRK_DEVICE_QUALIFIER },

272 273 274
	{ USB_DEVICE(0x04f3, 0x016f), .driver_info =
			USB_QUIRK_DEVICE_QUALIFIER },

275 276 277
	{ USB_DEVICE(0x04f3, 0x0381), .driver_info =
			USB_QUIRK_NO_LPM },

278 279 280
	{ USB_DEVICE(0x04f3, 0x21b8), .driver_info =
			USB_QUIRK_DEVICE_QUALIFIER },

281 282 283 284 285 286
	/* Roland SC-8820 */
	{ USB_DEVICE(0x0582, 0x0007), .driver_info = USB_QUIRK_RESET_RESUME },

	/* Edirol SD-20 */
	{ USB_DEVICE(0x0582, 0x0027), .driver_info = USB_QUIRK_RESET_RESUME },

287 288 289
	/* Alcor Micro Corp. Hub */
	{ USB_DEVICE(0x058f, 0x9254), .driver_info = USB_QUIRK_RESET_RESUME },

290 291 292
	/* appletouch */
	{ USB_DEVICE(0x05ac, 0x021a), .driver_info = USB_QUIRK_RESET_RESUME },

293 294 295
	/* Genesys Logic hub, internally used by KY-688 USB 3.1 Type-C Hub */
	{ USB_DEVICE(0x05e3, 0x0612), .driver_info = USB_QUIRK_NO_LPM },

296 297 298
	/* ELSA MicroLink 56K */
	{ USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_RESET_RESUME },

299 300 301
	/* Genesys Logic hub, internally used by Moshi USB to Ethernet Adapter */
	{ USB_DEVICE(0x05e3, 0x0616), .driver_info = USB_QUIRK_NO_LPM },

R
René Rebe 已提交
302 303 304 305
	/* Avision AV600U */
	{ USB_DEVICE(0x0638, 0x0a13), .driver_info =
	  USB_QUIRK_STRING_FETCH_255 },

306 307 308 309
	/* Saitek Cyborg Gold Joystick */
	{ USB_DEVICE(0x06a3, 0x0006), .driver_info =
			USB_QUIRK_CONFIG_INTF_STRINGS },

310
	/* Guillemot Webcam Hercules Dualpix Exchange (2nd ID) */
311 312
	{ USB_DEVICE(0x06f8, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME },

313 314 315
	/* Guillemot Webcam Hercules Dualpix Exchange*/
	{ USB_DEVICE(0x06f8, 0x3005), .driver_info = USB_QUIRK_RESET_RESUME },

316 317 318
	/* Midiman M-Audio Keystation 88es */
	{ USB_DEVICE(0x0763, 0x0192), .driver_info = USB_QUIRK_RESET_RESUME },

319 320 321
	/* M-Systems Flash Disk Pioneers */
	{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },

322 323 324 325 326 327 328 329
	/* Baum Vario Ultra */
	{ USB_DEVICE(0x0904, 0x6101), .driver_info =
			USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL },
	{ USB_DEVICE(0x0904, 0x6102), .driver_info =
			USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL },
	{ USB_DEVICE(0x0904, 0x6103), .driver_info =
			USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL },

330 331 332 333
	/* Keytouch QWERTY Panel keyboard */
	{ USB_DEVICE(0x0926, 0x3333), .driver_info =
			USB_QUIRK_CONFIG_INTF_STRINGS },

334 335 336
	/* X-Rite/Gretag-Macbeth Eye-One Pro display colorimeter */
	{ USB_DEVICE(0x0971, 0x2000), .driver_info = USB_QUIRK_NO_SET_INTF },

337 338 339
	/* Broadcom BCM92035DGROM BT dongle */
	{ USB_DEVICE(0x0a5c, 0x2021), .driver_info = USB_QUIRK_RESET_RESUME },

340 341 342
	/* MAYA44USB sound device */
	{ USB_DEVICE(0x0a92, 0x0091), .driver_info = USB_QUIRK_RESET_RESUME },

H
Hans de Goede 已提交
343 344 345 346
	/* ASUS Base Station(T100) */
	{ USB_DEVICE(0x0b05, 0x17e0), .driver_info =
			USB_QUIRK_IGNORE_REMOTE_WAKEUP },

A
Alan Stern 已提交
347 348 349
	/* Action Semiconductor flash disk */
	{ USB_DEVICE(0x10d6, 0x2200), .driver_info =
			USB_QUIRK_STRING_FETCH_255 },
350

351 352 353 354 355 356
	/* Huawei 4G LTE module */
	{ USB_DEVICE(0x12d1, 0x15bb), .driver_info =
			USB_QUIRK_DISCONNECT_SUSPEND },
	{ USB_DEVICE(0x12d1, 0x15c3), .driver_info =
			USB_QUIRK_DISCONNECT_SUSPEND },

357 358
	/* SKYMEDI USB_DRIVE */
	{ USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME },
359

J
James P Michels III 已提交
360 361 362 363
	/* Razer - Razer Blade Keyboard */
	{ USB_DEVICE(0x1532, 0x0116), .driver_info =
			USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },

364 365 366 367
	/* BUILDWIN Photo Frame */
	{ USB_DEVICE(0x1908, 0x1315), .driver_info =
			USB_QUIRK_HONOR_BNUMINTERFACES },

M
Macpaul Lin 已提交
368 369 370 371
	/* Protocol and OTG Electrical Test Device */
	{ USB_DEVICE(0x1a0a, 0x0200), .driver_info =
			USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },

372 373 374
	/* Corsair K70 RGB */
	{ USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT },

375
	/* Corsair Strafe RGB */
376 377
	{ USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT |
	  USB_QUIRK_DELAY_CTRL_MSG },
378

379 380 381
	/* Corsair K70 LUX */
	{ USB_DEVICE(0x1b1c, 0x1b36), .driver_info = USB_QUIRK_DELAY_INIT },

382 383 384 385
	/* MIDI keyboard WORLDE MINI */
	{ USB_DEVICE(0x1c75, 0x0204), .driver_info =
			USB_QUIRK_CONFIG_INTF_STRINGS },

386 387 388
	/* Acer C120 LED Projector */
	{ USB_DEVICE(0x1de1, 0xc102), .driver_info = USB_QUIRK_NO_LPM },

389 390 391 392 393 394
	/* Blackmagic Design Intensity Shuttle */
	{ USB_DEVICE(0x1edb, 0xbd3b), .driver_info = USB_QUIRK_NO_LPM },

	/* Blackmagic Design UltraStudio SDI */
	{ USB_DEVICE(0x1edb, 0xbd4f), .driver_info = USB_QUIRK_NO_LPM },

395 396 397 398
	/* Hauppauge HVR-950q */
	{ USB_DEVICE(0x2040, 0x7200), .driver_info =
			USB_QUIRK_CONFIG_INTF_STRINGS },

H
Hans de Goede 已提交
399 400 401
	/* INTEL VALUE SSD */
	{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },

402 403 404
	{ }  /* terminating entry must be last */
};

405
static const struct usb_device_id usb_interface_quirk_list[] = {
406 407 408 409
	/* Logitech UVC Cameras */
	{ USB_VENDOR_AND_INTERFACE_INFO(0x046d, USB_CLASS_VIDEO, 1, 0),
	  .driver_info = USB_QUIRK_RESET_RESUME },

410 411 412
	{ }  /* terminating entry must be last */
};

413 414 415 416 417 418 419 420
static const struct usb_device_id usb_amd_resume_quirk_list[] = {
	/* Lenovo Mouse with Pixart controller */
	{ USB_DEVICE(0x17ef, 0x602e), .driver_info = USB_QUIRK_RESET_RESUME },

	/* Pixart Mouse */
	{ USB_DEVICE(0x093a, 0x2500), .driver_info = USB_QUIRK_RESET_RESUME },
	{ USB_DEVICE(0x093a, 0x2510), .driver_info = USB_QUIRK_RESET_RESUME },
	{ USB_DEVICE(0x093a, 0x2521), .driver_info = USB_QUIRK_RESET_RESUME },
421
	{ USB_DEVICE(0x03f0, 0x2b4a), .driver_info = USB_QUIRK_RESET_RESUME },
422 423 424 425 426 427 428

	/* Logitech Optical Mouse M90/M100 */
	{ USB_DEVICE(0x046d, 0xc05a), .driver_info = USB_QUIRK_RESET_RESUME },

	{ }  /* terminating entry must be last */
};

429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
static bool usb_match_any_interface(struct usb_device *udev,
				    const struct usb_device_id *id)
{
	unsigned int i;

	for (i = 0; i < udev->descriptor.bNumConfigurations; ++i) {
		struct usb_host_config *cfg = &udev->config[i];
		unsigned int j;

		for (j = 0; j < cfg->desc.bNumInterfaces; ++j) {
			struct usb_interface_cache *cache;
			struct usb_host_interface *intf;

			cache = cfg->intf_cache[j];
			if (cache->num_altsetting == 0)
				continue;

			intf = &cache->altsetting[0];
			if (usb_match_one_id_intf(udev, intf, id))
				return true;
		}
	}

	return false;
}

455
static int usb_amd_resume_quirk(struct usb_device *udev)
456 457 458 459 460 461 462 463 464 465 466
{
	struct usb_hcd *hcd;

	hcd = bus_to_hcd(udev->bus);
	/* The device should be attached directly to root hub */
	if (udev->level == 1 && hcd->amd_resume_bug == 1)
		return 1;

	return 0;
}

467 468
static u32 usb_detect_static_quirks(struct usb_device *udev,
				    const struct usb_device_id *id)
469
{
470
	u32 quirks = 0;
471

472 473 474 475 476 477 478 479 480
	for (; id->match_flags; id++) {
		if (!usb_match_device(udev, id))
			continue;

		if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_INFO) &&
		    !usb_match_any_interface(udev, id))
			continue;

		quirks |= (u32)(id->driver_info);
481
	}
482 483

	return quirks;
484 485
}

486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
static u32 usb_detect_dynamic_quirks(struct usb_device *udev)
{
	u16 vid = le16_to_cpu(udev->descriptor.idVendor);
	u16 pid = le16_to_cpu(udev->descriptor.idProduct);
	int i, flags = 0;

	mutex_lock(&quirk_mutex);

	for (i = 0; i < quirk_count; i++) {
		if (vid == quirk_list[i].vid && pid == quirk_list[i].pid) {
			flags = quirk_list[i].flags;
			break;
		}
	}

	mutex_unlock(&quirk_mutex);

	return flags;
}

506 507 508 509 510
/*
 * Detect any quirks the device has, and do any housekeeping for it if needed.
 */
void usb_detect_quirks(struct usb_device *udev)
{
511
	udev->quirks = usb_detect_static_quirks(udev, usb_quirk_list);
512 513 514 515 516 517

	/*
	 * Pixart-based mice would trigger remote wakeup issue on AMD
	 * Yangtze chipset, so set them as RESET_RESUME flag.
	 */
	if (usb_amd_resume_quirk(udev))
518
		udev->quirks |= usb_detect_static_quirks(udev,
519 520
				usb_amd_resume_quirk_list);

521 522
	udev->quirks ^= usb_detect_dynamic_quirks(udev);

523 524
	if (udev->quirks)
		dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
525
			udev->quirks);
526

527 528
#ifdef CONFIG_USB_DEFAULT_PERSIST
	if (!(udev->quirks & USB_QUIRK_RESET))
529 530
		udev->persist_enabled = 1;
#else
531 532
	/* Hubs are automatically enabled for USB-PERSIST */
	if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
533
		udev->persist_enabled = 1;
534
#endif	/* CONFIG_USB_DEFAULT_PERSIST */
535
}
536 537 538 539 540

void usb_detect_interface_quirks(struct usb_device *udev)
{
	u32 quirks;

541
	quirks = usb_detect_static_quirks(udev, usb_interface_quirk_list);
542 543 544 545 546 547 548
	if (quirks == 0)
		return;

	dev_dbg(&udev->dev, "USB interface quirks for this device: %x\n",
		quirks);
	udev->quirks |= quirks;
}
549 550 551 552 553 554 555 556

void usb_release_quirk_list(void)
{
	mutex_lock(&quirk_mutex);
	kfree(quirk_list);
	quirk_list = NULL;
	mutex_unlock(&quirk_mutex);
}