Bluetooth: btmtk: MediaTek ISO data transmission support
Subsystems (2)
v5 cover Bluetooth: btmtk: MediaTek ISO data transmission support
Since SIG has not yet clearly defined the specification for ISO data transmission over USB, MediaTek has adopted a method of adding an additional interrupt endpoint for ISO data transmission. This approach differs from the current method used in the Bluetooth upstream driver, which utilizes existing bulk endpoints. The interrupt endpoint provides guaranteed bandwidth, sufficient maximum data length for ISO packets and error checking.
Driver sets up ISO interface and endpoints in btusb_mtk_setup and clears the setup in btusb_mtk_shutdown. These flow can't move to btmtk.c due to btusb_driver is only defined in btusb.c when claiming/relaesing interface. Once ISO interface is claimed, driver can use specific interrupt endpoint to send and receive iso data. ISO packet anchor stops when driver suspending and resubmit interrupt urb for ISO data when driver resuming.
---
Change v5:
-Add two patch MediaTek submit previusly
-Remove v4,1/4 & v4,3/4 , becasue it's not necessary
-Add patch to move most function from btusb.c to btmtk.c to make btusb.c more simple -refactor MediaTek ISO transmission function and implement in btmtk.c
---
Chris Lu (8):
Bluetooth: btusb: mediatek: remove the unnecessary goto tag
Bluetooth: btusb: mediatek: return error code for failed register access
Bluetooth: btmtk: rename btmediatek_data
Bluetooth: btusb: add callback function in btusb suspend/resume
Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c
Bluetooth: btmtk: move btusb_mtk_[setup, shutdown] to btmtk.c
Bluetooth: btmtk: move btusb_recv_acl_mtk to btmtk.c
Bluetooth: btusb: mediatek: add ISO data transmission functions
drivers/bluetooth/btmtk.c | 1058 ++++++++++++++++++++++++++++++++++++- drivers/bluetooth/btmtk.h | 93 +++- drivers/bluetooth/btusb.c | 751 +++----------------------- 3 files changed, 1218 insertions(+), 684 deletions(-)
Signature · 1 line
2.18.0
PATCH v5 1/8 Bluetooth: btusb: mediatek: remove the unnecessary goto tag
Remove the unnecessary goto tag whether there is an error or not, we have to free the buffer at the end of the function.
--- drivers/bluetooth/btusb.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
drivers/bluetooth/btusb.c +1 -4
@@ -2953,12 +2953,9 @@ static int btusb_mtk_uhw_reg_write(struct btusb_data *data, u32 reg, u32 val)0x5E , reg >>16 , reg &0xffff , buf, 4, USB_CTRL_SET_TIMEOUT); -if (err <0 ) { +if (err <0 )bt_dev_err (hdev,"Failed to write uhw reg(%d)" , err); - goto err_free_buf; - } -err_free_buf:kfree (buf);return err;
Signature · 1 line
2.18.0
PATCH v5 2/8 Bluetooth: btusb: mediatek: return error code for failed register access
In reply to Chris LuUpdate the code to immediately return an error code if accessing a related register fails. This ensures that our desired logic for subsequent register operations is maintained and allows us to promptly catch any unexpected errors.
--- drivers/bluetooth/btusb.c | 114 ++++++++++++++++++++++++++++---------- 1 file changed, 84 insertions(+), 30 deletions(-)
drivers/bluetooth/btusb.c +84 -30
@@ -3037,47 +3037,98 @@ static int btusb_mtk_subsys_reset(struct hci_dev *hdev, u32 dev_id)int err;if (dev_id ==0x7922 ) { -btusb_mtk_uhw_reg_read (data,MTK_BT_SUBSYS_RST , &val); + err =btusb_mtk_uhw_reg_read (data,MTK_BT_SUBSYS_RST , &val); +if (err <0 ) +return err; val |=0x00002020 ; -btusb_mtk_uhw_reg_write (data,MTK_BT_SUBSYS_RST , val); -btusb_mtk_uhw_reg_write (data,MTK_EP_RST_OPT ,0x00010001 ); -btusb_mtk_uhw_reg_read (data,MTK_BT_SUBSYS_RST , &val); + err =btusb_mtk_uhw_reg_write (data,MTK_BT_SUBSYS_RST , val); +if (err <0 ) +return err; + err =btusb_mtk_uhw_reg_write (data,MTK_EP_RST_OPT ,0x00010001 ); +if (err <0 ) +return err; + err =btusb_mtk_uhw_reg_read (data,MTK_BT_SUBSYS_RST , &val); +if (err <0 ) +return err; val |=BIT (0 ); -btusb_mtk_uhw_reg_write (data,MTK_BT_SUBSYS_RST , val); + err =btusb_mtk_uhw_reg_write (data,MTK_BT_SUBSYS_RST , val); +if (err <0 ) +return err;msleep (100 ); }else if (dev_id ==0x7925 ) { -btusb_mtk_uhw_reg_read (data,MTK_BT_RESET_REG_CONNV3 , &val); + err =btusb_mtk_uhw_reg_read (data,MTK_BT_RESET_REG_CONNV3 , &val); +if (err <0 ) +return err; val |= (1 <<5 ); -btusb_mtk_uhw_reg_write (data,MTK_BT_RESET_REG_CONNV3 , val); -btusb_mtk_uhw_reg_read (data,MTK_BT_RESET_REG_CONNV3 , &val); + err =btusb_mtk_uhw_reg_write (data,MTK_BT_RESET_REG_CONNV3 , val); +if (err <0 ) +return err; + err =btusb_mtk_uhw_reg_read (data,MTK_BT_RESET_REG_CONNV3 , &val); +if (err <0 ) +return err; val &=0xFFFF00FF ; +if (err <0 ) +return err; val |= (1 <<13 ); -btusb_mtk_uhw_reg_write (data,MTK_BT_RESET_REG_CONNV3 , val); -btusb_mtk_uhw_reg_write (data,MTK_EP_RST_OPT ,0x00010001 ); -btusb_mtk_uhw_reg_read (data,MTK_BT_RESET_REG_CONNV3 , &val); + err =btusb_mtk_uhw_reg_write (data,MTK_BT_RESET_REG_CONNV3 , val); +if (err <0 ) +return err; + err =btusb_mtk_uhw_reg_write (data,MTK_EP_RST_OPT ,0x00010001 ); +if (err <0 ) +return err; + err =btusb_mtk_uhw_reg_read (data,MTK_BT_RESET_REG_CONNV3 , &val); +if (err <0 ) +return err; val |= (1 <<0 ); -btusb_mtk_uhw_reg_write (data,MTK_BT_RESET_REG_CONNV3 , val); -btusb_mtk_uhw_reg_write (data,MTK_UDMA_INT_STA_BT ,0x000000FF ); -btusb_mtk_uhw_reg_read (data,MTK_UDMA_INT_STA_BT , &val); -btusb_mtk_uhw_reg_write (data,MTK_UDMA_INT_STA_BT1 ,0x000000FF ); -btusb_mtk_uhw_reg_read (data,MTK_UDMA_INT_STA_BT1 , &val); + err =btusb_mtk_uhw_reg_write (data,MTK_BT_RESET_REG_CONNV3 , val); +if (err <0 ) +return err; + err =btusb_mtk_uhw_reg_write (data,MTK_UDMA_INT_STA_BT ,0x000000FF ); +if (err <0 ) +return err; + err =btusb_mtk_uhw_reg_read (data,MTK_UDMA_INT_STA_BT , &val); +if (err <0 ) +return err; + err =btusb_mtk_uhw_reg_write (data,MTK_UDMA_INT_STA_BT1 ,0x000000FF ); +if (err <0 ) +return err; + err =btusb_mtk_uhw_reg_read (data,MTK_UDMA_INT_STA_BT1 , &val); +if (err <0 ) +return err;msleep (100 ); }else {/* It's Device EndPoint Reset Option Register */ bt_dev_dbg (hdev,"Initiating reset mechanism via uhw" ); -btusb_mtk_uhw_reg_write (data,MTK_EP_RST_OPT ,MTK_EP_RST_IN_OUT_OPT ); -btusb_mtk_uhw_reg_read (data,MTK_BT_WDT_STATUS , &val); - + err =btusb_mtk_uhw_reg_write (data,MTK_EP_RST_OPT ,MTK_EP_RST_IN_OUT_OPT ); +if (err <0 ) +return err; + err =btusb_mtk_uhw_reg_read (data,MTK_BT_WDT_STATUS , &val); +if (err <0 ) +return err;/* Reset the bluetooth chip via USB interface. */ -btusb_mtk_uhw_reg_write (data,MTK_BT_SUBSYS_RST ,1 ); -btusb_mtk_uhw_reg_write (data,MTK_UDMA_INT_STA_BT ,0x000000FF ); -btusb_mtk_uhw_reg_read (data,MTK_UDMA_INT_STA_BT , &val); -btusb_mtk_uhw_reg_write (data,MTK_UDMA_INT_STA_BT1 ,0x000000FF ); -btusb_mtk_uhw_reg_read (data,MTK_UDMA_INT_STA_BT1 , &val); + err =btusb_mtk_uhw_reg_write (data,MTK_BT_SUBSYS_RST ,1 ); +if (err <0 ) +return err; + err =btusb_mtk_uhw_reg_write (data,MTK_UDMA_INT_STA_BT ,0x000000FF ); +if (err <0 ) +return err; + err =btusb_mtk_uhw_reg_read (data,MTK_UDMA_INT_STA_BT , &val); +if (err <0 ) +return err; + err =btusb_mtk_uhw_reg_write (data,MTK_UDMA_INT_STA_BT1 ,0x000000FF ); +if (err <0 ) +return err; + err =btusb_mtk_uhw_reg_read (data,MTK_UDMA_INT_STA_BT1 , &val); +if (err <0 ) +return err;/* MT7921 need to delay 20ms between toggle reset bit */ msleep (20 ); -btusb_mtk_uhw_reg_write (data,MTK_BT_SUBSYS_RST ,0 ); -btusb_mtk_uhw_reg_read (data,MTK_BT_SUBSYS_RST , &val); + err =btusb_mtk_uhw_reg_write (data,MTK_BT_SUBSYS_RST ,0 ); +if (err <0 ) +return err; + err =btusb_mtk_uhw_reg_read (data,MTK_BT_SUBSYS_RST , &val); +if (err <0 ) +return err; } err = readx_poll_timeout(btusb_mtk_reset_done, hdev, val,
@@ -3085,11 +3136,14 @@ static int btusb_mtk_subsys_reset(struct hci_dev *hdev, u32 dev_id)if (err <0 )bt_dev_err (hdev,"Reset timeout" ); -if (dev_id ==0x7922 ) -btusb_mtk_uhw_reg_write (data,MTK_UDMA_INT_STA_BT ,0x000000FF ); +if (dev_id ==0x7922 ) { + err =btusb_mtk_uhw_reg_write (data,MTK_UDMA_INT_STA_BT ,0x000000FF ); +if (err <0 ) +return err; + } -btusb_mtk_id_get (data,0x70010200 , &val); -if (!val) + err =btusb_mtk_id_get (data,0x70010200 , &val); +if (err <0 || !val)bt_dev_err (hdev,"Can't get device id, subsys reset fail." );return err;
Signature · 1 line
2.18.0
PATCH v5 3/8 Bluetooth: btmtk: rename btmediatek_data
In reply to Chris LuRename btmediatek_data to have a consistent prefix throughout the driver.
--- drivers/bluetooth/btmtk.c | 10 +++++----- drivers/bluetooth/btmtk.h | 2 +- drivers/bluetooth/btusb.c | 9 ++++----- 3 files changed, 10 insertions(+), 11 deletions(-)
drivers/bluetooth/btmtk.c +5 -5
@@ -64,7 +64,7 @@ static void btmtk_coredump(struct hci_dev *hdev)static void btmtk_coredump_hdr (struct hci_dev *hdev,struct sk_buff *skb) { -struct btmediatek_data *data =hci_get_priv (hdev); +struct btmtk_data *data =hci_get_priv (hdev);char buf[80 ]; snprintf(buf, sizeof(buf), "Controller Name: 0x%X\n",
@@ -85,7 +85,7 @@ static void btmtk_coredump_hdr(struct hci_dev *hdev, struct sk_buff *skb)static void btmtk_coredump_notify (struct hci_dev *hdev,int state) { -struct btmediatek_data *data =hci_get_priv (hdev); +struct btmtk_data *data =hci_get_priv (hdev);switch (state) {case HCI_DEVCOREDUMP_IDLE :
@@ -355,7 +355,7 @@ EXPORT_SYMBOL_GPL(btmtk_set_bdaddr);void btmtk_reset_sync (struct hci_dev *hdev) { -struct btmediatek_data *reset_work =hci_get_priv (hdev); +struct btmtk_data *reset_work =hci_get_priv (hdev);int err;hci_dev_lock (hdev);
@@ -371,7 +371,7 @@ EXPORT_SYMBOL_GPL(btmtk_reset_sync);int btmtk_register_coredump (struct hci_dev *hdev,const char *name,u32 fw_version) { -struct btmediatek_data *data =hci_get_priv (hdev); +struct btmtk_data *data =hci_get_priv (hdev);if (!IS_ENABLED (CONFIG_DEV_COREDUMP ))return -EOPNOTSUPP ;
@@ -387,7 +387,7 @@ EXPORT_SYMBOL_GPL(btmtk_register_coredump);int btmtk_process_coredump (struct hci_dev *hdev,struct sk_buff *skb) { -struct btmediatek_data *data =hci_get_priv (hdev); +struct btmtk_data *data =hci_get_priv (hdev);int err;if (!IS_ENABLED (CONFIG_DEV_COREDUMP )) {
drivers/bluetooth/btmtk.h +1 -1
@@ -135,7 +135,7 @@ struct btmtk_coredump_info {int state; }; -struct btmediatek_data { +struct btmtk_data {u32 dev_id;btmtk_reset_sync_func_t reset_sync;struct btmtk_coredump_info cd_info;
drivers/bluetooth/btusb.c +4 -5
@@ -3152,7 +3152,7 @@ static int btusb_mtk_subsys_reset(struct hci_dev *hdev, u32 dev_id)static int btusb_mtk_reset (struct hci_dev *hdev,void *rst_data) {struct btusb_data *data =hci_get_drvdata (hdev); -struct btmediatek_data *mtk_data; +struct btmtk_data *btmtk_data =hci_get_priv (hdev);int err;/* It's MediaTek specific bluetooth reset mechanism via USB */
@@ -3167,9 +3167,8 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)btusb_stop_traffic (data);usb_kill_anchored_urbs (&data->tx_anchor); - mtk_data =hci_get_priv (hdev); - err =btusb_mtk_subsys_reset (hdev, mtk_data->dev_id); + err =btusb_mtk_subsys_reset (hdev, btmtk_data->dev_id);usb_queue_reset_device (data->intf);clear_bit (BTUSB_HW_RESET_ACTIVE , &data->flags);
@@ -3191,7 +3190,7 @@ static int btusb_mtk_setup(struct hci_dev *hdev)char fw_bin_name[64 ];u32 fw_version =0 , fw_flavor =0 ;u8 param; -struct btmediatek_data *mediatek; +struct btmtk_data *mediatek; calltime =ktime_get ();
@@ -4419,7 +4418,7 @@ static int btusb_probe(struct usb_interface *intf, data->recv_event = btusb_recv_event_realtek; }else if (id->driver_info &BTUSB_MEDIATEK ) {/* Allocate extra space for Mediatek device */ - priv_size +=sizeof (struct btmediatek_data ); + priv_size +=sizeof (struct btmtk_data ); } data->recv_acl = hci_recv_frame;
Signature · 1 line
2.18.0
PATCH v5 4/8 Bluetooth: btusb: add callback function in btusb suspend/resume
In reply to Chris LuAdd suspend/resum callback function in btusb_data which are reserved for vendor specific usage during suspend/resume. hdev->suspend will be added before stop traffic in btusb_suspend and hdev-> resume will be added after resubmit urb in btusb_resume.
--- drivers/bluetooth/btusb.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/bluetooth/btusb.c +9 -0
@@ -891,6 +891,9 @@ struct btusb_data {int (*setup_on_usb)(struct hci_dev *hdev); +int (*suspend)(struct hci_dev *hdev); +int (*resume)(struct hci_dev *hdev); +int oob_wake_irq;/* irq for out-of-band wake-on-bt */ unsigned cmd_timeout_cnt;
@@ -4765,6 +4768,9 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)cancel_work_sync (&data->work); +if (data->suspend) + data->suspend (data->hdev); +btusb_stop_traffic (data);usb_kill_anchored_urbs (&data->tx_anchor);
@@ -4868,6 +4874,9 @@ static int btusb_resume(struct usb_interface *intf)btusb_submit_isoc_urb (hdev,GFP_NOIO ); } +if (data->resume) + data->resume (hdev); +spin_lock_irq (&data->txlock);play_deferred (data);clear_bit (BTUSB_SUSPENDING , &data->flags);
Signature · 1 line
2.18.0
PATCH v5 5/8 Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c
In reply to Chris LuMove btusb_mtk_hci_wmt_sync from btusb.c to btmtk.c which holds vendor specific stuff and would make btusb.c clean.
--- drivers/bluetooth/btmtk.c | 264 ++++++++++++++++++++++++++++++++++ drivers/bluetooth/btmtk.h | 33 +++++ drivers/bluetooth/btusb.c | 290 +------------------------------------- 3 files changed, 304 insertions(+), 283 deletions(-)
drivers/bluetooth/btmtk.c +264 -0
@@ -431,6 +431,270 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb) }EXPORT_SYMBOL_GPL (btmtk_process_coredump); +static void btmtk_usb_wmt_recv (struct urb *urb) +{ +struct hci_dev *hdev = urb->context; +struct btmtk_data *data =hci_get_priv (hdev); +struct sk_buff *skb; +int err; + +if (urb->status ==0 && urb->actual_length >0 ) { + hdev->stat.byte_rx += urb->actual_length; + +/* WMT event shouldn't be fragmented and the size should be +* less than HCI_WMT_MAX_EVENT_SIZE. +*/ + skb =bt_skb_alloc (HCI_WMT_MAX_EVENT_SIZE ,GFP_ATOMIC ); +if (!skb) { + hdev->stat.err_rx++; +kfree (urb->setup_packet); +return ; + } + +hci_skb_pkt_type (skb) =HCI_EVENT_PKT ; +skb_put_data (skb, urb->transfer_buffer, urb->actual_length); + +/* When someone waits for the WMT event, the skb is being cloned +* and being processed the events from there then. +*/ +if (test_bit (BTMTK_TX_WAIT_VND_EVT , &data->flags)) { + data->evt_skb =skb_clone (skb,GFP_ATOMIC ); +if (!data->evt_skb) { +kfree_skb (skb); +kfree (urb->setup_packet); +return ; + } + } + + err =hci_recv_frame (hdev, skb); +if (err <0 ) { +kfree_skb (data->evt_skb); + data->evt_skb =NULL ; +kfree (urb->setup_packet); +return ; + } + +if (test_and_clear_bit (BTMTK_TX_WAIT_VND_EVT , + &data->flags)) { +/* Barrier to sync with other CPUs */ +smp_mb__after_atomic (); +wake_up_bit (&data->flags, +BTMTK_TX_WAIT_VND_EVT ); + } +kfree (urb->setup_packet); +return ; + }else if (urb->status == -ENOENT ) { +/* Avoid suspend failed when usb_kill_urb */ +return ; + } + +usb_mark_last_busy (data->udev); + +/* The URB complete handler is still called with urb->actual_length = 0 +* when the event is not available, so we should keep re-submitting +* URB until WMT event returns, Also, It's necessary to wait some time +* between the two consecutive control URBs to relax the target device +* to generate the event. Otherwise, the WMT event cannot return from +* the device successfully. +*/ +udelay (500 ); + +usb_anchor_urb (urb, data->ctrl_anchor); + err =usb_submit_urb (urb,GFP_ATOMIC ); +if (err <0 ) { +kfree (urb->setup_packet); +/* -EPERM: urb is being killed; +* -ENODEV: device got disconnected +*/ +if (err != -EPERM && err != -ENODEV ) +bt_dev_err (hdev,"urb %p failed to resubmit (%d)" , + urb, -err); +usb_unanchor_urb (urb); + } +} + +static int btmtk_usb_submit_wmt_recv_urb (struct hci_dev *hdev) +{ +struct btmtk_data *data =hci_get_priv (hdev); +struct usb_ctrlrequest *dr; +unsigned char *buf; +int err, size =64 ; +unsigned int pipe; +struct urb *urb; + + urb =usb_alloc_urb (0 ,GFP_KERNEL ); +if (!urb) +return -ENOMEM ; + + dr =kmalloc (sizeof (*dr),GFP_KERNEL ); +if (!dr) { +usb_free_urb (urb); +return -ENOMEM ; + } + + dr->bRequestType =USB_TYPE_VENDOR |USB_DIR_IN ; + dr->bRequest =1 ; + dr->wIndex =cpu_to_le16 (0 ); + dr->wValue =cpu_to_le16 (48 ); + dr->wLength =cpu_to_le16 (size); + + buf =kmalloc (size,GFP_KERNEL ); +if (!buf) { +kfree (dr); +usb_free_urb (urb); +return -ENOMEM ; + } + + pipe =usb_rcvctrlpipe (data->udev,0 ); + +usb_fill_control_urb (urb, data->udev, pipe, (void *)dr, + buf, size, btmtk_usb_wmt_recv, hdev); + + urb->transfer_flags |=URB_FREE_BUFFER ; + +usb_anchor_urb (urb, data->ctrl_anchor); + err =usb_submit_urb (urb,GFP_KERNEL ); +if (err <0 ) { +if (err != -EPERM && err != -ENODEV ) +bt_dev_err (hdev,"urb %p submission failed (%d)" , + urb, -err); +usb_unanchor_urb (urb); + } + +usb_free_urb (urb); + +return err; +} + +int btmtk_usb_hci_wmt_sync (struct hci_dev *hdev, +struct btmtk_hci_wmt_params *wmt_params) +{ +struct btmtk_data *data =hci_get_priv (hdev); +struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc; +u32 hlen, status =BTMTK_WMT_INVALID ; +struct btmtk_hci_wmt_evt *wmt_evt; +struct btmtk_hci_wmt_cmd *wc; +struct btmtk_wmt_hdr *hdr; +int err; + +/* Send the WMT command and wait until the WMT event returns */ + hlen =sizeof (*hdr) + wmt_params->dlen; +if (hlen >255 ) +return -EINVAL ; + + wc =kzalloc (hlen,GFP_KERNEL ); +if (!wc) +return -ENOMEM ; + + hdr = &wc->hdr; + hdr->dir =1 ; + hdr->op = wmt_params->op; + hdr->dlen =cpu_to_le16 (wmt_params->dlen +1 ); + hdr->flag = wmt_params->flag; +memcpy (wc->data, wmt_params->data, wmt_params->dlen); + +set_bit (BTMTK_TX_WAIT_VND_EVT , &data->flags); + +/* WMT cmd/event doesn't follow up the generic HCI cmd/event handling, +* it needs constantly polling control pipe until the host received the +* WMT event, thus, we should require to specifically acquire PM counter +* on the USB to prevent the interface from entering auto suspended +* while WMT cmd/event in progress. +*/ + err =usb_autopm_get_interface (data->intf); +if (err <0 ) + goto err_free_wc; + + err =__hci_cmd_send (hdev,0xfc6f , hlen, wc); + +if (err <0 ) { +clear_bit (BTMTK_TX_WAIT_VND_EVT , &data->flags); +usb_autopm_put_interface (data->intf); + goto err_free_wc; + } + +/* Submit control IN URB on demand to process the WMT event */ + err =btmtk_usb_submit_wmt_recv_urb (hdev); + +usb_autopm_put_interface (data->intf); + +if (err <0 ) + goto err_free_wc; + +/* The vendor specific WMT commands are all answered by a vendor +* specific event and will have the Command Status or Command +* Complete as with usual HCI command flow control. +* +* After sending the command, wait for BTUSB_TX_WAIT_VND_EVT +* state to be cleared. The driver specific event receive routine +* will clear that state and with that indicate completion of the +* WMT command. +*/ + err =wait_on_bit_timeout (&data->flags,BTMTK_TX_WAIT_VND_EVT , +TASK_INTERRUPTIBLE ,HCI_INIT_TIMEOUT ); +if (err == -EINTR ) { +bt_dev_err (hdev,"Execution of wmt command interrupted" ); +clear_bit (BTMTK_TX_WAIT_VND_EVT , &data->flags); + goto err_free_wc; + } + +if (err) { +bt_dev_err (hdev,"Execution of wmt command timed out" ); +clear_bit (BTMTK_TX_WAIT_VND_EVT , &data->flags); + err = -ETIMEDOUT ; + goto err_free_wc; + } + +if (data->evt_skb ==NULL ) + goto err_free_wc; + +/* Parse and handle the return WMT event */ + wmt_evt = (struct btmtk_hci_wmt_evt *)data->evt_skb->data; +if (wmt_evt->whdr.op != hdr->op) { +bt_dev_err (hdev,"Wrong op received %d expected %d" , + wmt_evt->whdr.op, hdr->op); + err = -EIO ; + goto err_free_skb; + } + +switch (wmt_evt->whdr.op) { +case BTMTK_WMT_SEMAPHORE : +if (wmt_evt->whdr.flag ==2 ) + status =BTMTK_WMT_PATCH_UNDONE ; +else + status =BTMTK_WMT_PATCH_DONE ; +break ; +case BTMTK_WMT_FUNC_CTRL : + wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt; +if (be16_to_cpu (wmt_evt_funcc->status) ==0x404 ) + status =BTMTK_WMT_ON_DONE ; +else if (be16_to_cpu (wmt_evt_funcc->status) ==0x420 ) + status =BTMTK_WMT_ON_PROGRESS ; +else + status =BTMTK_WMT_ON_UNDONE ; +break ; +case BTMTK_WMT_PATCH_DWNLD : +if (wmt_evt->whdr.flag ==2 ) + status =BTMTK_WMT_PATCH_DONE ; +else if (wmt_evt->whdr.flag ==1 ) + status =BTMTK_WMT_PATCH_PROGRESS ; +else + status =BTMTK_WMT_PATCH_UNDONE ; +break ; + } + +if (wmt_params->status) + *wmt_params->status = status; + +err_free_skb: +kfree_skb (data->evt_skb); + data->evt_skb =NULL ; +err_free_wc: +kfree (wc); +return err; +} +EXPORT_SYMBOL_GPL (btmtk_usb_hci_wmt_sync); +MODULE_AUTHOR ("Sean Wang <[email protected]>" );MODULE_AUTHOR ("Mark Chen <[email protected]>" );MODULE_DESCRIPTION ("Bluetooth support for MediaTek devices ver " VERSION );
drivers/bluetooth/btmtk.h +33 -0
@@ -1,6 +1,8 @@/* SPDX-License-Identifier: ISC */ /* Copyright (C) 2021 MediaTek Inc. */ +#include <linux/usb.h> +#define FIRMWARE_MT7622 "mediatek/mt7622pr2h.bin"#define FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin"#define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin"
@@ -28,6 +30,18 @@#define MTK_COREDUMP_END_LEN (sizeof(MTK_COREDUMP_END))#define MTK_COREDUMP_NUM 255 +/* UHW CR mapping */ +#define MTK_BT_MISC 0x70002510 +#define MTK_BT_SUBSYS_RST 0x70002610 +#define MTK_UDMA_INT_STA_BT 0x74000024 +#define MTK_UDMA_INT_STA_BT1 0x74000308 +#define MTK_BT_WDT_STATUS 0x740003A0 +#define MTK_EP_RST_OPT 0x74011890 +#define MTK_EP_RST_IN_OUT_OPT 0x00010001 +#define MTK_BT_RST_DONE 0x00000100 +#define MTK_BT_RESET_REG_CONNV3 0x70028610 +#define MTK_BT_READ_DEV_ID 0x70010200 +enum {BTMTK_WMT_PATCH_DWNLD =0x1 ,BTMTK_WMT_TEST =0x2 ,
@@ -126,6 +140,10 @@ struct btmtk_hci_wmt_params {u32 *status; }; +enum { +BTMTK_TX_WAIT_VND_EVT , +}; +typedef int (*btmtk_reset_sync_func_t )(struct hci_dev *,void *);struct btmtk_coredump_info {
@@ -136,9 +154,15 @@ struct btmtk_coredump_info { };struct btmtk_data { +unsigned long flags;u32 dev_id;btmtk_reset_sync_func_t reset_sync;struct btmtk_coredump_info cd_info; + +struct usb_device *udev; +struct usb_interface *intf; +struct usb_anchor *ctrl_anchor; +struct sk_buff *evt_skb; }; typedef int (*wmt_cmd_sync_func_t)(struct hci_dev *,
@@ -163,6 +187,9 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb);void btmtk_fw_get_filename (char *buf,size_t size,u32 dev_id,u32 fw_ver,u32 fw_flavor); + +int btmtk_usb_hci_wmt_sync (struct hci_dev *hdev, +struct btmtk_hci_wmt_params *wmt_params);#else static inline int btmtk_set_bdaddr(struct hci_dev *hdev,
@@ -202,4 +229,10 @@ static void btmtk_fw_get_filename(char *buf, size_t size, u32 dev_id, u32 fw_ver, u32 fw_flavor) { } + +static int btmtk_usb_hci_wmt_sync (struct hci_dev *hdev, +struct btmtk_hci_wmt_params *wmt_params) +{ +return -EOPNOTSUPP ; +}#endif
drivers/bluetooth/btusb.c +7 -283
338 lines not on this page · raw message
Signature · 1 line
2.18.0
kernel test robot
build botRe: [PATCH v5 5/8] Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c
kernel test robot noticed the following build errors:
Hi Chris,
kernel test robot noticed the following build errors:
[auto build test ERROR on bluetooth-next/master]
[also build test ERROR on next-20240626]
[cannot apply to bluetooth/master linus/master v6.10-rc5] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Chris-Lu/Bluetooth-btusb-mediatek-remove-the-unnecessary-goto-tag/20240626-114003 base: https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master patch link: https://lore.kernel.org/r/20240626025329.26424-6-chris.lu%40mediatek.com patch subject: [PATCH v5 5/8] Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c config: parisc-randconfig-001-20240627 (https://download.01.org/0day-ci/archive/20240628/[email protected]/config) compiler: hppa-linux-gcc (GCC) 13.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240628/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>, old ones prefixed by <<):
WARNING: modpost: missing MODULE_DESCRIPTION() in kernel/locking/test-ww_mutex.o
WARNING: modpost: missing MODULE_DESCRIPTION() in kernel/rcu/rcutorture.o
WARNING: modpost: missing MODULE_DESCRIPTION() in kernel/rcu/refscale.o
WARNING: modpost: missing MODULE_DESCRIPTION() in kernel/scftorture.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_cp850.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_cp852.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_cp855.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_cp866.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_cp932.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_euc-jp.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_cp936.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_cp949.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_ascii.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_iso8859-1.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_iso8859-2.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_iso8859-4.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_utf8.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/mac-cyrillic.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/mac-roman.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_ucs2_utils.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/binfmt_misc.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/jbd2/jbd2.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/hfs/hfs.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/efs/efs.o
WARNING: modpost: missing MODULE_DESCRIPTION() in crypto/cast_common.o
WARNING: modpost: missing MODULE_DESCRIPTION() in crypto/af_alg.o
WARNING: modpost: missing MODULE_DESCRIPTION() in crypto/algif_hash.o
WARNING: modpost: missing MODULE_DESCRIPTION() in lib/math/rational.o
WARNING: modpost: missing MODULE_DESCRIPTION() in lib/test_ubsan.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/irqchip/irq-ts4800.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/pinctrl/pinctrl-mcp23s08_i2c.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/pinctrl/pinctrl-mcp23s08.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/pwm/pwm-imx1.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/pwm/pwm-imx27.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/pwm/pwm-samsung.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/pwm/pwm-spear.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/soc/imx/soc-imx8m.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/soc/ixp4xx/ixp4xx-npe.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/soc/amlogic/meson-clk-measure.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/regulator/da9121-regulator.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/regulator/tps6286x-regulator.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/reset/hisilicon/hi6220_reset.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/tty/serial/esp32_uart.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/tty/serial/esp32_acm.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/tty/serial/owl-uart.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/tty/serial/serial_mctrl_gpio.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/char/ttyprintk.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/iommu/iova.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/base/regmap/regmap-ac97.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/base/regmap/regmap-i2c.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/base/regmap/regmap-slimbus.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/mfd/arizona.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/mfd/rt4831.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/mfd/qcom-pm8008.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/dax/dax.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/scsi/scsi_common.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/i2c/busses/i2c-pxa.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/media/rc/rc-core.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/mmc/core/pwrseq_simple.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/mmc/core/pwrseq_sd8787.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/firmware/google/coreboot_table.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/firmware/google/memconsole.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/firmware/google/memconsole-coreboot.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/firmware/google/cbmem.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-log.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-vibrator.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-audio-manager.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-gpio.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-i2c.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-uart.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/devfreq/governor_userspace.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hwtracing/intel_th/intel_th_msu_sink.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/nvmem/nvmem-apple-efuses.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/nvmem/nvmem_brcm_nvram.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/interconnect/imx/imx8mq-interconnect.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/interconnect/imx/imx8mn-interconnect.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hte/hte-tegra194-test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/vdpa/vdpa.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/uio/uio.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/input/matrix-keymap.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/input/vivaldi-fmap.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/iio/adc/ingenic-adc.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/iio/adc/xilinx-ams.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/iio/buffer/kfifo_buf.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/siox/siox-bus-gpio.o
>> ERROR: modpost: "usb_alloc_urb" [drivers/bluetooth/btmtk.ko] undefined! >> ERROR: modpost: "usb_free_urb" [drivers/bluetooth/btmtk.ko] undefined! >> ERROR: modpost: "usb_anchor_urb" [drivers/bluetooth/btmtk.ko] undefined! >> ERROR: modpost: "usb_submit_urb" [drivers/bluetooth/btmtk.ko] undefined! >> ERROR: modpost: "usb_unanchor_urb" [drivers/bluetooth/btmtk.ko] undefined!
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
PATCH v5 6/8 Bluetooth: btmtk: move btusb_mtk_[setup, shutdown] to btmtk.c
In reply to Chris LuMove btusb_mtk_[setup, shutdown] and related function from btusb.c to btmtk.c which holds vendor specific stuff and would make btusb.c clean.
--- drivers/bluetooth/btmtk.c | 454 +++++++++++++++++++++++++++++++++++++- drivers/bluetooth/btmtk.h | 23 +- drivers/bluetooth/btusb.c | 452 ++----------------------------------- 3 files changed, 484 insertions(+), 445 deletions(-)
drivers/bluetooth/btmtk.c +451 -3
@@ -4,6 +4,8 @@*/ #include <linux/module.h> #include <linux/firmware.h> +#include <linux/iopoll.h> +#include <asm/unaligned.h> #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h>
@@ -566,8 +568,8 @@ static int btmtk_usb_submit_wmt_recv_urb(struct hci_dev *hdev)return err; } -int btmtk_usb_hci_wmt_sync (struct hci_dev *hdev, -struct btmtk_hci_wmt_params *wmt_params) +static int btmtk_usb_hci_wmt_sync (struct hci_dev *hdev, +struct btmtk_hci_wmt_params *wmt_params) {struct btmtk_data *data =hci_get_priv (hdev);struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc;
@@ -693,7 +695,453 @@ int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,kfree (wc);return err; } -EXPORT_SYMBOL_GPL (btmtk_usb_hci_wmt_sync); + +static int btmtk_usb_func_query (struct hci_dev *hdev) +{ +struct btmtk_hci_wmt_params wmt_params; +int status, err; +u8 param =0 ; + +/* Query whether the function is enabled */ + wmt_params.op =BTMTK_WMT_FUNC_CTRL ; + wmt_params.flag =4 ; + wmt_params.dlen =sizeof (param); + wmt_params.data = ¶m; + wmt_params.status = &status; + + err =btmtk_usb_hci_wmt_sync (hdev, &wmt_params); +if (err <0 ) { +bt_dev_err (hdev,"Failed to query function status (%d)" , err); +return err; + } + +return status; +} + +static int btmtk_usb_uhw_reg_write (struct hci_dev *hdev,u32 reg,u32 val) +{ +struct btmtk_data *data =hci_get_priv (hdev); +int pipe, err; +void *buf; + + buf =kzalloc (4 ,GFP_KERNEL ); +if (!buf) +return -ENOMEM ; + +put_unaligned_le32 (val, buf); + + pipe =usb_sndctrlpipe (data->udev,0 ); + err =usb_control_msg (data->udev, pipe,0x02 , +0x5E , + reg >>16 , reg &0xffff , + buf,4 ,USB_CTRL_SET_TIMEOUT ); +if (err <0 ) +bt_dev_err (hdev,"Failed to write uhw reg(%d)" , err); + +kfree (buf); + +return err; +} + +static int btmtk_usb_uhw_reg_read (struct hci_dev *hdev,u32 reg,u32 *val) +{ +struct btmtk_data *data =hci_get_priv (hdev); +int pipe, err; +void *buf; + + buf =kzalloc (4 ,GFP_KERNEL ); +if (!buf) +return -ENOMEM ; + + pipe =usb_rcvctrlpipe (data->udev,0 ); + err =usb_control_msg (data->udev, pipe,0x01 , +0xDE , + reg >>16 , reg &0xffff , + buf,4 ,USB_CTRL_GET_TIMEOUT ); +if (err <0 ) { +bt_dev_err (hdev,"Failed to read uhw reg(%d)" , err); + goto err_free_buf; + } + + *val =get_unaligned_le32 (buf); +bt_dev_dbg (hdev,"reg=%x, value=0x%08x" , reg, *val); + +err_free_buf: +kfree (buf); + +return err; +} + +static int btmtk_usb_reg_read (struct hci_dev *hdev,u32 reg,u32 *val) +{ +struct btmtk_data *data =hci_get_priv (hdev); +int pipe, err, size =sizeof (u32); +void *buf; + + buf =kzalloc (size,GFP_KERNEL ); +if (!buf) +return -ENOMEM ; + + pipe =usb_rcvctrlpipe (data->udev,0 ); + err =usb_control_msg (data->udev, pipe,0x63 , +USB_TYPE_VENDOR |USB_DIR_IN , + reg >>16 , reg &0xffff , + buf, size,USB_CTRL_GET_TIMEOUT ); +if (err <0 ) + goto err_free_buf; + + *val =get_unaligned_le32 (buf); + +err_free_buf: +kfree (buf); + +return err; +} + +static int btmtk_usb_id_get (struct hci_dev *hdev,u32 reg,u32 *id) +{ +return btmtk_usb_reg_read (hdev, reg, id); +} + +static u32 btmtk_usb_reset_done (struct hci_dev *hdev) +{ +u32 val =0 ; + +btmtk_usb_uhw_reg_read (hdev,MTK_BT_MISC , &val); + +return val &MTK_BT_RST_DONE ; +} + +int btmtk_usb_subsys_reset (struct hci_dev *hdev,u32 dev_id) +{ +u32 val; +int err; + +if (dev_id ==0x7922 ) { + err =btmtk_usb_uhw_reg_read (hdev,MTK_BT_SUBSYS_RST , &val); +if (err <0 ) +return err; + val |=0x00002020 ; + err =btmtk_usb_uhw_reg_write (hdev,MTK_BT_SUBSYS_RST , val); +if (err <0 ) +return err; + err =btmtk_usb_uhw_reg_write (hdev,MTK_EP_RST_OPT ,0x00010001 ); +if (err <0 ) +return err; + err =btmtk_usb_uhw_reg_read (hdev,MTK_BT_SUBSYS_RST , &val); +if (err <0 ) +return err; + val |=BIT (0 ); + err =btmtk_usb_uhw_reg_write (hdev,MTK_BT_SUBSYS_RST , val); +if (err <0 ) +return err; +msleep (100 ); + }else if (dev_id ==0x7925 ) { + err =btmtk_usb_uhw_reg_read (hdev,MTK_BT_RESET_REG_CONNV3 , &val); +if (err <0 ) +return err; + val |= (1 <<5 ); + err =btmtk_usb_uhw_reg_write (hdev,MTK_BT_RESET_REG_CONNV3 , val); +if (err <0 ) +return err; + err =btmtk_usb_uhw_reg_read (hdev,MTK_BT_RESET_REG_CONNV3 , &val); +if (err <0 ) +return err; + val &=0xFFFF00FF ; + val |= (1 <<13 ); + err =btmtk_usb_uhw_reg_write (hdev,MTK_BT_RESET_REG_CONNV3 , val); +if (err <0 ) +return err; + err =btmtk_usb_uhw_reg_write (hdev,MTK_EP_RST_OPT ,0x00010001 ); +if (err <0 ) +return err; + err =btmtk_usb_uhw_reg_read (hdev,MTK_BT_RESET_REG_CONNV3 , &val); +if (err <0 ) +return err; + val |= (1 <<0 ); + err =btmtk_usb_uhw_reg_write (hdev,MTK_BT_RESET_REG_CONNV3 , val); +if (err <0 ) +return err; + err =btmtk_usb_uhw_reg_write (hdev,MTK_UDMA_INT_STA_BT ,0x000000FF ); +if (err <0 ) +return err; + err =btmtk_usb_uhw_reg_read (hdev,MTK_UDMA_INT_STA_BT , &val); +if (err <0 ) +return err; + err =btmtk_usb_uhw_reg_write (hdev,MTK_UDMA_INT_STA_BT1 ,0x000000FF ); +if (err <0 ) +return err; + err =btmtk_usb_uhw_reg_read (hdev,MTK_UDMA_INT_STA_BT1 , &val); +if (err <0 ) +return err; +msleep (100 ); + }else { +/* It's Device EndPoint Reset Option Register */ +bt_dev_dbg (hdev,"Initiating reset mechanism via uhw" ); + err =btmtk_usb_uhw_reg_write (hdev,MTK_EP_RST_OPT ,MTK_EP_RST_IN_OUT_OPT ); +if (err <0 ) +return err; + err =btmtk_usb_uhw_reg_read (hdev,MTK_BT_WDT_STATUS , &val); +if (err <0 ) +return err; +/* Reset the bluetooth chip via USB interface. */ + err =btmtk_usb_uhw_reg_write (hdev,MTK_BT_SUBSYS_RST ,1 ); +if (err <0 ) +return err; + err =btmtk_usb_uhw_reg_write (hdev,MTK_UDMA_INT_STA_BT ,0x000000FF ); +if (err <0 ) +return err; + err =btmtk_usb_uhw_reg_read (hdev,MTK_UDMA_INT_STA_BT , &val); +if (err <0 ) +return err; + err =btmtk_usb_uhw_reg_write (hdev,MTK_UDMA_INT_STA_BT1 ,0x000000FF ); +if (err <0 ) +return err; + err =btmtk_usb_uhw_reg_read (hdev,MTK_UDMA_INT_STA_BT1 , &val); +if (err <0 ) +return err; +/* MT7921 need to delay 20ms between toggle reset bit */ +msleep (20 ); + err =btmtk_usb_uhw_reg_write (hdev,MTK_BT_SUBSYS_RST ,0 ); +if (err <0 ) +return err; + err =btmtk_usb_uhw_reg_read (hdev,MTK_BT_SUBSYS_RST , &val); +if (err <0 ) +return err; + } + + err =readx_poll_timeout (btmtk_usb_reset_done, hdev, val, + val &MTK_BT_RST_DONE ,20000 ,1000000 ); +if (err <0 ) +bt_dev_err (hdev,"Reset timeout" ); + +if (dev_id ==0x7922 ) { + err =btmtk_usb_uhw_reg_write (hdev,MTK_UDMA_INT_STA_BT ,0x000000FF ); +if (err <0 ) +return err; + } + + err =btmtk_usb_id_get (hdev,0x70010200 , &val); +if (err <0 || !val) +bt_dev_err (hdev,"Can't get device id, subsys reset fail." ); + +return err; +} +EXPORT_SYMBOL_GPL (btmtk_usb_subsys_reset); + +int btmtk_usb_setup (struct hci_dev *hdev) +{ +struct btmtk_data *btmtk_data =hci_get_priv (hdev); +struct btmtk_hci_wmt_params wmt_params; +ktime_t calltime, delta, rettime; +struct btmtk_tci_sleep tci_sleep; +unsigned long long duration; +struct sk_buff *skb; +const char *fwname; +int err, status; +u32 dev_id =0 ; +char fw_bin_name[64 ]; +u32 fw_version =0 , fw_flavor =0 ; +u8 param; + + calltime =ktime_get (); + + err =btmtk_usb_id_get (hdev,0x80000008 , &dev_id); +if (err <0 ) { +bt_dev_err (hdev,"Failed to get device id (%d)" , err); +return err; + } + +if (!dev_id || dev_id !=0x7663 ) { + err =btmtk_usb_id_get (hdev,0x70010200 , &dev_id); +if (err <0 ) { +bt_dev_err (hdev,"Failed to get device id (%d)" , err); +return err; + } + err =btmtk_usb_id_get (hdev,0x80021004 , &fw_version); +if (err <0 ) { +bt_dev_err (hdev,"Failed to get fw version (%d)" , err); +return err; + } + err =btmtk_usb_id_get (hdev,0x70010020 , &fw_flavor); +if (err <0 ) { +bt_dev_err (hdev,"Failed to get fw flavor (%d)" , err); +return err; + } + fw_flavor = (fw_flavor &0x00000080 ) >>7 ; + } + + btmtk_data->dev_id = dev_id; + + err =btmtk_register_coredump (hdev, btmtk_data->drv_name, fw_version); +if (err <0 ) +bt_dev_err (hdev,"Failed to register coredump (%d)" , err); + +switch (dev_id) { +case 0x7663 : + fwname =FIRMWARE_MT7663 ; +break ; +case 0x7668 : + fwname =FIRMWARE_MT7668 ; +break ; +case 0x7922 : +case 0x7961 : +case 0x7925 : +/* Reset the device to ensure it's in the initial state before +* downloading the firmware to ensure. +*/ + +if (!test_bit (BTMTK_FIRMWARE_LOADED , &btmtk_data->flags)) +btmtk_usb_subsys_reset (hdev, dev_id); + +btmtk_fw_get_filename (fw_bin_name,sizeof (fw_bin_name), dev_id, + fw_version, fw_flavor); + + err =btmtk_setup_firmware_79xx (hdev, fw_bin_name, + btmtk_usb_hci_wmt_sync); +if (err <0 ) { +bt_dev_err (hdev,"Failed to set up firmware (%d)" , err); +clear_bit (BTMTK_FIRMWARE_LOADED , &btmtk_data->flags); +return err; + } + +set_bit (BTMTK_FIRMWARE_LOADED , &btmtk_data->flags); + +/* It's Device EndPoint Reset Option Register */ + err =btmtk_usb_uhw_reg_write (hdev,MTK_EP_RST_OPT , +MTK_EP_RST_IN_OUT_OPT ); +if (err <0 ) +return err; + +/* Enable Bluetooth protocol */ + param =1 ; + wmt_params.op =BTMTK_WMT_FUNC_CTRL ; + wmt_params.flag =0 ; + wmt_params.dlen =sizeof (param); + wmt_params.data = ¶m; + wmt_params.status =NULL ; + + err =btmtk_usb_hci_wmt_sync (hdev, &wmt_params); +if (err <0 ) { +bt_dev_err (hdev,"Failed to send wmt func ctrl (%d)" , err); +return err; + } + +hci_set_msft_opcode (hdev,0xFD30 ); +hci_set_aosp_capable (hdev); + + goto done; +default : +bt_dev_err (hdev,"Unsupported hardware variant (%08x)" , + dev_id); +return -ENODEV ; + } + +/* Query whether the firmware is already download */ + wmt_params.op =BTMTK_WMT_SEMAPHORE ; + wmt_params.flag =1 ; + wmt_params.dlen =0 ; + wmt_params.data =NULL ; + wmt_params.status = &status; + + err =btmtk_usb_hci_wmt_sync (hdev, &wmt_params); +if (err <0 ) { +bt_dev_err (hdev,"Failed to query firmware status (%d)" , err); +return err; + } + +if (status ==BTMTK_WMT_PATCH_DONE ) { +bt_dev_info (hdev,"firmware already downloaded" ); + goto ignore_setup_fw; + } + +/* Setup a firmware which the device definitely requires */ + err =btmtk_setup_firmware (hdev, fwname, + btmtk_usb_hci_wmt_sync); +if (err <0 ) +return err; + +ignore_setup_fw: + err =readx_poll_timeout (btmtk_usb_func_query, hdev, status, + status <0 || status !=BTMTK_WMT_ON_PROGRESS , +2000 ,5000000 ); +/* -ETIMEDOUT happens */ +if (err <0 ) +return err; + +/* The other errors happen in btmtk_usb_func_query */ +if (status <0 ) +return status; + +if (status ==BTMTK_WMT_ON_DONE ) { +bt_dev_info (hdev,"function already on" ); + goto ignore_func_on; + } + +/* Enable Bluetooth protocol */ + param =1 ; + wmt_params.op =BTMTK_WMT_FUNC_CTRL ; + wmt_params.flag =0 ; + wmt_params.dlen =sizeof (param); + wmt_params.data = ¶m; + wmt_params.status =NULL ; + + err =btmtk_usb_hci_wmt_sync (hdev, &wmt_params); +if (err <0 ) { +bt_dev_err (hdev,"Failed to send wmt func ctrl (%d)" , err); +return err; + } + +ignore_func_on: +/* Apply the low power environment setup */ + tci_sleep.mode =0x5 ; + tci_sleep.duration =cpu_to_le16 (0x640 ); + tci_sleep.host_duration =cpu_to_le16 (0x640 ); + tci_sleep.host_wakeup_pin =0 ; + tci_sleep.time_compensation =0 ; + + skb =__hci_cmd_sync (hdev,0xfc7a ,sizeof (tci_sleep), &tci_sleep, +HCI_INIT_TIMEOUT ); +if (IS_ERR (skb)) { + err =PTR_ERR (skb); +bt_dev_err (hdev,"Failed to apply low power setting (%d)" , err); +return err; + } +kfree_skb (skb); + +done: + rettime =ktime_get (); + delta =ktime_sub (rettime, calltime); + duration = (unsigned long long )ktime_to_ns (delta) >>10 ; + +bt_dev_info (hdev,"Device setup in %llu usecs" , duration); + +return 0 ; +} +EXPORT_SYMBOL_GPL (btmtk_usb_setup); + +int btmtk_usb_shutdown (struct hci_dev *hdev) +{ +struct btmtk_hci_wmt_params wmt_params; +u8 param =0 ; +int err; + +/* Disable the device */ + wmt_params.op =BTMTK_WMT_FUNC_CTRL ; + wmt_params.flag =0 ; + wmt_params.dlen =sizeof (param); + wmt_params.data = ¶m; + wmt_params.status =NULL ; + + err =btmtk_usb_hci_wmt_sync (hdev, &wmt_params); +if (err <0 ) { +bt_dev_err (hdev,"Failed to send wmt func ctrl (%d)" , err); +return err; + } + +return 0 ; +} +EXPORT_SYMBOL_GPL (btmtk_usb_shutdown);MODULE_AUTHOR ("Sean Wang <[email protected]>" );MODULE_AUTHOR ("Mark Chen <[email protected]>" );
drivers/bluetooth/btmtk.h +19 -4
@@ -142,6 +142,8 @@ struct btmtk_hci_wmt_params {enum {BTMTK_TX_WAIT_VND_EVT , +BTMTK_FIRMWARE_LOADED , +BTMTK_HW_RESET_ACTIVE , };typedef int (*btmtk_reset_sync_func_t )(struct hci_dev *,void *);
@@ -154,6 +156,7 @@ struct btmtk_coredump_info { };struct btmtk_data { +const char *drv_name;unsigned long flags;u32 dev_id;btmtk_reset_sync_func_t reset_sync;
@@ -188,8 +191,11 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb);void btmtk_fw_get_filename (char *buf,size_t size,u32 dev_id,u32 fw_ver,u32 fw_flavor); -int btmtk_usb_hci_wmt_sync (struct hci_dev *hdev, -struct btmtk_hci_wmt_params *wmt_params); +int btmtk_usb_subsys_reset (struct hci_dev *hdev,u32 dev_id); + +int btmtk_usb_setup (struct hci_dev *hdev); + +int btmtk_usb_shutdown (struct hci_dev *hdev);#else static inline int btmtk_set_bdaddr(struct hci_dev *hdev,
@@ -230,8 +236,17 @@ static void btmtk_fw_get_filename(char *buf, size_t size, u32 dev_id, { } -static int btmtk_usb_hci_wmt_sync (struct hci_dev *hdev, -struct btmtk_hci_wmt_params *wmt_params) +static int btmtk_usb_subsys_reset (struct hci_dev *hdev,u32 dev_id) +{ +return -EOPNOTSUPP ; +} + +static int btmtk_usb_setup (struct hci_dev *hdev) +{ +return -EOPNOTSUPP ; +} + +static int btmtk_usb_shutdown (struct hci_dev *hdev) {return -EOPNOTSUPP ; }
drivers/bluetooth/btusb.c +14 -438
484 lines not on this page · raw message
Signature · 1 line
2.18.0
PATCH v5 7/8 Bluetooth: btmtk: move btusb_recv_acl_mtk to btmtk.c
In reply to Chris LuMove btusb_recv_acl_mtk from btusb.c to btmtk.c which holds vendor specific stuff and would make btusb.c clean.
--- drivers/bluetooth/btmtk.c | 33 +++++++++++++++++++++++++++++++++ drivers/bluetooth/btmtk.h | 7 +++++++ drivers/bluetooth/btusb.c | 34 +--------------------------------- 3 files changed, 41 insertions(+), 33 deletions(-)
drivers/bluetooth/btmtk.c +33 -0
@@ -929,6 +929,39 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id) }EXPORT_SYMBOL_GPL (btmtk_usb_subsys_reset); +int btmtk_usb_recv_acl (struct hci_dev *hdev,struct sk_buff *skb) +{ +struct btmtk_data *data =hci_get_priv (hdev); +u16 handle =le16_to_cpu (hci_acl_hdr (skb)->handle); + +switch (handle) { +case 0xfc6f :/* Firmware dump from device */ +/* When the firmware hangs, the device can no longer +* suspend and thus disable auto-suspend. +*/ +usb_disable_autosuspend (data->udev); + +/* We need to forward the diagnostic packet to userspace daemon +* for backward compatibility, so we have to clone the packet +* extraly for the in-kernel coredump support. +*/ +if (IS_ENABLED (CONFIG_DEV_COREDUMP )) { +struct sk_buff *skb_cd =skb_clone (skb,GFP_ATOMIC ); + +if (skb_cd) +btmtk_process_coredump (hdev, skb_cd); + } + + fallthrough; +case 0x05ff :/* Firmware debug logging 1 */ +case 0x05fe :/* Firmware debug logging 2 */ +return hci_recv_diag (hdev, skb); + } + +return hci_recv_frame (hdev, skb); +} +EXPORT_SYMBOL_GPL (btmtk_usb_recv_acl); +int btmtk_usb_setup (struct hci_dev *hdev) {struct btmtk_data *btmtk_data =hci_get_priv (hdev);
drivers/bluetooth/btmtk.h +7 -0
@@ -193,6 +193,8 @@ void btmtk_fw_get_filename(char *buf, size_t size, u32 dev_id, u32 fw_ver,int btmtk_usb_subsys_reset (struct hci_dev *hdev,u32 dev_id); +int btmtk_usb_recv_acl (struct hci_dev *hdev,struct sk_buff *skb); +int btmtk_usb_setup (struct hci_dev *hdev);int btmtk_usb_shutdown (struct hci_dev *hdev);
@@ -241,6 +243,11 @@ static int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)return -EOPNOTSUPP ; } +static int btmtk_usb_recv_acl (struct hci_dev *hdev,struct sk_buff *skb) +{ +return -EOPNOTSUPP ; +} +static int btmtk_usb_setup (struct hci_dev *hdev) {return -EOPNOTSUPP ;
drivers/bluetooth/btusb.c +1 -33
@@ -2690,38 +2690,6 @@ static int btusb_mtk_shutdown(struct hci_dev *hdev)return btmtk_usb_shutdown (hdev); } -static int btusb_recv_acl_mtk (struct hci_dev *hdev,struct sk_buff *skb) -{ -struct btusb_data *data =hci_get_drvdata (hdev); -u16 handle =le16_to_cpu (hci_acl_hdr (skb)->handle); - -switch (handle) { -case 0xfc6f :/* Firmware dump from device */ -/* When the firmware hangs, the device can no longer -* suspend and thus disable auto-suspend. -*/ -usb_disable_autosuspend (data->udev); - -/* We need to forward the diagnostic packet to userspace daemon -* for backward compatibility, so we have to clone the packet -* extraly for the in-kernel coredump support. -*/ -if (IS_ENABLED (CONFIG_DEV_COREDUMP )) { -struct sk_buff *skb_cd =skb_clone (skb,GFP_ATOMIC ); - -if (skb_cd) -btmtk_process_coredump (hdev, skb_cd); - } - - fallthrough; -case 0x05ff :/* Firmware debug logging 1 */ -case 0x05fe :/* Firmware debug logging 2 */ -return hci_recv_diag (hdev, skb); - } - -return hci_recv_frame (hdev, skb); -} -#ifdef CONFIG_PM /* Configure an out-of-band gpio as wake-up pin, if specified in device tree */ static int marvell_config_oob_wake (struct hci_dev *hdev)
@@ -3827,7 +3795,7 @@ static int btusb_probe(struct usb_interface *intf, hdev->set_bdaddr = btmtk_set_bdaddr;set_bit (HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN , &hdev->quirks);set_bit (HCI_QUIRK_NON_PERSISTENT_SETUP , &hdev->quirks); - data->recv_acl = btusb_recv_acl_mtk; + data->recv_acl = btmtk_usb_recv_acl; }if (id->driver_info &BTUSB_SWAVE ) {
Signature · 1 line
2.18.0
PATCH v5 8/8 Bluetooth: btusb: mediatek: add ISO data transmission functions
In reply to Chris LuThis patch implements functions for ISO data send and receive in btusb driver for MediaTek's controller.
MediaTek defines a specific interrupt endpoint for ISO data transmissin because the characteristics of interrupt endpoint are similar to the application of ISO data which can support guaranteed transmissin bandwidth, enough maximum data length and error checking mechanism.
Driver sets up ISO interface and endpoints in btusb_mtk_setup and clears the setup in btusb_mtk_shutdown. These flow can't move to btmtk.c due to btusb_driver is only defined in btusb.c when claiming/relaesing interface. ISO packet anchor stops when driver suspending and resubmit interrupt urb for ISO data when driver resuming.
--- drivers/bluetooth/btmtk.c | 303 ++++++++++++++++++++++++++++++++++++++ drivers/bluetooth/btmtk.h | 36 +++++ drivers/bluetooth/btusb.c | 68 +++++++++ 3 files changed, 407 insertions(+)
drivers/bluetooth/btmtk.c +303 -0
@@ -21,6 +21,9 @@#define MTK_SEC_MAP_COMMON_SIZE 12#define MTK_SEC_MAP_NEED_SEND_SIZE 52 +/* It is for mt79xx iso data transmission setting */ +#define MTK_ISO_THRESHOLD 264 +struct btmtk_patch_header {u8 datetime[16 ];u8 platform[4 ];
@@ -962,6 +965,300 @@ int btmtk_usb_recv_acl(struct hci_dev *hdev, struct sk_buff *skb) }EXPORT_SYMBOL_GPL (btmtk_usb_recv_acl); +static int btmtk_isopkt_pad (struct hci_dev *hdev,struct sk_buff *skb) +{ +if (skb->len >MTK_ISO_THRESHOLD ) +return -EINVAL ; + +if (skb_pad (skb,MTK_ISO_THRESHOLD - skb->len)) +return -ENOMEM ; + +__skb_put (skb,MTK_ISO_THRESHOLD - skb->len); + +return 0 ; +} + +static int __set_mtk_intr_interface (struct hci_dev *hdev) +{ +struct btmtk_data *btmtk_data =hci_get_priv (hdev); +struct usb_interface *intf = btmtk_data->isopkt_intf; +int i, err; + +if (!btmtk_data->isopkt_intf) +return -ENODEV ; + + err =usb_set_interface (btmtk_data->udev,MTK_ISO_IFNUM ,1 ); +if (err <0 ) { +bt_dev_err (hdev,"setting interface failed (%d)" , -err); +return err; + } + + btmtk_data->isopkt_tx_ep =NULL ; + btmtk_data->isopkt_rx_ep =NULL ; + +for (i =0 ; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { +struct usb_endpoint_descriptor *ep_desc; + + ep_desc = &intf->cur_altsetting->endpoint[i].desc; + +if (!btmtk_data->isopkt_tx_ep && +usb_endpoint_is_int_out (ep_desc)) { + btmtk_data->isopkt_tx_ep = ep_desc; +continue ; + } + +if (!btmtk_data->isopkt_rx_ep && +usb_endpoint_is_int_in (ep_desc)) { + btmtk_data->isopkt_rx_ep = ep_desc; +continue ; + } + } + +if (!btmtk_data->isopkt_tx_ep || + !btmtk_data->isopkt_rx_ep) { +bt_dev_err (hdev,"invalid interrupt descriptors" ); +return -ENODEV ; + } + +return 0 ; +} + +struct urb *alloc_mtk_intr_urb (struct hci_dev *hdev,struct sk_buff *skb, +usb_complete_t tx_complete) +{ +struct btmtk_data *btmtk_data =hci_get_priv (hdev); +struct urb *urb; +unsigned int pipe; + +if (!btmtk_data->isopkt_tx_ep) +return ERR_PTR (-ENODEV ); + + urb =usb_alloc_urb (0 ,GFP_KERNEL ); +if (!urb) +return ERR_PTR (-ENOMEM ); + +if (btmtk_isopkt_pad (hdev, skb)) +return ERR_PTR (-EINVAL ); + + pipe =usb_sndintpipe (btmtk_data->udev, + btmtk_data->isopkt_tx_ep->bEndpointAddress); + +usb_fill_int_urb (urb, btmtk_data->udev, pipe, + skb->data, skb->len, tx_complete, + skb, btmtk_data->isopkt_tx_ep->bInterval); + + skb->dev = (void *)hdev; + +return urb; +} +EXPORT_SYMBOL_GPL (alloc_mtk_intr_urb); + +static int btmtk_recv_isopkt (struct hci_dev *hdev,void *buffer,int count) +{ +struct btmtk_data *btmtk_data =hci_get_priv (hdev); +struct sk_buff *skb; +unsigned long flags; +int err =0 ; + +spin_lock_irqsave (&btmtk_data->isorxlock, flags); + skb = btmtk_data->isopkt_skb; + +while (count) { +int len; + +if (!skb) { + skb =bt_skb_alloc (HCI_MAX_ISO_SIZE ,GFP_ATOMIC ); +if (!skb) { + err = -ENOMEM ; +break ; + } + +hci_skb_pkt_type (skb) =HCI_ISODATA_PKT ; +hci_skb_expect (skb) =HCI_ISO_HDR_SIZE ; + } + + len =min_t (uint,hci_skb_expect (skb), count); +skb_put_data (skb, buffer, len); + + count -= len; + buffer += len; +hci_skb_expect (skb) -= len; + +if (skb->len ==HCI_ISO_HDR_SIZE ) { +__le16 dlen = ((struct hci_iso_hdr *)skb->data)->dlen; + +/* Complete ISO header */ +hci_skb_expect (skb) =__le16_to_cpu (dlen); + +if (skb_tailroom (skb) <hci_skb_expect (skb)) { +kfree_skb (skb); + skb =NULL ; + + err = -EILSEQ ; +break ; + } + } + +if (!hci_skb_expect (skb)) { +/* Complete frame */ +hci_recv_frame (hdev, skb); + skb =NULL ; + } + } + + btmtk_data->isopkt_skb = skb; +spin_unlock_irqrestore (&btmtk_data->isorxlock, flags); + +return err; +} + +static void btmtk_intr_complete (struct urb *urb) +{ +struct hci_dev *hdev = urb->context; +struct btmtk_data *btmtk_data =hci_get_priv (hdev); +int err; + +BT_DBG ("%s urb %p status %d count %d" , hdev->name, urb, urb->status, + urb->actual_length); + +if (!test_bit (HCI_RUNNING , &hdev->flags)) +return ; + +if (hdev->suspended) +return ; + +if (urb->status ==0 ) { + hdev->stat.byte_rx += urb->actual_length; + +if (btmtk_recv_isopkt (hdev, urb->transfer_buffer, + urb->actual_length) <0 ) { +bt_dev_err (hdev,"corrupted iso packet" ); + hdev->stat.err_rx++; + } + }else if (urb->status == -ENOENT ) { +/* Avoid suspend failed when usb_kill_urb */ +return ; + } + +usb_mark_last_busy (btmtk_data->udev); +usb_anchor_urb (urb, &btmtk_data->isopkt_anchor); + + err =usb_submit_urb (urb,GFP_ATOMIC ); +if (err <0 ) { +/* -EPERM: urb is being killed; +* -ENODEV: device got disconnected +*/ +if (err != -EPERM && err != -ENODEV ) +bt_dev_err (hdev,"urb %p failed to resubmit (%d)" , + urb, -err); +if (err != -EPERM ) +hci_cmd_sync_cancel (hdev, -err); +usb_unanchor_urb (urb); + } +} + +static int btmtk_submit_intr_urb (struct hci_dev *hdev,gfp_t mem_flags) +{ +struct btmtk_data *btmtk_data =hci_get_priv (hdev); +unsigned char *buf; +unsigned int pipe; +struct urb *urb; +int err, size; + +BT_DBG ("%s" , hdev->name); + +if (!btmtk_data->isopkt_rx_ep) +return -ENODEV ; + + urb =usb_alloc_urb (0 , mem_flags); +if (!urb) +return -ENOMEM ; + size =le16_to_cpu (btmtk_data->isopkt_rx_ep->wMaxPacketSize); + + buf =kmalloc (size, mem_flags); +if (!buf) { +usb_free_urb (urb); +return -ENOMEM ; + } + + pipe =usb_rcvintpipe (btmtk_data->udev, + btmtk_data->isopkt_rx_ep->bEndpointAddress); + +usb_fill_int_urb (urb, btmtk_data->udev, pipe, buf, size, + btmtk_intr_complete, hdev, + btmtk_data->isopkt_rx_ep->bInterval); + + urb->transfer_flags |=URB_FREE_BUFFER ; + +usb_mark_last_busy (btmtk_data->udev); +usb_anchor_urb (urb, &btmtk_data->isopkt_anchor); + + err =usb_submit_urb (urb, mem_flags); +if (err <0 ) { +if (err != -EPERM && err != -ENODEV ) +bt_dev_err (hdev,"urb %p submission failed (%d)" , + urb, -err); +usb_unanchor_urb (urb); + } + +usb_free_urb (urb); + +return err; +} + +static int btmtk_usb_isointf_init (struct hci_dev *hdev) +{ +struct btmtk_data *btmtk_data =hci_get_priv (hdev); +u8 iso_param[2 ] = {0x08 ,0x01 }; +struct sk_buff *skb; +int err; + +init_usb_anchor (&btmtk_data->isopkt_anchor); +spin_lock_init (&btmtk_data->isorxlock); + +__set_mtk_intr_interface (hdev); + + err =btmtk_submit_intr_urb (hdev,GFP_KERNEL ); +if (err <0 ) { +btmtk_usb_isopkt_stop (hdev); +bt_dev_err (hdev,"ISO intf not support (%d)" , err); +return err; + } + + skb =__hci_cmd_sync (hdev,0xfd98 ,sizeof (iso_param), iso_param, +HCI_INIT_TIMEOUT ); +if (IS_ERR (skb)) { +bt_dev_err (hdev,"Failed to apply iso setting (%ld)" ,PTR_ERR (skb)); +return PTR_ERR (skb); + } +kfree_skb (skb); + +return 0 ; +} + +int btmtk_usb_isopkt_start (struct hci_dev *hdev) +{ +struct btmtk_data *btmtk_data =hci_get_priv (hdev); + +if (test_bit (BTMTK_ISOPKT_RUNNING , &btmtk_data->flags)) { +if (btmtk_submit_intr_urb (hdev,GFP_NOIO ) <0 ) +clear_bit (BTMTK_ISOPKT_RUNNING , &btmtk_data->flags); + } + +return 0 ; +} +EXPORT_SYMBOL_GPL (btmtk_usb_isopkt_start); + +int btmtk_usb_isopkt_stop (struct hci_dev *hdev) +{ +struct btmtk_data *btmtk_data =hci_get_priv (hdev); + +usb_kill_anchored_urbs (&btmtk_data->isopkt_anchor); + +return 0 ; +} +EXPORT_SYMBOL_GPL (btmtk_usb_isopkt_stop); +int btmtk_usb_setup (struct hci_dev *hdev) {struct btmtk_data *btmtk_data =hci_get_priv (hdev);
@@ -1063,6 +1360,12 @@ int btmtk_usb_setup(struct hci_dev *hdev)hci_set_msft_opcode (hdev,0xFD30 );hci_set_aosp_capable (hdev); +/* Set up ISO interface after protocol enabled */ +if (test_bit (BTMTK_ISOPKT_OVER_INTR , &btmtk_data->flags)) { +if (!btmtk_usb_isointf_init (hdev)) +set_bit (BTMTK_ISOPKT_RUNNING , &btmtk_data->flags); + } + goto done;default : bt_dev_err(hdev, "Unsupported hardware variant (%08x)",
drivers/bluetooth/btmtk.h +36 -0
@@ -42,6 +42,9 @@#define MTK_BT_RESET_REG_CONNV3 0x70028610#define MTK_BT_READ_DEV_ID 0x70010200 +/* MediaTek ISO Interface */ +#define MTK_ISO_IFNUM 2 +enum {BTMTK_WMT_PATCH_DWNLD =0x1 ,BTMTK_WMT_TEST =0x2 ,
@@ -144,6 +147,8 @@ enum {BTMTK_TX_WAIT_VND_EVT ,BTMTK_FIRMWARE_LOADED ,BTMTK_HW_RESET_ACTIVE , +BTMTK_ISOPKT_OVER_INTR , + BTMTK_ISOPKT_RUNNING, };typedef int (*btmtk_reset_sync_func_t )(struct hci_dev *,void *);
@@ -166,6 +171,14 @@ struct btmtk_data {struct usb_interface *intf;struct usb_anchor *ctrl_anchor;struct sk_buff *evt_skb; +struct usb_endpoint_descriptor *isopkt_tx_ep; +struct usb_endpoint_descriptor *isopkt_rx_ep; +struct usb_interface *isopkt_intf; +struct usb_anchor isopkt_anchor; +struct sk_buff *isopkt_skb; + +/* spinlock for ISO data transmission */ +spinlock_t isorxlock; }; typedef int (*wmt_cmd_sync_func_t)(struct hci_dev *,
@@ -195,6 +208,13 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id);int btmtk_usb_recv_acl (struct hci_dev *hdev,struct sk_buff *skb); +struct urb *alloc_mtk_intr_urb (struct hci_dev *hdev,struct sk_buff *skb, +usb_complete_t tx_complete); + +int btmtk_usb_isopkt_start (struct hci_dev *hdev); + +int btmtk_usb_isopkt_stop (struct hci_dev *hdev); +int btmtk_usb_setup (struct hci_dev *hdev);int btmtk_usb_shutdown (struct hci_dev *hdev);
@@ -248,6 +268,22 @@ static int btmtk_usb_recv_acl(struct hci_dev *hdev, struct sk_buff *skb)return -EOPNOTSUPP ; } +static struct urb *alloc_mtk_intr_urb (struct hci_dev *hdev,struct sk_buff *skb, +usb_complete_t tx_complete) +{ +return PTR_ERR (-EOPNOTSUPP ); +} + +static int btmtk_usb_isopkt_start (struct hci_dev *hdev) +{ +return -EOPNOTSUPP ; +} + +static int btmtk_usb_isopkt_stop (struct hci_dev *hdev) +{ +return -EOPNOTSUPP ; +} +static int btmtk_usb_setup (struct hci_dev *hdev) {return -EOPNOTSUPP ;
drivers/bluetooth/btusb.c +68 -0
106 lines not on this page · raw message
Signature · 1 line
2.18.0
kernel test robot
build botRe: [PATCH v5 8/8] Bluetooth: btusb: mediatek: add ISO data transmission functions
kernel test robot noticed the following build errors:
Hi Chris,
kernel test robot noticed the following build errors:
[auto build test ERROR on bluetooth-next/master]
[also build test ERROR on next-20240626]
[cannot apply to bluetooth/master linus/master v6.10-rc5] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Chris-Lu/Bluetooth-btusb-mediatek-remove-the-unnecessary-goto-tag/20240626-114003 base: https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master patch link: https://lore.kernel.org/r/20240626025329.26424-9-chris.lu%40mediatek.com patch subject: [PATCH v5 8/8] Bluetooth: btusb: mediatek: add ISO data transmission functions config: i386-buildonly-randconfig-003-20240627 (https://download.01.org/0day-ci/archive/20240628/[email protected]/config) compiler: clang version 18.1.5 (https://github.com/llvm/llvm-project 617a15a9eac96088ae5e9134248d8236e34b91b1) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240628/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>):
In file included from drivers/bluetooth/btusb.c:28:
>> drivers/bluetooth/btmtk.h:274:17: error: incompatible integer to pointer conversion passing 'int' to parameter of type 'const void *' [-Wint-conversion]
274 | return PTR_ERR(-EOPNOTSUPP);
| ^~~~~~~~~~~
include/linux/err.h:49:61: note: passing argument to parameter 'ptr' here
49 | static inline long __must_check PTR_ERR(__force const void *ptr)
| ^
In file included from drivers/bluetooth/btusb.c:28:
>> drivers/bluetooth/btmtk.h:274:9: error: incompatible integer to pointer conversion returning 'long' from a function with result type 'struct urb *' [-Wint-conversion]
274 | return PTR_ERR(-EOPNOTSUPP);
| ^~~~~~~~~~~~~~~~~~~~2 errors generated.
vim +274 drivers/bluetooth/btmtk.h
270
271 static struct urb *alloc_mtk_intr_urb(struct hci_dev *hdev, struct sk_buff *skb,
272 usb_complete_t tx_complete)
273 {
> 274 return PTR_ERR(-EOPNOTSUPP);
275 }
276
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
kernel test robot
build botRe: [PATCH v5 8/8] Bluetooth: btusb: mediatek: add ISO data transmission functions
In reply to Chris Lukernel test robot noticed the following build warnings:
Hi Chris,
kernel test robot noticed the following build warnings:
[auto build test WARNING on bluetooth-next/master]
[also build test WARNING on next-20240626]
[cannot apply to bluetooth/master linus/master v6.10-rc5] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Chris-Lu/Bluetooth-btusb-mediatek-remove-the-unnecessary-goto-tag/20240626-114003 base: https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master patch link: https://lore.kernel.org/r/20240626025329.26424-9-chris.lu%40mediatek.com patch subject: [PATCH v5 8/8] Bluetooth: btusb: mediatek: add ISO data transmission functions config: mips-lemote2f_defconfig (https://download.01.org/0day-ci/archive/20240628/[email protected]/config) compiler: mips64el-linux-gcc (GCC) 13.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240628/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All warnings (new ones prefixed by >>):
In file included from drivers/bluetooth/btusb.c:28:
drivers/bluetooth/btmtk.h: In function 'alloc_mtk_intr_urb':
>> drivers/bluetooth/btmtk.h:274:24: warning: passing argument 1 of 'PTR_ERR' makes pointer from integer without a cast [-Wint-conversion]
274 | return PTR_ERR(-EOPNOTSUPP);
In file included from include/linux/kernfs.h:9,
from include/linux/sysfs.h:16,
from include/linux/kobject.h:20,
from include/linux/dmi.h:6,
from drivers/bluetooth/btusb.c:9:
include/linux/err.h:49:61: note: expected 'const void *' but argument is of type 'int'
49 | static inline long __must_check PTR_ERR(__force const void *ptr)
| ~~~~~~~~~~~~^~~
>> drivers/bluetooth/btmtk.h:274:16: warning: returning 'long int' from a function with return type 'struct urb *' makes pointer from integer without a cast [-Wint-conversion]
274 | return PTR_ERR(-EOPNOTSUPP);
| ^~~~~~~~~~~~~~~~~~~~ drivers/bluetooth/btmtk.h: At top level:
drivers/bluetooth/btmtk.h:256:13: warning: 'btmtk_fw_get_filename' defined but not used [-Wunused-function]
256 | static void btmtk_fw_get_filename(char *buf, size_t size, u32 dev_id,
| ^~~~~~~~~~~~~~~~~~~~~
drivers/bluetooth/btmtk.h:251:12: warning: 'btmtk_process_coredump' defined but not used [-Wunused-function]
251 | static int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
| ^~~~~~~~~~~~~~~~~~~~~~
drivers/bluetooth/btmtk.h:245:12: warning: 'btmtk_register_coredump' defined but not used [-Wunused-function]
245 | static int btmtk_register_coredump(struct hci_dev *hdev, const char *name,
| ^~~~~~~~~~~~~~~~~~~~~~~
drivers/bluetooth/btmtk.h:235:12: warning: 'btmtk_setup_firmware' defined but not used [-Wunused-function]
235 | static int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
| ^~~~~~~~~~~~~~~~~~~~
drivers/bluetooth/btmtk.h:229:12: warning: 'btmtk_setup_firmware_79xx' defined but not used [-Wunused-function]
229 | static int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
| ^~~~~~~~~~~~~~~~~~~~~~~~~
vim +/PTR_ERR +274 drivers/bluetooth/btmtk.h
270
271 static struct urb *alloc_mtk_intr_urb(struct hci_dev *hdev, struct sk_buff *skb,
272 usb_complete_t tx_complete)
273 {
> 274 return PTR_ERR(-EOPNOTSUPP);
275 }
276
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki