Bug 177711

Summary: Do not delete the link in the hci_core.c:hci_init4_req function
Product: Drivers Reporter: fin4478
Component: BluetoothAssignee: linux-bluetooth (linux-bluetooth)
Status: RESOLVED CODE_FIX    
Severity: blocking    
Priority: P1    
Hardware: x86-64   
OS: Linux   
Kernel Version: 4.9-rc1 Subsystem:
Regression: No Bisected commit-id:

Description fin4478 2016-10-16 07:57:15 UTC
There has been a long bug in the /net/bluetooth/hci_core.c hci_init4_req
function. My usb stick supports deleting link and and if you delete the link the stick does not work. Bluez5 file transfer feature is the only bluetooth feature I am using. 

I need to comment the if statement away. Dmesg shows my stick as:
[    1.673730] usb 5-1: New USB device found, idVendor=0a5c, idProduct=2190
[    1.673738] usb 5-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[    1.673742] usb 5-1: Product: Bluetooth V3.0 Device
[    1.673746] usb 5-1: Manufacturer: Broadcom  v3.0
[    1.673749] usb 5-1: SerialNumber: 001A7D0AC581

The product is:
http://www.gearbest.com/usb-gadgets/pp_134921.html

The following is my temporary fix. Those who know more could implement a more general solution:
static int hci_init4_req(struct hci_request *req, unsigned long opt)
{
	struct hci_dev *hdev = req->hdev;

	/* Some Broadcom based Bluetooth controllers do not support the
	 * Delete Stored Link Key command. They are clearly indicating its
	 * absence in the bit mask of supported commands.
	 *
	 * Check the supported commands and only if the the command is marked
	 * as supported send it. If not supported assume that the controller
	 * does not have actual support for stored link keys which makes this
	 * command redundant anyway.
	 *
	 * Some controllers indicate that they support handling deleting
	 * stored link keys, but they don't. The quirk lets a driver
	 * just disable this command.
	 *
	if (hdev->commands[6] & 0x80 &&
	    !test_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks)) {
		struct hci_cp_delete_stored_link_key cp;

		bacpy(&cp.bdaddr, BDADDR_ANY);
		cp.delete_all = 0x01;
		hci_req_add(req, HCI_OP_DELETE_STORED_LINK_KEY,
			    sizeof(cp), &cp);
          }
*/