@@ -168,6 +168,12 @@ struct btnxpuart_data {
168
168
const char * fw_name_old ;
169
169
};
170
170
171
+ enum bootloader_param_change {
172
+ not_changed ,
173
+ cmd_sent ,
174
+ changed
175
+ };
176
+
171
177
struct btnxpuart_dev {
172
178
struct hci_dev * hdev ;
173
179
struct serdev_device * serdev ;
@@ -183,6 +189,7 @@ struct btnxpuart_dev {
183
189
u32 fw_v1_sent_bytes ;
184
190
u32 fw_dnld_v3_offset ;
185
191
u32 fw_v3_offset_correction ;
192
+ u32 fw_v3_prev_sent ;
186
193
u32 fw_v1_expected_len ;
187
194
u32 boot_reg_offset ;
188
195
wait_queue_head_t fw_dnld_done_wait_q ;
@@ -191,8 +198,8 @@ struct btnxpuart_dev {
191
198
u32 new_baudrate ;
192
199
u32 current_baudrate ;
193
200
u32 fw_init_baudrate ;
194
- bool timeout_changed ;
195
- bool baudrate_changed ;
201
+ enum bootloader_param_change timeout_changed ;
202
+ enum bootloader_param_change baudrate_changed ;
196
203
bool helper_downloaded ;
197
204
198
205
struct ps_data psdata ;
@@ -680,8 +687,8 @@ static int nxp_download_firmware(struct hci_dev *hdev)
680
687
nxpdev -> boot_reg_offset = 0 ;
681
688
nxpdev -> fw_dnld_v3_offset = 0 ;
682
689
nxpdev -> fw_v3_offset_correction = 0 ;
683
- nxpdev -> baudrate_changed = false ;
684
- nxpdev -> timeout_changed = false ;
690
+ nxpdev -> baudrate_changed = not_changed ;
691
+ nxpdev -> timeout_changed = not_changed ;
685
692
nxpdev -> helper_downloaded = false;
686
693
687
694
serdev_device_set_baudrate (nxpdev -> serdev , HCI_NXP_PRI_BAUDRATE );
@@ -913,15 +920,14 @@ static int nxp_recv_fw_req_v1(struct hci_dev *hdev, struct sk_buff *skb)
913
920
len = __le16_to_cpu (req -> len );
914
921
915
922
if (!nxp_data -> helper_fw_name ) {
916
- if (! nxpdev -> timeout_changed ) {
917
- nxpdev -> timeout_changed = nxp_fw_change_timeout (hdev ,
918
- len ) ;
923
+ if (nxpdev -> timeout_changed != changed ) {
924
+ nxp_fw_change_timeout (hdev , len );
925
+ nxpdev -> timeout_changed = changed ;
919
926
goto free_skb ;
920
927
}
921
- if (!nxpdev -> baudrate_changed ) {
922
- nxpdev -> baudrate_changed = nxp_fw_change_baudrate (hdev ,
923
- len );
924
- if (nxpdev -> baudrate_changed ) {
928
+ if (nxpdev -> baudrate_changed != changed ) {
929
+ if (nxp_fw_change_baudrate (hdev , len )) {
930
+ nxpdev -> baudrate_changed = changed ;
925
931
serdev_device_set_baudrate (nxpdev -> serdev ,
926
932
HCI_NXP_SEC_BAUDRATE );
927
933
serdev_device_set_flow_control (nxpdev -> serdev , true);
@@ -1127,7 +1133,8 @@ static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
1127
1133
{
1128
1134
struct btnxpuart_dev * nxpdev = hci_get_drvdata (hdev );
1129
1135
struct v3_data_req * req ;
1130
- __u16 len ;
1136
+ __u16 len = 0 ;
1137
+ __u16 err = 0 ;
1131
1138
__u32 offset ;
1132
1139
1133
1140
if (!process_boot_signature (nxpdev ))
@@ -1137,23 +1144,40 @@ static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
1137
1144
if (!req || !nxpdev -> fw )
1138
1145
goto free_skb ;
1139
1146
1140
- if (!req -> error ) {
1147
+ err = __le16_to_cpu (req -> error );
1148
+
1149
+ if (!err ) {
1141
1150
nxp_send_ack (NXP_ACK_V3 , hdev );
1151
+ if (nxpdev -> timeout_changed == cmd_sent )
1152
+ nxpdev -> timeout_changed = changed ;
1153
+ if (nxpdev -> baudrate_changed == cmd_sent )
1154
+ nxpdev -> baudrate_changed = changed ;
1142
1155
} else {
1143
1156
nxp_handle_fw_download_error (hdev , req );
1157
+ if (nxpdev -> timeout_changed == cmd_sent &&
1158
+ err == NXP_CRC_RX_ERROR ) {
1159
+ nxpdev -> fw_v3_offset_correction -= nxpdev -> fw_v3_prev_sent ;
1160
+ nxpdev -> timeout_changed = not_changed ;
1161
+ }
1162
+ if (nxpdev -> baudrate_changed == cmd_sent &&
1163
+ err == NXP_CRC_RX_ERROR ) {
1164
+ nxpdev -> fw_v3_offset_correction -= nxpdev -> fw_v3_prev_sent ;
1165
+ nxpdev -> baudrate_changed = not_changed ;
1166
+ }
1144
1167
goto free_skb ;
1145
1168
}
1146
1169
1147
1170
len = __le16_to_cpu (req -> len );
1148
1171
1149
- if (!nxpdev -> timeout_changed ) {
1150
- nxpdev -> timeout_changed = nxp_fw_change_timeout (hdev , len );
1172
+ if (nxpdev -> timeout_changed != changed ) {
1173
+ nxp_fw_change_timeout (hdev , len );
1174
+ nxpdev -> timeout_changed = cmd_sent ;
1151
1175
goto free_skb ;
1152
1176
}
1153
1177
1154
- if (! nxpdev -> baudrate_changed ) {
1155
- nxpdev -> baudrate_changed = nxp_fw_change_baudrate (hdev , len );
1156
- if ( nxpdev -> baudrate_changed ) {
1178
+ if (nxpdev -> baudrate_changed != changed ) {
1179
+ if ( nxp_fw_change_baudrate (hdev , len )) {
1180
+ nxpdev -> baudrate_changed = cmd_sent ;
1157
1181
serdev_device_set_baudrate (nxpdev -> serdev ,
1158
1182
HCI_NXP_SEC_BAUDRATE );
1159
1183
serdev_device_set_flow_control (nxpdev -> serdev , true);
@@ -1185,6 +1209,7 @@ static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
1185
1209
nxpdev -> fw_dnld_v3_offset , len );
1186
1210
1187
1211
free_skb :
1212
+ nxpdev -> fw_v3_prev_sent = len ;
1188
1213
kfree_skb (skb );
1189
1214
return 0 ;
1190
1215
}
0 commit comments