From: Greg Kroah-Hartman Date: Tue, 27 Oct 2020 13:41:31 +0000 (+0100) Subject: 4.14-stable patches X-Git-Tag: v4.4.241~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6e4f4788dfcab91979ef022ec85629682caeb819;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: eeprom-at25-set-minimum-read-write-access-stride-to-1.patch tty-serial-fsl_lpuart-fix-lpuart32_poll_get_char.patch usb-cdc-acm-add-quirk-to-blacklist-etas-es58x-devices.patch usb-cdc-wdm-make-wdm_flush-interruptible-and-add-wdm_fsync.patch --- diff --git a/queue-4.14/eeprom-at25-set-minimum-read-write-access-stride-to-1.patch b/queue-4.14/eeprom-at25-set-minimum-read-write-access-stride-to-1.patch new file mode 100644 index 00000000000..62bf47ef869 --- /dev/null +++ b/queue-4.14/eeprom-at25-set-minimum-read-write-access-stride-to-1.patch @@ -0,0 +1,31 @@ +From 284f52ac1c6cfa1b2e5c11b84653dd90e4e91de7 Mon Sep 17 00:00:00 2001 +From: Christian Eggers +Date: Tue, 28 Jul 2020 11:29:59 +0200 +Subject: eeprom: at25: set minimum read/write access stride to 1 + +From: Christian Eggers + +commit 284f52ac1c6cfa1b2e5c11b84653dd90e4e91de7 upstream. + +SPI eeproms are addressed by byte. + +Signed-off-by: Christian Eggers +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20200728092959.24600-1-ceggers@arri.de +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/misc/eeprom/at25.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/misc/eeprom/at25.c ++++ b/drivers/misc/eeprom/at25.c +@@ -355,7 +355,7 @@ static int at25_probe(struct spi_device + at25->nvmem_config.reg_read = at25_ee_read; + at25->nvmem_config.reg_write = at25_ee_write; + at25->nvmem_config.priv = at25; +- at25->nvmem_config.stride = 4; ++ at25->nvmem_config.stride = 1; + at25->nvmem_config.word_size = 1; + at25->nvmem_config.size = chip.byte_len; + diff --git a/queue-4.14/series b/queue-4.14/series index 5b76bad0092..dcd8ab42c40 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -184,3 +184,7 @@ usb-core-solve-race-condition-in-anchor-cleanup-func.patch scsi-ufs-ufs-qcom-fix-race-conditions-caused-by-ufs_.patch ath10k-check-idx-validity-in-__ath10k_htt_rx_ring_fi.patch net-korina-cast-kseg0-address-to-pointer-in-kfree.patch +tty-serial-fsl_lpuart-fix-lpuart32_poll_get_char.patch +usb-cdc-acm-add-quirk-to-blacklist-etas-es58x-devices.patch +usb-cdc-wdm-make-wdm_flush-interruptible-and-add-wdm_fsync.patch +eeprom-at25-set-minimum-read-write-access-stride-to-1.patch diff --git a/queue-4.14/tty-serial-fsl_lpuart-fix-lpuart32_poll_get_char.patch b/queue-4.14/tty-serial-fsl_lpuart-fix-lpuart32_poll_get_char.patch new file mode 100644 index 00000000000..75d376d860a --- /dev/null +++ b/queue-4.14/tty-serial-fsl_lpuart-fix-lpuart32_poll_get_char.patch @@ -0,0 +1,35 @@ +From 29788ab1d2bf26c130de8f44f9553ee78a27e8d5 Mon Sep 17 00:00:00 2001 +From: Peng Fan +Date: Tue, 29 Sep 2020 17:55:09 +0800 +Subject: tty: serial: fsl_lpuart: fix lpuart32_poll_get_char + +From: Peng Fan + +commit 29788ab1d2bf26c130de8f44f9553ee78a27e8d5 upstream. + +The watermark is set to 1, so we need to input two chars to trigger RDRF +using the original logic. With the new logic, we could always get the +char when there is data in FIFO. + +Suggested-by: Fugang Duan +Signed-off-by: Peng Fan +Link: https://lore.kernel.org/r/20200929095509.21680-1-peng.fan@nxp.com +Cc: stable +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/serial/fsl_lpuart.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/tty/serial/fsl_lpuart.c ++++ b/drivers/tty/serial/fsl_lpuart.c +@@ -567,7 +567,7 @@ static void lpuart32_poll_put_char(struc + + static int lpuart32_poll_get_char(struct uart_port *port) + { +- if (!(lpuart32_read(port, UARTSTAT) & UARTSTAT_RDRF)) ++ if (!(lpuart32_read(port, UARTWATER) >> UARTWATER_RXCNT_OFF)) + return NO_POLL_CHAR; + + return lpuart32_read(port, UARTDATA); diff --git a/queue-4.14/usb-cdc-acm-add-quirk-to-blacklist-etas-es58x-devices.patch b/queue-4.14/usb-cdc-acm-add-quirk-to-blacklist-etas-es58x-devices.patch new file mode 100644 index 00000000000..3de892c6b92 --- /dev/null +++ b/queue-4.14/usb-cdc-acm-add-quirk-to-blacklist-etas-es58x-devices.patch @@ -0,0 +1,340 @@ +From a4f88430af896bf34ec25a7a5f0e053fb3d928e0 Mon Sep 17 00:00:00 2001 +From: Vincent Mailhol +Date: Sat, 3 Oct 2020 00:41:51 +0900 +Subject: usb: cdc-acm: add quirk to blacklist ETAS ES58X devices + +From: Vincent Mailhol + +commit a4f88430af896bf34ec25a7a5f0e053fb3d928e0 upstream. + +The ES58X devices has a CDC ACM interface (used for debug +purpose). During probing, the device is thus recognized as USB Modem +(CDC ACM), preventing the etas-es58x module to load: + usbcore: registered new interface driver etas_es58x + usb 1-1.1: new full-speed USB device number 14 using xhci_hcd + usb 1-1.1: New USB device found, idVendor=108c, idProduct=0159, bcdDevice= 1.00 + usb 1-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3 + usb 1-1.1: Product: ES581.4 + usb 1-1.1: Manufacturer: ETAS GmbH + usb 1-1.1: SerialNumber: 2204355 + cdc_acm 1-1.1:1.0: No union descriptor, testing for castrated device + cdc_acm 1-1.1:1.0: ttyACM0: USB ACM device + +Thus, these have been added to the ignore list in +drivers/usb/class/cdc-acm.c + +N.B. Future firmware release of the ES58X will remove the CDC-ACM +interface. + +`lsusb -v` of the three devices variant (ES581.4, ES582.1 and +ES584.1): + + Bus 001 Device 011: ID 108c:0159 Robert Bosch GmbH ES581.4 + Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.10 + bDeviceClass 2 Communications + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x108c Robert Bosch GmbH + idProduct 0x0159 + bcdDevice 1.00 + iManufacturer 1 ETAS GmbH + iProduct 2 ES581.4 + iSerial 3 2204355 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 0x0035 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 5 Bus Powered Configuration + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 3 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 0 + iInterface 4 ACM Control Interface + CDC Header: + bcdCDC 1.10 + CDC Call Management: + bmCapabilities 0x01 + call management + bDataInterface 0 + CDC ACM: + bmCapabilities 0x06 + sends break + line coding and serial state + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 10 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 0 + Device Status: 0x0000 + (Bus Powered) + + Bus 001 Device 012: ID 108c:0168 Robert Bosch GmbH ES582 + Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 2 Communications + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x108c Robert Bosch GmbH + idProduct 0x0168 + bcdDevice 1.00 + iManufacturer 1 ETAS GmbH + iProduct 2 ES582 + iSerial 3 0108933 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 0x0043 + bNumInterfaces 2 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 500mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 0 + CDC Header: + bcdCDC 1.10 + CDC ACM: + bmCapabilities 0x02 + line coding and serial state + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + CDC Call Management: + bmCapabilities 0x03 + call management + use DataInterface + bDataInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 16 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 0 + Device Qualifier (for other device speed): + bLength 10 + bDescriptorType 6 + bcdUSB 2.00 + bDeviceClass 2 Communications + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + bNumConfigurations 1 + Device Status: 0x0000 + (Bus Powered) + + Bus 001 Device 013: ID 108c:0169 Robert Bosch GmbH ES584.1 + Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 2 Communications + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x108c Robert Bosch GmbH + idProduct 0x0169 + bcdDevice 1.00 + iManufacturer 1 ETAS GmbH + iProduct 2 ES584.1 + iSerial 3 0100320 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 0x0043 + bNumInterfaces 2 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 500mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 0 + CDC Header: + bcdCDC 1.10 + CDC ACM: + bmCapabilities 0x02 + line coding and serial state + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + CDC Call Management: + bmCapabilities 0x03 + call management + use DataInterface + bDataInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 16 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 0 + Device Qualifier (for other device speed): + bLength 10 + bDescriptorType 6 + bcdUSB 2.00 + bDeviceClass 2 Communications + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + bNumConfigurations 1 + Device Status: 0x0000 + (Bus Powered) + +Signed-off-by: Vincent Mailhol +Cc: stable +Link: https://lore.kernel.org/r/20201002154219.4887-8-mailhol.vincent@wanadoo.fr +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/class/cdc-acm.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -1957,6 +1957,17 @@ static const struct usb_device_id acm_id + .driver_info = IGNORE_DEVICE, + }, + ++ /* Exclude ETAS ES58x */ ++ { USB_DEVICE(0x108c, 0x0159), /* ES581.4 */ ++ .driver_info = IGNORE_DEVICE, ++ }, ++ { USB_DEVICE(0x108c, 0x0168), /* ES582.1 */ ++ .driver_info = IGNORE_DEVICE, ++ }, ++ { USB_DEVICE(0x108c, 0x0169), /* ES584.1 */ ++ .driver_info = IGNORE_DEVICE, ++ }, ++ + { USB_DEVICE(0x1bc7, 0x0021), /* Telit 3G ACM only composition */ + .driver_info = SEND_ZERO_PACKET, + }, diff --git a/queue-4.14/usb-cdc-wdm-make-wdm_flush-interruptible-and-add-wdm_fsync.patch b/queue-4.14/usb-cdc-wdm-make-wdm_flush-interruptible-and-add-wdm_fsync.patch new file mode 100644 index 00000000000..d1f0ec58b1c --- /dev/null +++ b/queue-4.14/usb-cdc-wdm-make-wdm_flush-interruptible-and-add-wdm_fsync.patch @@ -0,0 +1,184 @@ +From 37d2a36394d954413a495da61da1b2a51ecd28ab Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Mon, 28 Sep 2020 23:17:55 +0900 +Subject: USB: cdc-wdm: Make wdm_flush() interruptible and add wdm_fsync(). + +From: Oliver Neukum + +commit 37d2a36394d954413a495da61da1b2a51ecd28ab upstream. + +syzbot is reporting hung task at wdm_flush() [1], for there is a circular +dependency that wdm_flush() from flip_close() for /dev/cdc-wdm0 forever +waits for /dev/raw-gadget to be closed while close() for /dev/raw-gadget +cannot be called unless close() for /dev/cdc-wdm0 completes. + +Tetsuo Handa considered that such circular dependency is an usage error [2] +which corresponds to an unresponding broken hardware [3]. But Alan Stern +responded that we should be prepared for such hardware [4]. Therefore, +this patch changes wdm_flush() to use wait_event_interruptible_timeout() +which gives up after 30 seconds, for hardware that remains silent must be +ignored. The 30 seconds are coming out of thin air. + +Changing wait_event() to wait_event_interruptible_timeout() makes error +reporting from close() syscall less reliable. To compensate it, this patch +also implements wdm_fsync() which does not use timeout. Those who want to +be very sure that data has gone out to the device are now advised to call +fsync(), with a caveat that fsync() can return -EINVAL when running on +older kernels which do not implement wdm_fsync(). + +This patch also fixes three more problems (listed below) found during +exhaustive discussion and testing. + + Since multiple threads can concurrently call wdm_write()/wdm_flush(), + we need to use wake_up_all() whenever clearing WDM_IN_USE in order to + make sure that all waiters are woken up. Also, error reporting needs + to use fetch-and-clear approach in order not to report same error for + multiple times. + + Since wdm_flush() checks WDM_DISCONNECTING, wdm_write() should as well + check WDM_DISCONNECTING. + + In wdm_flush(), since locks are not held, it is not safe to dereference + desc->intf after checking that WDM_DISCONNECTING is not set [5]. Thus, + remove dev_err() from wdm_flush(). + +[1] https://syzkaller.appspot.com/bug?id=e7b761593b23eb50855b9ea31e3be5472b711186 +[2] https://lkml.kernel.org/r/27b7545e-8f41-10b8-7c02-e35a08eb1611@i-love.sakura.ne.jp +[3] https://lkml.kernel.org/r/79ba410f-e0ef-2465-b94f-6b9a4a82adf5@i-love.sakura.ne.jp +[4] https://lkml.kernel.org/r/20200530011040.GB12419@rowland.harvard.edu +[5] https://lkml.kernel.org/r/c85331fc-874c-6e46-a77f-0ef1dc075308@i-love.sakura.ne.jp + +Reported-by: syzbot +Cc: stable +Co-developed-by: Tetsuo Handa +Signed-off-by: Tetsuo Handa +Signed-off-by: Oliver Neukum +Cc: Alan Stern +Link: https://lore.kernel.org/r/20200928141755.3476-1-penguin-kernel@I-love.SAKURA.ne.jp +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/class/cdc-wdm.c | 70 +++++++++++++++++++++++++++++++++----------- + 1 file changed, 54 insertions(+), 16 deletions(-) + +--- a/drivers/usb/class/cdc-wdm.c ++++ b/drivers/usb/class/cdc-wdm.c +@@ -57,6 +57,9 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); + + #define WDM_MAX 16 + ++/* we cannot wait forever at flush() */ ++#define WDM_FLUSH_TIMEOUT (30 * HZ) ++ + /* CDC-WMC r1.1 requires wMaxCommand to be "at least 256 decimal (0x100)" */ + #define WDM_DEFAULT_BUFSIZE 256 + +@@ -147,7 +150,7 @@ static void wdm_out_callback(struct urb + kfree(desc->outbuf); + desc->outbuf = NULL; + clear_bit(WDM_IN_USE, &desc->flags); +- wake_up(&desc->wait); ++ wake_up_all(&desc->wait); + } + + /* forward declaration */ +@@ -390,6 +393,9 @@ static ssize_t wdm_write + if (test_bit(WDM_RESETTING, &desc->flags)) + r = -EIO; + ++ if (test_bit(WDM_DISCONNECTING, &desc->flags)) ++ r = -ENODEV; ++ + if (r < 0) { + rv = r; + goto out_free_mem_pm; +@@ -421,6 +427,7 @@ static ssize_t wdm_write + if (rv < 0) { + desc->outbuf = NULL; + clear_bit(WDM_IN_USE, &desc->flags); ++ wake_up_all(&desc->wait); /* for wdm_wait_for_response() */ + dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv); + rv = usb_translate_errors(rv); + goto out_free_mem_pm; +@@ -580,28 +587,58 @@ err: + return rv; + } + +-static int wdm_flush(struct file *file, fl_owner_t id) ++static int wdm_wait_for_response(struct file *file, long timeout) + { + struct wdm_device *desc = file->private_data; ++ long rv; /* Use long here because (int) MAX_SCHEDULE_TIMEOUT < 0. */ + +- wait_event(desc->wait, +- /* +- * needs both flags. We cannot do with one +- * because resetting it would cause a race +- * with write() yet we need to signal +- * a disconnect +- */ +- !test_bit(WDM_IN_USE, &desc->flags) || +- test_bit(WDM_DISCONNECTING, &desc->flags)); ++ /* ++ * Needs both flags. We cannot do with one because resetting it would ++ * cause a race with write() yet we need to signal a disconnect. ++ */ ++ rv = wait_event_interruptible_timeout(desc->wait, ++ !test_bit(WDM_IN_USE, &desc->flags) || ++ test_bit(WDM_DISCONNECTING, &desc->flags), ++ timeout); + +- /* cannot dereference desc->intf if WDM_DISCONNECTING */ ++ /* ++ * To report the correct error. This is best effort. ++ * We are inevitably racing with the hardware. ++ */ + if (test_bit(WDM_DISCONNECTING, &desc->flags)) + return -ENODEV; +- if (desc->werr < 0) +- dev_err(&desc->intf->dev, "Error in flush path: %d\n", +- desc->werr); ++ if (!rv) ++ return -EIO; ++ if (rv < 0) ++ return -EINTR; ++ ++ spin_lock_irq(&desc->iuspin); ++ rv = desc->werr; ++ desc->werr = 0; ++ spin_unlock_irq(&desc->iuspin); ++ ++ return usb_translate_errors(rv); ++ ++} + +- return usb_translate_errors(desc->werr); ++/* ++ * You need to send a signal when you react to malicious or defective hardware. ++ * Also, don't abort when fsync() returned -EINVAL, for older kernels which do ++ * not implement wdm_flush() will return -EINVAL. ++ */ ++static int wdm_fsync(struct file *file, loff_t start, loff_t end, int datasync) ++{ ++ return wdm_wait_for_response(file, MAX_SCHEDULE_TIMEOUT); ++} ++ ++/* ++ * Same with wdm_fsync(), except it uses finite timeout in order to react to ++ * malicious or defective hardware which ceased communication after close() was ++ * implicitly called due to process termination. ++ */ ++static int wdm_flush(struct file *file, fl_owner_t id) ++{ ++ return wdm_wait_for_response(file, WDM_FLUSH_TIMEOUT); + } + + static unsigned int wdm_poll(struct file *file, struct poll_table_struct *wait) +@@ -726,6 +763,7 @@ static const struct file_operations wdm_ + .owner = THIS_MODULE, + .read = wdm_read, + .write = wdm_write, ++ .fsync = wdm_fsync, + .open = wdm_open, + .flush = wdm_flush, + .release = wdm_release,