FreeBSD Bugzilla – Attachment 205385 Details for
Bug 237083
[ubt] Init fails on Intel Wireless 8260/8265 (Thinkpad t480s and others)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
firmware downloader - kernel part (blocks ng_ubt attachment if firmware is not in operational state)
iwmbt-kernel.diff (text/plain), 8.57 KB, created by
Vladimir Kondratyev
on 2019-06-27 22:04:32 UTC
(
hide
)
Description:
firmware downloader - kernel part (blocks ng_ubt attachment if firmware is not in operational state)
Filename:
MIME Type:
Creator:
Vladimir Kondratyev
Created:
2019-06-27 22:04:32 UTC
Size:
8.57 KB
patch
obsolete
>commit a76943cad8fa07bc4801c71e6a9209c4d4b5e96b >Author: Vladimir Kondratyev <vladimir@kondratyev.su> >Date: Sun Apr 7 02:20:06 2019 +0300 > > ng_ubt(4): do not attach Intel Wireless 8260/8265 in bootloader mode. > > Add helper function for synchronous execution of HCI commands at probe > stage and use this function to check firmware state of Intel Wireless > 8260/8265 bluetooth devices found in many post 2016 year laptops. > > Attempt to initialize FreeBSD bluetooth stack while such a device is in > bootloader mode locks the adapter hardly so it requires power on/off > cycle to restore. > > This change blocks ng_ubt attachment unless operational firmware is > loaded thus preventing the lock up. > >diff --git a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c >index 368fd501eebd..19cf074c413e 100644 >--- a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c >+++ b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c >@@ -252,6 +252,7 @@ static struct ng_type typestruct = > ****************************************************************************/ > > /* USB methods */ >+static usb_callback_t ubt_probe_intr_callback; > static usb_callback_t ubt_ctrl_write_callback; > static usb_callback_t ubt_intr_read_callback; > static usb_callback_t ubt_bulk_read_callback; >@@ -421,6 +422,13 @@ static const STRUCT_USB_HOST_ID ubt_ignore_devs[] = > /* Atheros AR5BBU12 with sflash firmware */ > { USB_VPI(0x0489, 0xe03c, 0), USB_DEV_BCD_LTEQ(1) }, > { USB_VPI(0x0489, 0xe036, 0), USB_DEV_BCD_LTEQ(1) }, >+ >+ /* Intel Wireless 8260/8265 and successors */ >+ { USB_VPI(USB_VENDOR_INTEL2, 0x0a2b, UBT_INTEL8265) }, >+ { USB_VPI(USB_VENDOR_INTEL2, 0x0aaa, UBT_INTEL8265) }, >+ { USB_VPI(USB_VENDOR_INTEL2, 0x0025, UBT_INTEL8265) }, >+ { USB_VPI(USB_VENDOR_INTEL2, 0x0026, UBT_INTEL8265) }, >+ { USB_VPI(USB_VENDOR_INTEL2, 0x0029, UBT_INTEL8265) }, > }; > > /* List of supported bluetooth devices */ >@@ -502,6 +510,114 @@ static const STRUCT_USB_HOST_ID ubt_devs[] = > { USB_VPI(USB_VENDOR_DELL, 0x8197, 0) }, > }; > >+/* >+ * Does a synchronous (waits for completion event) execution of HCI command. >+ * Size of both command and response buffers are passed in length field of >+ * corresponding structures in "Parameter Total Length" format i.e. >+ * not including HCI packet headers. >+ * >+ * Must not be used after USB transfers have been configured in attach routine. >+ */ >+ >+static usb_error_t >+ubt_do_hci_request(struct usb_device *udev, struct ubt_hci_cmd *cmd, >+ void *evt, usb_timeout_t timeout) >+{ >+ static const struct usb_config ubt_probe_config = { >+ .type = UE_INTERRUPT, >+ .endpoint = UE_ADDR_ANY, >+ .direction = UE_DIR_IN, >+ .flags = { .pipe_bof = 1, .short_xfer_ok = 1 }, >+ .bufsize = UBT_INTR_BUFFER_SIZE, >+ .callback = &ubt_probe_intr_callback, >+ }; >+ struct usb_device_request req; >+ struct usb_xfer *xfer[1]; >+ struct mtx mtx; >+ usb_error_t error = USB_ERR_NORMAL_COMPLETION; >+ uint8_t iface_index = 0; >+ >+ /* Initialize a USB control request and then do it */ >+ bzero(&req, sizeof(req)); >+ req.bmRequestType = UBT_HCI_REQUEST; >+ req.wIndex[0] = iface_index; >+ USETW(req.wLength, UBT_HCI_CMD_SIZE(cmd)); >+ >+ error = usbd_do_request(udev, NULL, &req, cmd); >+ if (error != USB_ERR_NORMAL_COMPLETION) { >+ printf("ng_ubt: usbd_do_request error=%s\n", >+ usbd_errstr(error)); >+ return (error); >+ } >+ >+ if (evt == NULL) >+ return (USB_ERR_NORMAL_COMPLETION); >+ >+ /* Initialize INTR endpoint xfer and wait for response */ >+ mtx_init(&mtx, "ubt pb", NULL, MTX_DEF); >+ >+ error = usbd_transfer_setup(udev, &iface_index, xfer, >+ &ubt_probe_config, 1, evt, &mtx); >+ if (error == USB_ERR_NORMAL_COMPLETION) { >+ >+ mtx_lock(&mtx); >+ usbd_transfer_start(*xfer); >+ >+ if (msleep_sbt(evt, &mtx, 0, "ubt pb", SBT_1MS * timeout, >+ 0, C_HARDCLOCK) == EWOULDBLOCK) { >+ printf("ng_ubt: HCI command 0x%04x timed out\n", >+ le16toh(cmd->opcode)); >+ error = USB_ERR_TIMEOUT; >+ } >+ >+ usbd_transfer_stop(*xfer); >+ mtx_unlock(&mtx); >+ >+ usbd_transfer_unsetup(xfer, 1); >+ } else >+ printf("ng_ubt: usbd_transfer_setup error=%s\n", >+ usbd_errstr(error)); >+ >+ mtx_destroy(&mtx); >+ >+ return (error); >+} >+ >+/* >+ * Find if the Intel Wireless 8260/8265 device is in bootloader mode or is >+ * running operational firmware with checking of 7-th byte "Intel version" >+ * HCI command response. The value 0x23 identifies the operational firmware. >+ * Attempt to initialize bluetooth stack while device is in bootloader mode >+ * (7-th byte is 0x06) locks the adapter hardly and requires power on/off >+ * cycle to restore. >+ */ >+ >+static bool >+ubt_check_intel8265_firmware_state(struct usb_device *udev) >+{ >+#define UBT_INTEL_VER_LEN 13 >+#define UBT_INTEL_HCICMD_TIMEOUT 2000 /* ms */ >+ struct ubt_hci_event_command_compl *evt; >+ uint8_t buf[offsetof(struct ubt_hci_event, data) + UBT_INTEL_VER_LEN]; >+ static struct ubt_hci_cmd cmd = { >+ .opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_VENDOR, 0x05)), >+ .length = 0, >+ }; >+ usb_error_t error; >+ >+ bzero(buf, sizeof(buf)); >+ evt = (struct ubt_hci_event_command_compl *)buf; >+ evt->header.length = UBT_INTEL_VER_LEN; >+ >+ error = ubt_do_hci_request(udev, &cmd, evt, UBT_INTEL_HCICMD_TIMEOUT); >+ if (error != USB_ERR_NORMAL_COMPLETION) >+ return false; >+ >+ return (evt->header.event == NG_HCI_EVENT_COMMAND_COMPL && >+ evt->header.length == UBT_INTEL_VER_LEN && >+ evt->data[4] == 0x23); >+} >+ > /* > * Probe for a USB Bluetooth device. > * USB context. >@@ -520,8 +636,13 @@ ubt_probe(device_t dev) > return (ENXIO); > > if (usbd_lookup_id_by_uaa(ubt_ignore_devs, >- sizeof(ubt_ignore_devs), uaa) == 0) >- return (ENXIO); >+ sizeof(ubt_ignore_devs), uaa) == 0) { >+ if ((USB_GET_DRIVER_INFO(uaa) & UBT_INTEL8265) != 0) { >+ if (!ubt_check_intel8265_firmware_state(uaa->device)) >+ return (ENXIO); >+ } else >+ return (ENXIO); >+ } > > error = usbd_lookup_id_by_uaa(ubt_devs, sizeof(ubt_devs), uaa); > if (error == 0) >@@ -717,6 +838,49 @@ ubt_detach(device_t dev) > return (0); > } /* ubt_detach */ > >+/* >+ * Called when incoming interrupt transfer (HCI event) has completed, i.e. >+ * HCI event was received from the device during device probe stage. >+ * USB context. >+ */ >+ >+static void >+ubt_probe_intr_callback(struct usb_xfer *xfer, usb_error_t error) >+{ >+ struct ubt_hci_event *evt = usbd_xfer_softc(xfer); >+ struct usb_page_cache *pc; >+ int actlen; >+ >+ usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); >+ >+ switch (USB_GET_STATE(xfer)) { >+ case USB_ST_TRANSFERRED: >+ if (actlen > UBT_HCI_EVENT_SIZE(evt)) >+ actlen = UBT_HCI_EVENT_SIZE(evt); >+ pc = usbd_xfer_get_frame(xfer, 0); >+ usbd_copy_out(pc, 0, evt, actlen); >+ /* OneShot mode */ >+ wakeup(evt); >+ break; >+ >+ case USB_ST_SETUP: >+submit_next: >+ usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); >+ usbd_transfer_submit(xfer); >+ break; >+ >+ default: >+ if (error != USB_ERR_CANCELLED) { >+ printf("ng_ubt: interrupt transfer failed: %s\n", >+ usbd_errstr(error)); >+ /* Try clear stall first */ >+ usbd_xfer_set_stall(xfer); >+ goto submit_next; >+ } >+ break; >+ } >+} /* ubt_probe_intr_callback */ >+ > /* > * Called when outgoing control request (HCI command) has completed, i.e. > * HCI command was sent to the device. >diff --git a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_var.h b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_var.h >index 55f30d086392..78267d1ddd1c 100644 >--- a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_var.h >+++ b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_var.h >@@ -57,6 +57,9 @@ do { \ > #define UBT_DEFAULT_QLEN 64 > #define UBT_ISOC_NFRAMES 32 /* should be factor of 8 */ > >+/* USB driver info flags */ >+#define UBT_INTEL8265 (1 << 0) >+ > /* Bluetooth USB defines */ > enum { > /* Interface #0 transfers */ >@@ -74,6 +77,35 @@ enum { > UBT_N_TRANSFER, /* total number of transfers */ > }; > >+/* USB control request (HCI command) structure */ >+struct ubt_hci_cmd { >+ uint16_t opcode; >+ uint8_t length; >+ uint8_t data[]; >+} __attribute__ ((packed)); >+#define UBT_HCI_CMD_SIZE(cmd) \ >+ ((cmd)->length + offsetof(struct ubt_hci_cmd, data)) >+ >+/* USB interrupt transfer HCI event header structure */ >+struct ubt_hci_evhdr { >+ uint8_t event; >+ uint8_t length; >+} __attribute__ ((packed)); >+/* USB interrupt transfer (generic HCI event) structure */ >+struct ubt_hci_event { >+ struct ubt_hci_evhdr header; >+ uint8_t data[]; >+} __attribute__ ((packed)); >+/* USB interrupt transfer (HCI command completion event) structure */ >+struct ubt_hci_event_command_compl { >+ struct ubt_hci_evhdr header; >+ uint8_t numpkt; >+ uint16_t opcode; >+ uint8_t data[]; >+} __attribute__ ((packed)); >+#define UBT_HCI_EVENT_SIZE(evt) \ >+ ((evt)->header.length + offsetof(struct ubt_hci_event, data)) >+ > /* USB device softc structure */ > struct ubt_softc { > device_t sc_dev; /* for debug printf */
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 237083
:
204303
| 205385 |
205386
|
205387
|
205388
|
206565
|
206566