@@ -168,6 +168,12 @@ struct btnxpuart_data {
168168 const char * fw_name_old ;
169169};
170170
171+ enum bootloader_param_change {
172+ not_changed ,
173+ cmd_sent ,
174+ changed
175+ };
176+
171177struct btnxpuart_dev {
172178 struct hci_dev * hdev ;
173179 struct serdev_device * serdev ;
@@ -183,6 +189,7 @@ struct btnxpuart_dev {
183189 u32 fw_v1_sent_bytes ;
184190 u32 fw_dnld_v3_offset ;
185191 u32 fw_v3_offset_correction ;
192+ u32 fw_v3_prev_sent ;
186193 u32 fw_v1_expected_len ;
187194 u32 boot_reg_offset ;
188195 wait_queue_head_t fw_dnld_done_wait_q ;
@@ -191,8 +198,8 @@ struct btnxpuart_dev {
191198 u32 new_baudrate ;
192199 u32 current_baudrate ;
193200 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 ;
196203 bool helper_downloaded ;
197204
198205 struct ps_data psdata ;
@@ -680,8 +687,8 @@ static int nxp_download_firmware(struct hci_dev *hdev)
680687 nxpdev -> boot_reg_offset = 0 ;
681688 nxpdev -> fw_dnld_v3_offset = 0 ;
682689 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 ;
685692 nxpdev -> helper_downloaded = false;
686693
687694 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)
913920 len = __le16_to_cpu (req -> len );
914921
915922 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 ;
919926 goto free_skb ;
920927 }
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 ;
925931 serdev_device_set_baudrate (nxpdev -> serdev ,
926932 HCI_NXP_SEC_BAUDRATE );
927933 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)
11271133{
11281134 struct btnxpuart_dev * nxpdev = hci_get_drvdata (hdev );
11291135 struct v3_data_req * req ;
1130- __u16 len ;
1136+ __u16 len = 0 ;
1137+ __u16 err = 0 ;
11311138 __u32 offset ;
11321139
11331140 if (!process_boot_signature (nxpdev ))
@@ -1137,23 +1144,40 @@ static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
11371144 if (!req || !nxpdev -> fw )
11381145 goto free_skb ;
11391146
1140- if (!req -> error ) {
1147+ err = __le16_to_cpu (req -> error );
1148+
1149+ if (!err ) {
11411150 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 ;
11421155 } else {
11431156 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+ }
11441167 goto free_skb ;
11451168 }
11461169
11471170 len = __le16_to_cpu (req -> len );
11481171
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 ;
11511175 goto free_skb ;
11521176 }
11531177
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 ;
11571181 serdev_device_set_baudrate (nxpdev -> serdev ,
11581182 HCI_NXP_SEC_BAUDRATE );
11591183 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)
11851209 nxpdev -> fw_dnld_v3_offset , len );
11861210
11871211free_skb :
1212+ nxpdev -> fw_v3_prev_sent = len ;
11881213 kfree_skb (skb );
11891214 return 0 ;
11901215}
0 commit comments