@@ -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)
@@ -2010,103 +2011,68 @@ struct hci_cb {
20102011
20112012 char * name ;
20122013
2013- bool (* match ) (struct hci_conn * conn );
20142014 void (* connect_cfm ) (struct hci_conn * conn , __u8 status );
20152015 void (* disconn_cfm ) (struct hci_conn * conn , __u8 status );
20162016 void (* security_cfm ) (struct hci_conn * conn , __u8 status ,
2017- __u8 encrypt );
2017+ __u8 encrypt );
20182018 void (* key_change_cfm ) (struct hci_conn * conn , __u8 status );
20192019 void (* role_switch_cfm ) (struct hci_conn * conn , __u8 status , __u8 role );
20202020};
20212021
2022- static inline void hci_cb_lookup (struct hci_conn * conn , struct list_head * list )
2023- {
2024- struct hci_cb * cb , * cpy ;
2025-
2026- rcu_read_lock ();
2027- list_for_each_entry_rcu (cb , & hci_cb_list , list ) {
2028- if (cb -> match && cb -> match (conn )) {
2029- cpy = kmalloc (sizeof (* cpy ), GFP_ATOMIC );
2030- if (!cpy )
2031- break ;
2032-
2033- * cpy = * cb ;
2034- INIT_LIST_HEAD (& cpy -> list );
2035- list_add_rcu (& cpy -> list , list );
2036- }
2037- }
2038- rcu_read_unlock ();
2039- }
2040-
20412022static inline void hci_connect_cfm (struct hci_conn * conn , __u8 status )
20422023{
2043- struct list_head list ;
2044- struct hci_cb * cb , * tmp ;
2045-
2046- INIT_LIST_HEAD (& list );
2047- hci_cb_lookup (conn , & list );
2024+ struct hci_cb * cb ;
20482025
2049- list_for_each_entry_safe (cb , tmp , & list , list ) {
2026+ mutex_lock (& hci_cb_list_lock );
2027+ list_for_each_entry (cb , & hci_cb_list , list ) {
20502028 if (cb -> connect_cfm )
20512029 cb -> connect_cfm (conn , status );
2052- kfree (cb );
20532030 }
2031+ mutex_unlock (& hci_cb_list_lock );
20542032
20552033 if (conn -> connect_cfm_cb )
20562034 conn -> connect_cfm_cb (conn , status );
20572035}
20582036
20592037static inline void hci_disconn_cfm (struct hci_conn * conn , __u8 reason )
20602038{
2061- struct list_head list ;
2062- struct hci_cb * cb , * tmp ;
2063-
2064- INIT_LIST_HEAD (& list );
2065- hci_cb_lookup (conn , & list );
2039+ struct hci_cb * cb ;
20662040
2067- list_for_each_entry_safe (cb , tmp , & list , list ) {
2041+ mutex_lock (& hci_cb_list_lock );
2042+ list_for_each_entry (cb , & hci_cb_list , list ) {
20682043 if (cb -> disconn_cfm )
20692044 cb -> disconn_cfm (conn , reason );
2070- kfree (cb );
20712045 }
2046+ mutex_unlock (& hci_cb_list_lock );
20722047
20732048 if (conn -> disconn_cfm_cb )
20742049 conn -> disconn_cfm_cb (conn , reason );
20752050}
20762051
2077- static inline void hci_security_cfm (struct hci_conn * conn , __u8 status ,
2078- __u8 encrypt )
2079- {
2080- struct list_head list ;
2081- struct hci_cb * cb , * tmp ;
2082-
2083- INIT_LIST_HEAD (& list );
2084- hci_cb_lookup (conn , & list );
2085-
2086- list_for_each_entry_safe (cb , tmp , & list , list ) {
2087- if (cb -> security_cfm )
2088- cb -> security_cfm (conn , status , encrypt );
2089- kfree (cb );
2090- }
2091-
2092- if (conn -> security_cfm_cb )
2093- conn -> security_cfm_cb (conn , status );
2094- }
2095-
20962052static inline void hci_auth_cfm (struct hci_conn * conn , __u8 status )
20972053{
2054+ struct hci_cb * cb ;
20982055 __u8 encrypt ;
20992056
21002057 if (test_bit (HCI_CONN_ENCRYPT_PEND , & conn -> flags ))
21012058 return ;
21022059
21032060 encrypt = test_bit (HCI_CONN_ENCRYPT , & conn -> flags ) ? 0x01 : 0x00 ;
21042061
2105- hci_security_cfm (conn , status , encrypt );
2062+ mutex_lock (& hci_cb_list_lock );
2063+ list_for_each_entry (cb , & hci_cb_list , list ) {
2064+ if (cb -> security_cfm )
2065+ cb -> security_cfm (conn , status , encrypt );
2066+ }
2067+ mutex_unlock (& hci_cb_list_lock );
2068+
2069+ if (conn -> security_cfm_cb )
2070+ conn -> security_cfm_cb (conn , status );
21062071}
21072072
21082073static inline void hci_encrypt_cfm (struct hci_conn * conn , __u8 status )
21092074{
2075+ struct hci_cb * cb ;
21102076 __u8 encrypt ;
21112077
21122078 if (conn -> state == BT_CONFIG ) {
@@ -2133,38 +2099,40 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
21332099 conn -> sec_level = conn -> pending_sec_level ;
21342100 }
21352101
2136- hci_security_cfm (conn , status , encrypt );
2102+ mutex_lock (& hci_cb_list_lock );
2103+ list_for_each_entry (cb , & hci_cb_list , list ) {
2104+ if (cb -> security_cfm )
2105+ cb -> security_cfm (conn , status , encrypt );
2106+ }
2107+ mutex_unlock (& hci_cb_list_lock );
2108+
2109+ if (conn -> security_cfm_cb )
2110+ conn -> security_cfm_cb (conn , status );
21372111}
21382112
21392113static inline void hci_key_change_cfm (struct hci_conn * conn , __u8 status )
21402114{
2141- struct list_head list ;
2142- struct hci_cb * cb , * tmp ;
2143-
2144- INIT_LIST_HEAD (& list );
2145- hci_cb_lookup (conn , & list );
2115+ struct hci_cb * cb ;
21462116
2147- list_for_each_entry_safe (cb , tmp , & list , list ) {
2117+ mutex_lock (& hci_cb_list_lock );
2118+ list_for_each_entry (cb , & hci_cb_list , list ) {
21482119 if (cb -> key_change_cfm )
21492120 cb -> key_change_cfm (conn , status );
2150- kfree (cb );
21512121 }
2122+ mutex_unlock (& hci_cb_list_lock );
21522123}
21532124
21542125static inline void hci_role_switch_cfm (struct hci_conn * conn , __u8 status ,
21552126 __u8 role )
21562127{
2157- struct list_head list ;
2158- struct hci_cb * cb , * tmp ;
2159-
2160- INIT_LIST_HEAD (& list );
2161- hci_cb_lookup (conn , & list );
2128+ struct hci_cb * cb ;
21622129
2163- list_for_each_entry_safe (cb , tmp , & list , list ) {
2130+ mutex_lock (& hci_cb_list_lock );
2131+ list_for_each_entry (cb , & hci_cb_list , list ) {
21642132 if (cb -> role_switch_cfm )
21652133 cb -> role_switch_cfm (conn , status , role );
2166- kfree (cb );
21672134 }
2135+ mutex_unlock (& hci_cb_list_lock );
21682136}
21692137
21702138static inline bool hci_bdaddr_is_rpa (bdaddr_t * bdaddr , u8 addr_type )
0 commit comments