Hi Pavel, On Tue, Jun 11, 2013, Johan Hedberg wrote: > On Mon, Jun 10, 2013, Pavel Machek wrote: > > < HCI Command: Delete Stored Link Key (0x03|0x0012) plen 7 > > bdaddr 00:00:00:00:00:00 all 1 > > > HCI Event: Command Complete (0x0e) plen 4 > > Delete Stored Link Key (0x03|0x0012) ncmd 1 > > status 0x11 deleted 0 > > Error: Unsupported Feature or Parameter Value > > Here's the cause of your issue. It's not one of the recently added HCI > commands but one that's been around for quite some time. I just checked > and it's even there in kernel 3.9, so I'm surprised that you're saying > this is a regression since that version. Are you completely sure about > it? Could you try if the attached patch helps? It modifies the HCI request state tracking to allow flagging certain HCI commands as non-critical and just ignores their failures. If the patch helps, could you still provide a HCI trace (both plain text and btsnoop format) of a successful "hciconfig hci0 up"? It might help create a simpler patch for this issue. Johan
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 10eb9b3..2ee2520 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -265,6 +265,7 @@ typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status); struct hci_req_ctrl { bool start; + bool ignore_status; u8 event; hci_req_complete_t complete; }; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 7cb6d36..f1d7500 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1084,7 +1084,7 @@ int hci_req_run(struct hci_request *req, hci_req_complete_t complete); void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, const void *param); void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, - const void *param, u8 event); + const void *param, u8 event, bool ignore_status); void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status); struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen, diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index d817c93..c3d5056 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -145,7 +145,7 @@ struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen, hci_req_init(&req, hdev); - hci_req_add_ev(&req, opcode, plen, param, event); + hci_req_add_ev(&req, opcode, plen, param, event, false); hdev->req_status = HCI_REQ_PEND; @@ -367,7 +367,8 @@ static void bredr_setup(struct hci_request *req) bacpy(&cp.bdaddr, BDADDR_ANY); cp.delete_all = 0x01; - hci_req_add(req, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp); + hci_req_add_ev(req, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp, + 0, true); /* Read page scan parameters */ if (req->hdev->hci_ver > BLUETOOTH_VER_1_1) { @@ -2669,7 +2670,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, /* Queue a command to an asynchronous HCI request */ void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, - const void *param, u8 event) + const void *param, u8 event, bool ignore_status) { struct hci_dev *hdev = req->hdev; struct sk_buff *skb; @@ -2694,6 +2695,7 @@ void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, bt_cb(skb)->req.start = true; bt_cb(skb)->req.event = event; + bt_cb(skb)->req.ignore_status = ignore_status; skb_queue_tail(&req->cmd_q, skb); } @@ -2701,7 +2703,7 @@ void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, const void *param) { - hci_req_add_ev(req, opcode, plen, param, 0); + hci_req_add_ev(req, opcode, plen, param, 0, false); } /* Get data from the previously sent command */ @@ -3425,6 +3427,10 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status) return; } + /* Check for commands whose failures aren't critical */ + if (bt_cb(hdev->sent_cmd)->req.ignore_status) + status = 0; + /* If the command succeeded and there's still more commands in * this request the request is not yet complete. */