Message ID | 429cbc5a4fcdb150c62cf368c928e1174016eefb.1691606987.git.pav@iki.fi (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | [BlueZ] adapter: wait for kernel exp features in adapter initialization | expand |
Context | Check | Description |
---|---|---|
tedd_an/pre-ci_am | success | Success |
tedd_an/CheckPatch | warning | WARNING:COMMIT_LOG_LONG_LINE: Possible unwrapped commit description (prefer a maximum 75 chars per line) #90: bluetoothd[981]: src/adapter.c:read_exp_features_complete() 6fbaf188-05e0-496a-9885-d6ddfdb4e03e flags 0 action 1 /github/workspace/src/src/13348341.patch total: 0 errors, 1 warnings, 176 lines checked NOTE: For some of the reported defects, checkpatch may be able to mechanically convert to the typical style using --fix or --fix-inplace. /github/workspace/src/src/13348341.patch has style problems, please review. NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO NOTE: If any of the errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS. |
tedd_an/GitLint | fail | WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python regex 'match' (match beginning) to 'search' (match anywhere) semantics. Please review your ignore-body-lines.regex option accordingly. To remove this warning, set general.regex-style-search=True. More details: https://jorisroovers.github.io/gitlint/configuration/#regex-style-search 12: B1 Line exceeds max length (113>80): "bluetoothd[981]: src/adapter.c:read_exp_features_complete() 6fbaf188-05e0-496a-9885-d6ddfdb4e03e flags 0 action 1" 14: B1 Line exceeds max length (94>80): "bluetoothd[981]: profiles/audio/bap.c:bap_probe() BAP requires ISO Socket which is not enabled" |
tedd_an/BuildEll | success | Build ELL PASS |
tedd_an/BluezMake | success | Bluez Make PASS |
tedd_an/MakeCheck | success | Bluez Make Check PASS |
tedd_an/MakeDistcheck | success | Make Distcheck PASS |
tedd_an/CheckValgrind | success | Check Valgrind PASS |
tedd_an/CheckSmatch | success | CheckSparse PASS |
tedd_an/bluezmakeextell | success | Make External ELL PASS |
tedd_an/IncrementalBuild | success | Incremental Build PASS |
tedd_an/ScanBuild | success | Scan Build PASS |
Hi Pauli, On Wed, Aug 9, 2023 at 12:14 PM Pauli Virtanen <pav@iki.fi> wrote: > > Things like BAP depend on ISO sockets being enabled in kernel. It is > possible the MGMT commands enabling experimental kernel features do not > complete, before BAP etc. initialization and probing starts, in which > case BAP will be mostly nonfunctional. > > This was observed to occur always when running BlueZ in a Fedora VM, > requiring bluetoothd restart after every boot for BAP to work, > log containing lines in the order: > > bluetoothd[981]: src/adapter.c:read_exp_features_complete() 6fbaf188-05e0-496a-9885-d6ddfdb4e03e flags 0 action 1 > bluetoothd[981]: src/adapter.c:read_info_complete() index 0 status 0x00 > bluetoothd[981]: profiles/audio/bap.c:bap_probe() BAP requires ISO Socket which is not enabled > bluetoothd[981]: src/adapter.c:iso_socket_complete() ISO Socket successfully set > > Fix by waiting in adapter initialization that all MGMT exp feature > requests are done, before proceeding to read adapter information. > > Also fix canceling MGMT_OP_SET_EXP_FEATURE for ISO sockets. > --- > src/adapter.c | 90 ++++++++++++++++++++++++++++++++++++++++----------- > 1 file changed, 71 insertions(+), 19 deletions(-) > > diff --git a/src/adapter.c b/src/adapter.c > index 004062e7c..608c06f9e 100644 > --- a/src/adapter.c > +++ b/src/adapter.c > @@ -331,6 +331,8 @@ struct btd_adapter { > > bool is_default; /* true if adapter is default one */ > > + unsigned int set_exp_iso_id; > + unsigned int exp_pending; Lets use a struct queue to store these ids, since there could be more than one pending and there could be more of these races with other drivers. > struct queue *exps; > }; > > @@ -5782,6 +5784,8 @@ static void adapter_free(gpointer user_data) > g_queue_free(adapter->auths); > queue_destroy(adapter->exps, NULL); > > + adapter->exp_pending = 0; > + > /* > * Unregister all handlers for this specific index since > * the adapter bound to them is no longer valid. > @@ -5796,6 +5800,8 @@ static void adapter_free(gpointer user_data) > * since the adapter bound to them is no longer valid. > */ > mgmt_cancel_index(adapter->mgmt, adapter->dev_id); > + if (adapter->set_exp_iso_id) > + mgmt_cancel(adapter->mgmt, adapter->set_exp_iso_id); > > mgmt_unref(adapter->mgmt); > > @@ -6895,6 +6901,8 @@ static void adapter_remove(struct btd_adapter *adapter) > > g_slist_free(adapter->msd_callbacks); > adapter->msd_callbacks = NULL; > + > + adapter->exp_pending = 0; > } > > const char *adapter_get_path(struct btd_adapter *adapter) > @@ -9824,6 +9832,8 @@ static bool set_blocked_keys(struct btd_adapter *adapter) > .func = _func, \ > } > > +static void exp_complete(void *user_data); > + > static void set_exp_debug_complete(uint8_t status, uint16_t len, > const void *param, void *user_data) > { > @@ -9854,8 +9864,10 @@ static void exp_debug_func(struct btd_adapter *adapter, uint8_t action) > > if (mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE, > adapter->dev_id, sizeof(cp), &cp, > - set_exp_debug_complete, adapter, NULL) > 0) > + set_exp_debug_complete, adapter, exp_complete) > 0) { > + ++adapter->exp_pending; > return; > + } > > btd_error(adapter->dev_id, "Failed to set exp debug"); > } > @@ -9904,8 +9916,11 @@ static void rpa_resolution_func(struct btd_adapter *adapter, uint8_t action) > > if (mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE, > adapter->dev_id, sizeof(cp), &cp, > - set_rpa_resolution_complete, adapter, NULL) > 0) > + set_rpa_resolution_complete, adapter, > + exp_complete) > 0) { > + ++adapter->exp_pending; > return; > + } > > btd_error(adapter->dev_id, "Failed to set RPA Resolution"); > } > @@ -9940,12 +9955,22 @@ static void codec_offload_func(struct btd_adapter *adapter, uint8_t action) > > if (mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE, > adapter->dev_id, sizeof(cp), &cp, > - codec_offload_complete, adapter, NULL) > 0) > + codec_offload_complete, adapter, exp_complete) > 0) { > + ++adapter->exp_pending; > return; > + } > > btd_error(adapter->dev_id, "Failed to set Codec Offload"); > } > > +static void iso_socket_done(void *user_data) > +{ > + struct btd_adapter *adapter = user_data; > + > + adapter->set_exp_iso_id = 0; > + exp_complete(adapter); > +} > + > static void iso_socket_complete(uint8_t status, uint16_t len, > const void *param, void *user_data) > { > @@ -9969,15 +9994,20 @@ static void iso_socket_complete(uint8_t status, uint16_t len, > static void iso_socket_func(struct btd_adapter *adapter, uint8_t action) > { > struct mgmt_cp_set_exp_feature cp; > + unsigned int id; > > memset(&cp, 0, sizeof(cp)); > memcpy(cp.uuid, iso_socket_uuid.val, 16); > cp.action = action; > > - if (mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE, > - MGMT_INDEX_NONE, sizeof(cp), &cp, > - iso_socket_complete, adapter, NULL) > 0) > + id = mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE, MGMT_INDEX_NONE, > + sizeof(cp), &cp, iso_socket_complete, adapter, > + iso_socket_done); > + if (id > 0) { > + adapter->set_exp_iso_id = id; > + ++adapter->exp_pending; > return; > + } > > btd_error(adapter->dev_id, "Failed to set ISO Socket"); > } > @@ -10063,8 +10093,10 @@ static void read_exp_features(struct btd_adapter *adapter) > { > if (mgmt_send(adapter->mgmt, MGMT_OP_READ_EXP_FEATURES_INFO, > adapter->dev_id, 0, NULL, read_exp_features_complete, > - adapter, NULL) > 0) > + adapter, exp_complete) > 0) { > + ++adapter->exp_pending; > return; > + } > > btd_error(adapter->dev_id, "Failed to read exp features info"); > } > @@ -10389,6 +10421,36 @@ static void reset_adv_monitors(uint16_t index) > error("Failed to reset Adv Monitors"); > } > > +static void read_info(struct btd_adapter *adapter) > +{ > + DBG("sending read info command for index %u", adapter->dev_id); > + > + if (mgmt_send(mgmt_primary, MGMT_OP_READ_INFO, adapter->dev_id, 0, NULL, > + read_info_complete, adapter, NULL) > 0) > + return; > + > + btd_error(adapter->dev_id, > + "Failed to read controller info for index %u", > + adapter->dev_id); > + > + adapter_list = g_list_remove(adapter_list, adapter); > + > + btd_adapter_unref(adapter); > +} > + > +static void exp_complete(void *user_data) > +{ > + struct btd_adapter *adapter = user_data; > + > + adapter->exp_pending--; > + > + DBG("index %u has %u pending MGMT EXP requests", adapter->dev_id, > + adapter->exp_pending); > + > + if (!adapter->exp_pending) > + read_info(adapter); > +} > + > static void index_added(uint16_t index, uint16_t length, const void *param, > void *user_data) > { > @@ -10435,18 +10497,8 @@ static void index_added(uint16_t index, uint16_t length, const void *param, > */ > adapter_list = g_list_append(adapter_list, adapter); > > - DBG("sending read info command for index %u", index); > - > - if (mgmt_send(mgmt_primary, MGMT_OP_READ_INFO, index, 0, NULL, > - read_info_complete, adapter, NULL) > 0) > - return; > - > - btd_error(adapter->dev_id, > - "Failed to read controller info for index %u", index); > - > - adapter_list = g_list_remove(adapter_list, adapter); > - > - btd_adapter_unref(adapter); > + if (!adapter->exp_pending) > + read_info(adapter); > } > > static void index_removed(uint16_t index, uint16_t length, const void *param, > -- > 2.41.0 >
Hi Luiz, ke, 2023-08-09 kello 12:52 -0700, Luiz Augusto von Dentz kirjoitti: > Hi Pauli, > > On Wed, Aug 9, 2023 at 12:14 PM Pauli Virtanen <pav@iki.fi> wrote: > > > > Things like BAP depend on ISO sockets being enabled in kernel. It is > > possible the MGMT commands enabling experimental kernel features do not > > complete, before BAP etc. initialization and probing starts, in which > > case BAP will be mostly nonfunctional. > > > > This was observed to occur always when running BlueZ in a Fedora VM, > > requiring bluetoothd restart after every boot for BAP to work, > > log containing lines in the order: > > > > bluetoothd[981]: src/adapter.c:read_exp_features_complete() 6fbaf188-05e0-496a-9885-d6ddfdb4e03e flags 0 action 1 > > bluetoothd[981]: src/adapter.c:read_info_complete() index 0 status 0x00 > > bluetoothd[981]: profiles/audio/bap.c:bap_probe() BAP requires ISO Socket which is not enabled > > bluetoothd[981]: src/adapter.c:iso_socket_complete() ISO Socket successfully set > > > > Fix by waiting in adapter initialization that all MGMT exp feature > > requests are done, before proceeding to read adapter information. > > > > Also fix canceling MGMT_OP_SET_EXP_FEATURE for ISO sockets. > > --- > > src/adapter.c | 90 ++++++++++++++++++++++++++++++++++++++++----------- > > 1 file changed, 71 insertions(+), 19 deletions(-) > > > > diff --git a/src/adapter.c b/src/adapter.c > > index 004062e7c..608c06f9e 100644 > > --- a/src/adapter.c > > +++ b/src/adapter.c > > @@ -331,6 +331,8 @@ struct btd_adapter { > > > > bool is_default; /* true if adapter is default one */ > > > > + unsigned int set_exp_iso_id; > > + unsigned int exp_pending; > > Lets use a struct queue to store these ids, since there could be more > than one pending and there could be more of these races with other > drivers. Ack, I can do that maybe it is simpler. Note though the current version does wait for all mgmt calls, and cleanup should also be right. set_exp_iso_id is special since that's on MGMT_INDEX_NONE so the mgmt_cancel_index cleanup in adapter_free won't cancel it. > > > struct queue *exps; > > }; > > > > @@ -5782,6 +5784,8 @@ static void adapter_free(gpointer user_data) > > g_queue_free(adapter->auths); > > queue_destroy(adapter->exps, NULL); > > > > + adapter->exp_pending = 0; > > + > > /* > > * Unregister all handlers for this specific index since > > * the adapter bound to them is no longer valid. > > @@ -5796,6 +5800,8 @@ static void adapter_free(gpointer user_data) > > * since the adapter bound to them is no longer valid. > > */ > > mgmt_cancel_index(adapter->mgmt, adapter->dev_id); > > + if (adapter->set_exp_iso_id) > > + mgmt_cancel(adapter->mgmt, adapter->set_exp_iso_id); > > > > mgmt_unref(adapter->mgmt); > > > > @@ -6895,6 +6901,8 @@ static void adapter_remove(struct btd_adapter *adapter) > > > > g_slist_free(adapter->msd_callbacks); > > adapter->msd_callbacks = NULL; > > + > > + adapter->exp_pending = 0; > > } > > > > const char *adapter_get_path(struct btd_adapter *adapter) > > @@ -9824,6 +9832,8 @@ static bool set_blocked_keys(struct btd_adapter *adapter) > > .func = _func, \ > > } > > > > +static void exp_complete(void *user_data); > > + > > static void set_exp_debug_complete(uint8_t status, uint16_t len, > > const void *param, void *user_data) > > { > > @@ -9854,8 +9864,10 @@ static void exp_debug_func(struct btd_adapter *adapter, uint8_t action) > > > > if (mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE, > > adapter->dev_id, sizeof(cp), &cp, > > - set_exp_debug_complete, adapter, NULL) > 0) > > + set_exp_debug_complete, adapter, exp_complete) > 0) { > > + ++adapter->exp_pending; > > return; > > + } > > > > btd_error(adapter->dev_id, "Failed to set exp debug"); > > } > > @@ -9904,8 +9916,11 @@ static void rpa_resolution_func(struct btd_adapter *adapter, uint8_t action) > > > > if (mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE, > > adapter->dev_id, sizeof(cp), &cp, > > - set_rpa_resolution_complete, adapter, NULL) > 0) > > + set_rpa_resolution_complete, adapter, > > + exp_complete) > 0) { > > + ++adapter->exp_pending; > > return; > > + } > > > > btd_error(adapter->dev_id, "Failed to set RPA Resolution"); > > } > > @@ -9940,12 +9955,22 @@ static void codec_offload_func(struct btd_adapter *adapter, uint8_t action) > > > > if (mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE, > > adapter->dev_id, sizeof(cp), &cp, > > - codec_offload_complete, adapter, NULL) > 0) > > + codec_offload_complete, adapter, exp_complete) > 0) { > > + ++adapter->exp_pending; > > return; > > + } > > > > btd_error(adapter->dev_id, "Failed to set Codec Offload"); > > } > > > > +static void iso_socket_done(void *user_data) > > +{ > > + struct btd_adapter *adapter = user_data; > > + > > + adapter->set_exp_iso_id = 0; > > + exp_complete(adapter); > > +} > > + > > static void iso_socket_complete(uint8_t status, uint16_t len, > > const void *param, void *user_data) > > { > > @@ -9969,15 +9994,20 @@ static void iso_socket_complete(uint8_t status, uint16_t len, > > static void iso_socket_func(struct btd_adapter *adapter, uint8_t action) > > { > > struct mgmt_cp_set_exp_feature cp; > > + unsigned int id; > > > > memset(&cp, 0, sizeof(cp)); > > memcpy(cp.uuid, iso_socket_uuid.val, 16); > > cp.action = action; > > > > - if (mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE, > > - MGMT_INDEX_NONE, sizeof(cp), &cp, > > - iso_socket_complete, adapter, NULL) > 0) > > + id = mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE, MGMT_INDEX_NONE, > > + sizeof(cp), &cp, iso_socket_complete, adapter, > > + iso_socket_done); > > + if (id > 0) { > > + adapter->set_exp_iso_id = id; > > + ++adapter->exp_pending; > > return; > > + } > > > > btd_error(adapter->dev_id, "Failed to set ISO Socket"); > > } > > @@ -10063,8 +10093,10 @@ static void read_exp_features(struct btd_adapter *adapter) > > { > > if (mgmt_send(adapter->mgmt, MGMT_OP_READ_EXP_FEATURES_INFO, > > adapter->dev_id, 0, NULL, read_exp_features_complete, > > - adapter, NULL) > 0) > > + adapter, exp_complete) > 0) { > > + ++adapter->exp_pending; > > return; > > + } > > > > btd_error(adapter->dev_id, "Failed to read exp features info"); > > } > > @@ -10389,6 +10421,36 @@ static void reset_adv_monitors(uint16_t index) > > error("Failed to reset Adv Monitors"); > > } > > > > +static void read_info(struct btd_adapter *adapter) > > +{ > > + DBG("sending read info command for index %u", adapter->dev_id); > > + > > + if (mgmt_send(mgmt_primary, MGMT_OP_READ_INFO, adapter->dev_id, 0, NULL, > > + read_info_complete, adapter, NULL) > 0) > > + return; > > + > > + btd_error(adapter->dev_id, > > + "Failed to read controller info for index %u", > > + adapter->dev_id); > > + > > + adapter_list = g_list_remove(adapter_list, adapter); > > + > > + btd_adapter_unref(adapter); > > +} > > + > > +static void exp_complete(void *user_data) > > +{ > > + struct btd_adapter *adapter = user_data; > > + > > + adapter->exp_pending--; > > + > > + DBG("index %u has %u pending MGMT EXP requests", adapter->dev_id, > > + adapter->exp_pending); > > + > > + if (!adapter->exp_pending) > > + read_info(adapter); > > +} > > + > > static void index_added(uint16_t index, uint16_t length, const void *param, > > void *user_data) > > { > > @@ -10435,18 +10497,8 @@ static void index_added(uint16_t index, uint16_t length, const void *param, > > */ > > adapter_list = g_list_append(adapter_list, adapter); > > > > - DBG("sending read info command for index %u", index); > > - > > - if (mgmt_send(mgmt_primary, MGMT_OP_READ_INFO, index, 0, NULL, > > - read_info_complete, adapter, NULL) > 0) > > - return; > > - > > - btd_error(adapter->dev_id, > > - "Failed to read controller info for index %u", index); > > - > > - adapter_list = g_list_remove(adapter_list, adapter); > > - > > - btd_adapter_unref(adapter); > > + if (!adapter->exp_pending) > > + read_info(adapter); > > } > > > > static void index_removed(uint16_t index, uint16_t length, const void *param, > > -- > > 2.41.0 > > > >
This is automated email and please do not reply to this email! Dear submitter, Thank you for submitting the patches to the linux bluetooth mailing list. This is a CI test results with your patch series: PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=774659 ---Test result--- Test Summary: CheckPatch FAIL 0.88 seconds GitLint FAIL 0.64 seconds BuildEll PASS 27.25 seconds BluezMake PASS 971.50 seconds MakeCheck PASS 12.61 seconds MakeDistcheck PASS 172.52 seconds CheckValgrind PASS 257.26 seconds CheckSmatch PASS 343.22 seconds bluezmakeextell PASS 103.97 seconds IncrementalBuild PASS 835.52 seconds ScanBuild PASS 1057.65 seconds Details ############################## Test: CheckPatch - FAIL Desc: Run checkpatch.pl script Output: [BlueZ] adapter: wait for kernel exp features in adapter initialization WARNING:COMMIT_LOG_LONG_LINE: Possible unwrapped commit description (prefer a maximum 75 chars per line) #90: bluetoothd[981]: src/adapter.c:read_exp_features_complete() 6fbaf188-05e0-496a-9885-d6ddfdb4e03e flags 0 action 1 /github/workspace/src/src/13348341.patch total: 0 errors, 1 warnings, 176 lines checked NOTE: For some of the reported defects, checkpatch may be able to mechanically convert to the typical style using --fix or --fix-inplace. /github/workspace/src/src/13348341.patch has style problems, please review. NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO NOTE: If any of the errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS. ############################## Test: GitLint - FAIL Desc: Run gitlint Output: [BlueZ] adapter: wait for kernel exp features in adapter initialization WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python regex 'match' (match beginning) to 'search' (match anywhere) semantics. Please review your ignore-body-lines.regex option accordingly. To remove this warning, set general.regex-style-search=True. More details: https://jorisroovers.github.io/gitlint/configuration/#regex-style-search 12: B1 Line exceeds max length (113>80): "bluetoothd[981]: src/adapter.c:read_exp_features_complete() 6fbaf188-05e0-496a-9885-d6ddfdb4e03e flags 0 action 1" 14: B1 Line exceeds max length (94>80): "bluetoothd[981]: profiles/audio/bap.c:bap_probe() BAP requires ISO Socket which is not enabled" --- Regards, Linux Bluetooth
diff --git a/src/adapter.c b/src/adapter.c index 004062e7c..608c06f9e 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -331,6 +331,8 @@ struct btd_adapter { bool is_default; /* true if adapter is default one */ + unsigned int set_exp_iso_id; + unsigned int exp_pending; struct queue *exps; }; @@ -5782,6 +5784,8 @@ static void adapter_free(gpointer user_data) g_queue_free(adapter->auths); queue_destroy(adapter->exps, NULL); + adapter->exp_pending = 0; + /* * Unregister all handlers for this specific index since * the adapter bound to them is no longer valid. @@ -5796,6 +5800,8 @@ static void adapter_free(gpointer user_data) * since the adapter bound to them is no longer valid. */ mgmt_cancel_index(adapter->mgmt, adapter->dev_id); + if (adapter->set_exp_iso_id) + mgmt_cancel(adapter->mgmt, adapter->set_exp_iso_id); mgmt_unref(adapter->mgmt); @@ -6895,6 +6901,8 @@ static void adapter_remove(struct btd_adapter *adapter) g_slist_free(adapter->msd_callbacks); adapter->msd_callbacks = NULL; + + adapter->exp_pending = 0; } const char *adapter_get_path(struct btd_adapter *adapter) @@ -9824,6 +9832,8 @@ static bool set_blocked_keys(struct btd_adapter *adapter) .func = _func, \ } +static void exp_complete(void *user_data); + static void set_exp_debug_complete(uint8_t status, uint16_t len, const void *param, void *user_data) { @@ -9854,8 +9864,10 @@ static void exp_debug_func(struct btd_adapter *adapter, uint8_t action) if (mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE, adapter->dev_id, sizeof(cp), &cp, - set_exp_debug_complete, adapter, NULL) > 0) + set_exp_debug_complete, adapter, exp_complete) > 0) { + ++adapter->exp_pending; return; + } btd_error(adapter->dev_id, "Failed to set exp debug"); } @@ -9904,8 +9916,11 @@ static void rpa_resolution_func(struct btd_adapter *adapter, uint8_t action) if (mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE, adapter->dev_id, sizeof(cp), &cp, - set_rpa_resolution_complete, adapter, NULL) > 0) + set_rpa_resolution_complete, adapter, + exp_complete) > 0) { + ++adapter->exp_pending; return; + } btd_error(adapter->dev_id, "Failed to set RPA Resolution"); } @@ -9940,12 +9955,22 @@ static void codec_offload_func(struct btd_adapter *adapter, uint8_t action) if (mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE, adapter->dev_id, sizeof(cp), &cp, - codec_offload_complete, adapter, NULL) > 0) + codec_offload_complete, adapter, exp_complete) > 0) { + ++adapter->exp_pending; return; + } btd_error(adapter->dev_id, "Failed to set Codec Offload"); } +static void iso_socket_done(void *user_data) +{ + struct btd_adapter *adapter = user_data; + + adapter->set_exp_iso_id = 0; + exp_complete(adapter); +} + static void iso_socket_complete(uint8_t status, uint16_t len, const void *param, void *user_data) { @@ -9969,15 +9994,20 @@ static void iso_socket_complete(uint8_t status, uint16_t len, static void iso_socket_func(struct btd_adapter *adapter, uint8_t action) { struct mgmt_cp_set_exp_feature cp; + unsigned int id; memset(&cp, 0, sizeof(cp)); memcpy(cp.uuid, iso_socket_uuid.val, 16); cp.action = action; - if (mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE, - MGMT_INDEX_NONE, sizeof(cp), &cp, - iso_socket_complete, adapter, NULL) > 0) + id = mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE, MGMT_INDEX_NONE, + sizeof(cp), &cp, iso_socket_complete, adapter, + iso_socket_done); + if (id > 0) { + adapter->set_exp_iso_id = id; + ++adapter->exp_pending; return; + } btd_error(adapter->dev_id, "Failed to set ISO Socket"); } @@ -10063,8 +10093,10 @@ static void read_exp_features(struct btd_adapter *adapter) { if (mgmt_send(adapter->mgmt, MGMT_OP_READ_EXP_FEATURES_INFO, adapter->dev_id, 0, NULL, read_exp_features_complete, - adapter, NULL) > 0) + adapter, exp_complete) > 0) { + ++adapter->exp_pending; return; + } btd_error(adapter->dev_id, "Failed to read exp features info"); } @@ -10389,6 +10421,36 @@ static void reset_adv_monitors(uint16_t index) error("Failed to reset Adv Monitors"); } +static void read_info(struct btd_adapter *adapter) +{ + DBG("sending read info command for index %u", adapter->dev_id); + + if (mgmt_send(mgmt_primary, MGMT_OP_READ_INFO, adapter->dev_id, 0, NULL, + read_info_complete, adapter, NULL) > 0) + return; + + btd_error(adapter->dev_id, + "Failed to read controller info for index %u", + adapter->dev_id); + + adapter_list = g_list_remove(adapter_list, adapter); + + btd_adapter_unref(adapter); +} + +static void exp_complete(void *user_data) +{ + struct btd_adapter *adapter = user_data; + + adapter->exp_pending--; + + DBG("index %u has %u pending MGMT EXP requests", adapter->dev_id, + adapter->exp_pending); + + if (!adapter->exp_pending) + read_info(adapter); +} + static void index_added(uint16_t index, uint16_t length, const void *param, void *user_data) { @@ -10435,18 +10497,8 @@ static void index_added(uint16_t index, uint16_t length, const void *param, */ adapter_list = g_list_append(adapter_list, adapter); - DBG("sending read info command for index %u", index); - - if (mgmt_send(mgmt_primary, MGMT_OP_READ_INFO, index, 0, NULL, - read_info_complete, adapter, NULL) > 0) - return; - - btd_error(adapter->dev_id, - "Failed to read controller info for index %u", index); - - adapter_list = g_list_remove(adapter_list, adapter); - - btd_adapter_unref(adapter); + if (!adapter->exp_pending) + read_info(adapter); } static void index_removed(uint16_t index, uint16_t length, const void *param,