@@ -804,6 +804,7 @@ struct hci_conn_params {
804804extern struct list_head hci_dev_list ;
805805extern struct list_head hci_cb_list ;
806806extern rwlock_t hci_dev_list_lock ;
807+ extern struct mutex hci_cb_list_lock ;
807808
808809#define hci_dev_set_flag (hdev , nr ) set_bit((nr), (hdev)->dev_flags)
809810#define hci_dev_clear_flag (hdev , nr ) clear_bit((nr), (hdev)->dev_flags)
@@ -2006,103 +2007,68 @@ struct hci_cb {
20062007
20072008 char * name ;
20082009
2009- bool (* match ) (struct hci_conn * conn );
20102010 void (* connect_cfm ) (struct hci_conn * conn , __u8 status );
20112011 void (* disconn_cfm ) (struct hci_conn * conn , __u8 status );
20122012 void (* security_cfm ) (struct hci_conn * conn , __u8 status ,
2013- __u8 encrypt );
2013+ __u8 encrypt );
20142014 void (* key_change_cfm ) (struct hci_conn * conn , __u8 status );
20152015 void (* role_switch_cfm ) (struct hci_conn * conn , __u8 status , __u8 role );
20162016};
20172017
2018- static inline void hci_cb_lookup (struct hci_conn * conn , struct list_head * list )
2019- {
2020- struct hci_cb * cb , * cpy ;
2021-
2022- rcu_read_lock ();
2023- list_for_each_entry_rcu (cb , & hci_cb_list , list ) {
2024- if (cb -> match && cb -> match (conn )) {
2025- cpy = kmalloc (sizeof (* cpy ), GFP_ATOMIC );
2026- if (!cpy )
2027- break ;
2028-
2029- * cpy = * cb ;
2030- INIT_LIST_HEAD (& cpy -> list );
2031- list_add_rcu (& cpy -> list , list );
2032- }
2033- }
2034- rcu_read_unlock ();
2035- }
2036-
20372018static inline void hci_connect_cfm (struct hci_conn * conn , __u8 status )
20382019{
2039- struct list_head list ;
2040- struct hci_cb * cb , * tmp ;
2041-
2042- INIT_LIST_HEAD (& list );
2043- hci_cb_lookup (conn , & list );
2020+ struct hci_cb * cb ;
20442021
2045- list_for_each_entry_safe (cb , tmp , & list , list ) {
2022+ mutex_lock (& hci_cb_list_lock );
2023+ list_for_each_entry (cb , & hci_cb_list , list ) {
20462024 if (cb -> connect_cfm )
20472025 cb -> connect_cfm (conn , status );
2048- kfree (cb );
20492026 }
2027+ mutex_unlock (& hci_cb_list_lock );
20502028
20512029 if (conn -> connect_cfm_cb )
20522030 conn -> connect_cfm_cb (conn , status );
20532031}
20542032
20552033static inline void hci_disconn_cfm (struct hci_conn * conn , __u8 reason )
20562034{
2057- struct list_head list ;
2058- struct hci_cb * cb , * tmp ;
2059-
2060- INIT_LIST_HEAD (& list );
2061- hci_cb_lookup (conn , & list );
2035+ struct hci_cb * cb ;
20622036
2063- list_for_each_entry_safe (cb , tmp , & list , list ) {
2037+ mutex_lock (& hci_cb_list_lock );
2038+ list_for_each_entry (cb , & hci_cb_list , list ) {
20642039 if (cb -> disconn_cfm )
20652040 cb -> disconn_cfm (conn , reason );
2066- kfree (cb );
20672041 }
2042+ mutex_unlock (& hci_cb_list_lock );
20682043
20692044 if (conn -> disconn_cfm_cb )
20702045 conn -> disconn_cfm_cb (conn , reason );
20712046}
20722047
2073- static inline void hci_security_cfm (struct hci_conn * conn , __u8 status ,
2074- __u8 encrypt )
2075- {
2076- struct list_head list ;
2077- struct hci_cb * cb , * tmp ;
2078-
2079- INIT_LIST_HEAD (& list );
2080- hci_cb_lookup (conn , & list );
2081-
2082- list_for_each_entry_safe (cb , tmp , & list , list ) {
2083- if (cb -> security_cfm )
2084- cb -> security_cfm (conn , status , encrypt );
2085- kfree (cb );
2086- }
2087-
2088- if (conn -> security_cfm_cb )
2089- conn -> security_cfm_cb (conn , status );
2090- }
2091-
20922048static inline void hci_auth_cfm (struct hci_conn * conn , __u8 status )
20932049{
2050+ struct hci_cb * cb ;
20942051 __u8 encrypt ;
20952052
20962053 if (test_bit (HCI_CONN_ENCRYPT_PEND , & conn -> flags ))
20972054 return ;
20982055
20992056 encrypt = test_bit (HCI_CONN_ENCRYPT , & conn -> flags ) ? 0x01 : 0x00 ;
21002057
2101- hci_security_cfm (conn , status , encrypt );
2058+ mutex_lock (& hci_cb_list_lock );
2059+ list_for_each_entry (cb , & hci_cb_list , list ) {
2060+ if (cb -> security_cfm )
2061+ cb -> security_cfm (conn , status , encrypt );
2062+ }
2063+ mutex_unlock (& hci_cb_list_lock );
2064+
2065+ if (conn -> security_cfm_cb )
2066+ conn -> security_cfm_cb (conn , status );
21022067}
21032068
21042069static inline void hci_encrypt_cfm (struct hci_conn * conn , __u8 status )
21052070{
2071+ struct hci_cb * cb ;
21062072 __u8 encrypt ;
21072073
21082074 if (conn -> state == BT_CONFIG ) {
@@ -2129,38 +2095,40 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
21292095 conn -> sec_level = conn -> pending_sec_level ;
21302096 }
21312097
2132- hci_security_cfm (conn , status , encrypt );
2098+ mutex_lock (& hci_cb_list_lock );
2099+ list_for_each_entry (cb , & hci_cb_list , list ) {
2100+ if (cb -> security_cfm )
2101+ cb -> security_cfm (conn , status , encrypt );
2102+ }
2103+ mutex_unlock (& hci_cb_list_lock );
2104+
2105+ if (conn -> security_cfm_cb )
2106+ conn -> security_cfm_cb (conn , status );
21332107}
21342108
21352109static inline void hci_key_change_cfm (struct hci_conn * conn , __u8 status )
21362110{
2137- struct list_head list ;
2138- struct hci_cb * cb , * tmp ;
2139-
2140- INIT_LIST_HEAD (& list );
2141- hci_cb_lookup (conn , & list );
2111+ struct hci_cb * cb ;
21422112
2143- list_for_each_entry_safe (cb , tmp , & list , list ) {
2113+ mutex_lock (& hci_cb_list_lock );
2114+ list_for_each_entry (cb , & hci_cb_list , list ) {
21442115 if (cb -> key_change_cfm )
21452116 cb -> key_change_cfm (conn , status );
2146- kfree (cb );
21472117 }
2118+ mutex_unlock (& hci_cb_list_lock );
21482119}
21492120
21502121static inline void hci_role_switch_cfm (struct hci_conn * conn , __u8 status ,
21512122 __u8 role )
21522123{
2153- struct list_head list ;
2154- struct hci_cb * cb , * tmp ;
2155-
2156- INIT_LIST_HEAD (& list );
2157- hci_cb_lookup (conn , & list );
2124+ struct hci_cb * cb ;
21582125
2159- list_for_each_entry_safe (cb , tmp , & list , list ) {
2126+ mutex_lock (& hci_cb_list_lock );
2127+ list_for_each_entry (cb , & hci_cb_list , list ) {
21602128 if (cb -> role_switch_cfm )
21612129 cb -> role_switch_cfm (conn , status , role );
2162- kfree (cb );
21632130 }
2131+ mutex_unlock (& hci_cb_list_lock );
21642132}
21652133
21662134static inline bool hci_bdaddr_is_rpa (bdaddr_t * bdaddr , u8 addr_type )
0 commit comments