1 /****************************************************************************
3 * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved
5 ****************************************************************************/
7 #include <linux/module.h>
8 #include <linux/init.h>
9 #include <linux/firmware.h>
10 #include <linux/slab.h>
11 #include <linux/delay.h>
12 #include <linux/version.h>
13 #include <linux/kmod.h>
14 #include <linux/notifier.h>
15 #include "scsc_mx_impl.h"
16 #include "miframman.h"
17 #include "mifmboxman.h"
20 #include "mxmgmt_transport.h"
21 #include "gdb_transport.h"
27 #include "fw_panic_record.h"
30 #include "mxlog_transport.h"
32 #ifdef CONFIG_SCSC_SMAPPER
33 #include "mifsmapper.h"
35 #ifdef CONFIG_SCSC_QOS
38 #include "mxfwconfig.h"
39 #include <scsc/kic/slsi_kic_lib.h>
40 #include <scsc/scsc_release.h>
41 #include <scsc/scsc_mx.h>
43 #ifdef CONFIG_SCSC_LOG_COLLECTION
44 #include <scsc/scsc_log_collector.h>
47 #include <scsc/scsc_logring.h>
48 #ifdef CONFIG_SCSC_WLBTD
49 #include "scsc_wlbtd.h"
50 #define SCSC_SCRIPT_MOREDUMP "moredump"
51 #define SCSC_SCRIPT_LOGGER_DUMP "mx_logger_dump.sh"
52 static struct work_struct wlbtd_work
;
55 #include "scsc_lerna.h"
58 #include <scsc/api/bt_audio.h>
60 #define STRING_BUFFER_MAX_LENGTH 512
61 #define NUMBER_OF_STRING_ARGS 5
62 #define MX_DRAM_SIZE (4 * 1024 * 1024)
63 #define MX_DRAM_SIZE_SECTION_1 (8 * 1024 * 1024)
64 #define MX_DRAM_SIZE_SECTION_2 (8 * 1024 * 1024)
65 #define MX_FW_RUNTIME_LENGTH (1024 * 1024)
66 #define WAIT_FOR_FW_TO_START_DELAY_MS 1000
67 #define MBOX2_MAGIC_NUMBER 0xbcdeedcb
68 #define MBOX_INDEX_0 0
69 #define MBOX_INDEX_1 1
70 #define MBOX_INDEX_2 2
71 #define MBOX_INDEX_3 3
72 #ifdef CONFIG_SOC_EXYNOS7570
73 #define MBOX_INDEX_4 4
74 #define MBOX_INDEX_5 5
75 #define MBOX_INDEX_6 6
76 #define MBOX_INDEX_7 7
79 #define SCSC_PANIC_ORIGIN_FW (0x0 << 15)
80 #define SCSC_PANIC_ORIGIN_HOST (0x1 << 15)
82 #define SCSC_PANIC_TECH_WLAN (0x0 << 13)
83 #define SCSC_PANIC_TECH_CORE (0x1 << 13)
84 #define SCSC_PANIC_TECH_BT (0x2 << 13)
85 #define SCSC_PANIC_TECH_UNSP (0x3 << 13)
87 #define SCSC_PANIC_CODE_MASK 0xFFFF
88 #define SCSC_PANIC_ORIGIN_MASK 0x8000
89 #define SCSC_PANIC_TECH_MASK 0x6000
90 #define SCSC_PANIC_SUBCODE_MASK_LEGACY 0x0FFF
91 #define SCSC_PANIC_SUBCODE_MASK 0x7FFF
93 #define SCSC_R4_V2_MINOR_52 52
94 #define SCSC_R4_V2_MINOR_53 53
96 #define MM_HALT_RSP_TIMEOUT_MS 100
98 static char panic_record_dump
[PANIC_RECORD_DUMP_BUFFER_SZ
];
99 static BLOCKING_NOTIFIER_HEAD(firmware_chain
);
102 * This will be returned as fw version ONLY if Maxwell
103 * was never found or was unloaded.
105 static char saved_fw_build_id
[FW_BUILD_ID_SZ
] = "Maxwell WLBT unavailable";
107 static bool allow_unidentified_firmware
;
108 module_param(allow_unidentified_firmware
, bool, S_IRUGO
| S_IWUSR
);
109 MODULE_PARM_DESC(allow_unidentified_firmware
, "Allow unidentified firmware");
111 static bool skip_header
;
112 module_param(skip_header
, bool, S_IRUGO
| S_IWUSR
);
113 MODULE_PARM_DESC(skip_header
, "Skip header, assuming unidentified firmware");
115 static bool crc_check_allow_none
= true;
116 module_param(crc_check_allow_none
, bool, S_IRUGO
| S_IWUSR
);
117 MODULE_PARM_DESC(crc_check_allow_none
, "Allow skipping firmware CRC checks if CRC is not present");
119 static int crc_check_period_ms
= 30000;
120 module_param(crc_check_period_ms
, int, S_IRUGO
| S_IWUSR
);
121 MODULE_PARM_DESC(crc_check_period_ms
, "Time period for checking the firmware CRCs");
123 static ulong mm_completion_timeout_ms
= 2000;
124 module_param(mm_completion_timeout_ms
, ulong
, S_IRUGO
| S_IWUSR
);
125 MODULE_PARM_DESC(mm_completion_timeout_ms
, "Timeout wait_for_mm_msg_start_ind (ms) - default 1000. 0 = infinite");
127 static bool skip_mbox0_check
;
128 module_param(skip_mbox0_check
, bool, S_IRUGO
| S_IWUSR
);
129 MODULE_PARM_DESC(skip_mbox0_check
, "Allow skipping firmware mbox0 signature check");
131 static uint firmware_startup_flags
;
132 module_param(firmware_startup_flags
, uint
, S_IRUGO
| S_IWUSR
);
133 MODULE_PARM_DESC(firmware_startup_flags
, "0 = Proceed as normal (default); Bit 0 = 1 - spin at start of CRT0; Other bits reserved = 0");
135 #ifdef CONFIG_SCSC_CHV_SUPPORT
136 /* First arg controls chv function */
138 module_param(chv_run
, int, S_IRUGO
| S_IWUSR
);
139 MODULE_PARM_DESC(chv_run
, "Run chv f/w: 0 = feature disabled, 1 = for continuous checking, 2 = 1 shot, anything else, undefined");
141 /* Optional array of args for firmware to interpret when chv_run = 1 */
142 static unsigned int chv_argv
[32];
145 module_param_array(chv_argv
, uint
, &chv_argc
, S_IRUGO
| S_IWUSR
);
146 MODULE_PARM_DESC(chv_argv
, "Array of up to 32 x u32 args for the CHV firmware when chv_run = 1");
149 static bool disable_auto_coredump
;
150 module_param(disable_auto_coredump
, bool, S_IRUGO
| S_IWUSR
);
151 MODULE_PARM_DESC(disable_auto_coredump
, "Disable driver automatic coredump");
153 static bool disable_error_handling
;
154 module_param(disable_error_handling
, bool, S_IRUGO
| S_IWUSR
);
155 MODULE_PARM_DESC(disable_error_handling
, "Disable error handling");
157 int disable_recovery_handling
= 1; /* MEMDUMP_FILE_FOR_RECOVERY : for /sys/wifi/memdump */
158 module_param(disable_recovery_handling
, int, S_IRUGO
| S_IWUSR
);
159 MODULE_PARM_DESC(disable_recovery_handling
, "Disable recovery handling");
160 static bool disable_recovery_from_memdump_file
= true;
161 static int memdump
= -1;
162 static bool disable_recovery_until_reboot
;
164 static uint panic_record_delay
= 1;
165 module_param(panic_record_delay
, uint
, S_IRUGO
| S_IWUSR
);
166 MODULE_PARM_DESC(panic_record_delay
, "Delay in ms before accessing the panic record");
168 static bool disable_logger
= true;
169 module_param(disable_logger
, bool, S_IRUGO
| S_IWUSR
);
170 MODULE_PARM_DESC(disable_logger
, "Disable launch of user space logger");
173 * shared between this module and mgt.c as this is the kobject referring to
174 * /sys/wifi directory. Core driver is called 1st we create the directory
175 * here and share the kobject, so in mgt.c wifi driver can create
176 * /sys/wif/mac_addr using sysfs_create_file api using the kobject
178 * If both modules tried to create the dir we were getting kernel panic
179 * failure due to kobject associated with dir already existed
181 static struct kobject
*wifi_kobj_ref
;
183 static ssize_t
sysfs_show_memdump(struct kobject
*kobj
, struct kobj_attribute
*attr
,
185 static ssize_t
sysfs_store_memdump(struct kobject
*kobj
, struct kobj_attribute
*attr
,
186 const char *buf
, size_t count
);
187 static struct kobj_attribute memdump_attr
=
188 __ATTR(memdump
, 0660, sysfs_show_memdump
, sysfs_store_memdump
);
191 #ifdef CONFIG_SCSC_LOG_COLLECTION
192 static int mxman_minimoredump_collect(struct scsc_log_collector_client
*collect_client
, size_t size
)
195 struct mxman
*mxman
= (struct mxman
*) collect_client
->prv
;
197 if (!mxman
|| !mxman
->start_dram
)
200 SCSC_TAG_INFO(MXMAN
, "Collecting Minimoredump runtime_length %d fw_image_size %d\n",
201 mxman
->fwhdr
.fw_runtime_length
, mxman
->fw_image_size
);
202 /* collect RAM sections of FW */
203 ret
= scsc_log_collector_write(mxman
->start_dram
+ mxman
->fw_image_size
,
204 mxman
->fwhdr
.fw_runtime_length
- mxman
->fw_image_size
, 1);
209 struct scsc_log_collector_client mini_moredump_client
= {
210 .name
= "minimoredump",
211 .type
= SCSC_LOG_MINIMOREDUMP
,
212 .collect_init
= NULL
,
213 .collect
= mxman_minimoredump_collect
,
219 /* Retrieve memdump in sysfs global */
220 static ssize_t
sysfs_show_memdump(struct kobject
*kobj
,
221 struct kobj_attribute
*attr
,
224 return sprintf(buf
, "%d\n", memdump
);
227 /* Update memdump in sysfs global */
228 static ssize_t
sysfs_store_memdump(struct kobject
*kobj
,
229 struct kobj_attribute
*attr
,
235 r
= kstrtoint(buf
, 10, &memdump
);
242 disable_recovery_from_memdump_file
= false;
246 disable_recovery_from_memdump_file
= true;
250 SCSC_TAG_INFO(MXMAN
, "memdump: %d\n", memdump
);
252 return (r
== 0) ? count
: 0;
255 struct kobject
*mxman_wifi_kobject_ref_get(void)
257 if (refcount
++ == 0) {
258 /* Create sysfs directory /sys/wifi */
259 wifi_kobj_ref
= kobject_create_and_add("wifi", NULL
);
260 kobject_get(wifi_kobj_ref
);
261 kobject_uevent(wifi_kobj_ref
, KOBJ_ADD
);
262 SCSC_TAG_INFO(MXMAN
, "wifi_kobj_ref: 0x%p\n", wifi_kobj_ref
);
263 WARN_ON(refcount
== 0);
265 return wifi_kobj_ref
;
267 EXPORT_SYMBOL(mxman_wifi_kobject_ref_get
);
269 void mxman_wifi_kobject_ref_put(void)
271 if (--refcount
== 0) {
272 kobject_put(wifi_kobj_ref
);
273 kobject_uevent(wifi_kobj_ref
, KOBJ_REMOVE
);
274 wifi_kobj_ref
= NULL
;
275 WARN_ON(refcount
< 0);
278 EXPORT_SYMBOL(mxman_wifi_kobject_ref_put
);
280 /* Register memdump override */
281 void mxman_create_sysfs_memdump(void)
284 struct kobject
*kobj_ref
= mxman_wifi_kobject_ref_get();
286 SCSC_TAG_INFO(MXMAN
, "kobj_ref: 0x%p\n", kobj_ref
);
289 /* Create sysfs file /sys/wifi/memdump */
290 r
= sysfs_create_file(kobj_ref
, &memdump_attr
.attr
);
292 /* Failed, so clean up dir */
293 SCSC_TAG_ERR(MXMAN
, "Can't create /sys/wifi/memdump\n");
294 mxman_wifi_kobject_ref_put();
298 SCSC_TAG_ERR(MXMAN
, "failed to create /sys/wifi directory");
302 /* Unregister memdump override */
303 void mxman_destroy_sysfs_memdump(void)
308 /* Destroy /sys/wifi/memdump file */
309 sysfs_remove_file(wifi_kobj_ref
, &memdump_attr
.attr
);
311 /* Destroy /sys/wifi virtual dir */
312 mxman_wifi_kobject_ref_put();
315 /* Track when WLBT reset fails to allow debug */
317 static u64 reset_failed_time
;
319 /* Status of FM driver request, which persists beyond the lifecyle
320 * of the scsx_mx driver.
322 #ifdef CONFIG_SCSC_FM
326 static int firmware_runtime_flags
;
327 static int syserr_command
;
329 * This mxman reference is initialized/nullified via mxman_init/deinit
330 * called by scsc_mx_create/destroy on module probe/remove.
332 static struct mxman
*active_mxman
;
333 static bool send_fw_config_to_active_mxman(uint32_t fw_runtime_flags
);
334 static bool send_syserr_cmd_to_active_mxman(u32 syserr_cmd
);
336 static int fw_runtime_flags_setter(const char *val
, const struct kernel_param
*kp
)
339 uint32_t fw_runtime_flags
= 0;
343 ret
= kstrtouint(val
, 10, &fw_runtime_flags
);
345 if (send_fw_config_to_active_mxman(fw_runtime_flags
))
346 firmware_runtime_flags
= fw_runtime_flags
;
354 * We don't bother to keep an updated copy of the runtime flags effectively
355 * currently set into FW...we should add a new message answer handling both in
356 * Kenrel and FW side to be sure and this is just to easy debug at the end.
358 static struct kernel_param_ops fw_runtime_kops
= {
359 .set
= fw_runtime_flags_setter
,
363 module_param_cb(firmware_runtime_flags
, &fw_runtime_kops
, NULL
, 0200);
364 MODULE_PARM_DESC(firmware_runtime_flags
,
365 "0 = Proceed as normal (default); nnn = Provides FW runtime flags bitmask: unknown bits will be ignored.");
367 static int syserr_setter(const char *val
, const struct kernel_param
*kp
)
374 ret
= kstrtouint(val
, 10, &syserr_cmd
);
376 u8 sub_system
= (u8
)(syserr_cmd
/ 10);
377 u8 level
= (u8
)(syserr_cmd
% 10);
379 if (((sub_system
> 2) && (sub_system
< 8)) || (sub_system
> 8) || (level
> 7))
381 else if (send_syserr_cmd_to_active_mxman(syserr_cmd
))
382 syserr_command
= syserr_cmd
;
389 static struct kernel_param_ops syserr_kops
= {
390 .set
= syserr_setter
,
394 module_param_cb(syserr_command
, &syserr_kops
, NULL
, 0200);
395 MODULE_PARM_DESC(syserr_command
,
396 "Decimal XY - Trigger Type X(0,1,2,8), Level Y(1-7). Some combinations not supported");
399 * Maxwell Agent Management Messages.
401 * TODO: common defn with firmware, generated.
403 * The numbers here *must* match the firmware!
413 MM_FM_RADIO_CONFIG
= 7,
420 * Format of the Maxwell agent messages
421 * on the Maxwell management transport stream.
423 struct ma_msg_packet
{
425 uint8_t ma_msg
; /* Message from ma_msg enum */
426 uint32_t arg
; /* Optional arg set by f/w in some to-host messages */
430 * Special case Maxwell management, carrying FM radio configuration structure
432 struct ma_msg_packet_fm_radio_config
{
434 uint8_t ma_msg
; /* Message from ma_msg enum */
435 struct wlbt_fm_params fm_params
; /* FM Radio parameters */
438 static bool send_fw_config_to_active_mxman(uint32_t fw_runtime_flags
)
441 struct srvman
*srvman
= NULL
;
443 SCSC_TAG_INFO(MXMAN
, "\n");
445 SCSC_TAG_ERR(MXMAN
, "Active MXMAN NOT FOUND...cannot send running FW config.\n");
449 mutex_lock(&active_mxman
->mxman_mutex
);
450 srvman
= scsc_mx_get_srvman(active_mxman
->mx
);
451 if (srvman
&& srvman
->error
) {
452 mutex_unlock(&active_mxman
->mxman_mutex
);
453 SCSC_TAG_INFO(MXMAN
, "Called during error - ignore\n");
457 if (active_mxman
->mxman_state
== MXMAN_STATE_STARTED
) {
458 struct ma_msg_packet message
= { .ma_msg
= MM_FW_CONFIG
,
459 .arg
= fw_runtime_flags
};
461 SCSC_TAG_INFO(MXMAN
, "MM_FW_CONFIG - firmware_runtime_flags:%d\n", message
.arg
);
462 mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(active_mxman
->mx
),
463 MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT
, &message
,
467 SCSC_TAG_INFO(MXMAN
, "MXMAN is NOT STARTED...cannot send MM_FW_CONFIG msg.\n");
469 mutex_unlock(&active_mxman
->mxman_mutex
);
474 static bool send_syserr_cmd_to_active_mxman(u32 syserr_cmd
)
477 struct srvman
*srvman
= NULL
;
479 SCSC_TAG_INFO(MXMAN
, "\n");
481 SCSC_TAG_ERR(MXMAN
, "Active MXMAN NOT FOUND...cannot send running FW config.\n");
485 mutex_lock(&active_mxman
->mxman_mutex
);
486 srvman
= scsc_mx_get_srvman(active_mxman
->mx
);
487 if (srvman
&& srvman
->error
) {
488 mutex_unlock(&active_mxman
->mxman_mutex
);
489 SCSC_TAG_INFO(MXMAN
, "Called during error - ignore\n");
493 if (active_mxman
->mxman_state
== MXMAN_STATE_STARTED
) {
494 struct ma_msg_packet message
= { .ma_msg
= MM_SYSERR_CMD
,
497 SCSC_TAG_INFO(MXMAN
, "MM_SYSERR_CMD - Args %02d\n", message
.arg
);
498 mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(active_mxman
->mx
),
499 MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT
, &message
,
503 SCSC_TAG_INFO(MXMAN
, "MXMAN is NOT STARTED...cannot send MM_SYSERR_CMD msg.\n");
505 mutex_unlock(&active_mxman
->mxman_mutex
);
510 #ifdef CONFIG_SCSC_FM
511 static bool send_fm_params_to_active_mxman(struct wlbt_fm_params
*params
)
514 struct srvman
*srvman
= NULL
;
516 SCSC_TAG_INFO(MXMAN
, "\n");
518 SCSC_TAG_ERR(MXMAN
, "Active MXMAN NOT FOUND...cannot send FM params\n");
522 mutex_lock(&active_mxman
->mxman_mutex
);
523 srvman
= scsc_mx_get_srvman(active_mxman
->mx
);
524 if (srvman
&& srvman
->error
) {
525 mutex_unlock(&active_mxman
->mxman_mutex
);
526 SCSC_TAG_INFO(MXMAN
, "Called during error - ignore\n");
530 if (active_mxman
->mxman_state
== MXMAN_STATE_STARTED
) {
531 struct ma_msg_packet_fm_radio_config message
= { .ma_msg
= MM_FM_RADIO_CONFIG
,
532 .fm_params
= *params
};
534 SCSC_TAG_INFO(MXMAN
, "MM_FM_RADIO_CONFIG\n");
535 mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(active_mxman
->mx
),
536 MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT
, &message
,
539 ret
= true; /* Success */
541 SCSC_TAG_INFO(MXMAN
, "MXMAN is NOT STARTED...cannot send MM_FM_RADIO_CONFIG msg.\n");
543 mutex_unlock(&active_mxman
->mxman_mutex
);
549 static void mxman_stop(struct mxman
*mxman
);
550 static void print_mailboxes(struct mxman
*mxman
);
551 #ifdef CONFIG_SCSC_WLBTD
552 static int _mx_exec(char *prog
, int wait_exec
) __attribute__((unused
));
554 static int _mx_exec(char *prog
, int wait_exec
);
556 static int wait_for_mm_msg(struct mxman
*mxman
, struct completion
*mm_msg_completion
, ulong timeout_ms
)
560 (void)mxman
; /* unused */
562 if (timeout_ms
== 0) {
563 /* Zero implies infinite wait */
564 r
= wait_for_completion_interruptible(mm_msg_completion
);
565 /* r = -ERESTARTSYS if interrupted, 0 if completed */
568 r
= wait_for_completion_timeout(mm_msg_completion
, msecs_to_jiffies(timeout_ms
));
570 SCSC_TAG_ERR(MXMAN
, "timeout\n");
577 static int wait_for_mm_msg_start_ind(struct mxman
*mxman
)
579 return wait_for_mm_msg(mxman
, &mxman
->mm_msg_start_ind_completion
, mm_completion_timeout_ms
);
582 static int wait_for_mm_msg_halt_rsp(struct mxman
*mxman
)
585 (void)mxman
; /* unused */
587 if (MM_HALT_RSP_TIMEOUT_MS
== 0) {
588 /* Zero implies infinite wait */
589 r
= wait_for_completion_interruptible(&mxman
->mm_msg_halt_rsp_completion
);
590 /* r = -ERESTARTSYS if interrupted, 0 if completed */
594 r
= wait_for_completion_timeout(&mxman
->mm_msg_halt_rsp_completion
, msecs_to_jiffies(MM_HALT_RSP_TIMEOUT_MS
));
596 SCSC_TAG_INFO(MXMAN
, "Received MM_HALT_RSP from firmware");
601 #ifndef CONFIG_SCSC_WLBTD
602 static int coredump_helper(void)
606 static char mdbin
[128];
608 /* Determine path to moredump helper script */
609 r
= mx140_exe_path(NULL
, mdbin
, sizeof(mdbin
), "moredump");
611 SCSC_TAG_ERR(MXMAN
, "moredump path error\n");
615 for (i
= 0; i
< 20; i
++) {
616 r
= _mx_exec(mdbin
, UMH_WAIT_PROC
);
619 /* If the usermode helper fails with -EBUSY, the userspace is
620 * likely still frozen from suspend. Back off and retry.
622 SCSC_TAG_INFO(MXMAN
, "waiting for userspace to thaw...\n");
626 /* Application return codes are in the MSB */
628 SCSC_TAG_INFO(MXMAN
, "moredump.bin exit(%ld), check syslog\n", (r
& 0xff00L
) >> 8);
634 static int send_mm_msg_stop_blocking(struct mxman
*mxman
)
637 #ifdef CONFIG_SCSC_FM
638 struct ma_msg_packet message
= { .ma_msg
= MM_HALT_REQ
,
639 .arg
= mxman
->on_halt_ldos_on
};
641 struct ma_msg_packet message
= { .ma_msg
= MM_HALT_REQ
};
643 mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(mxman
->mx
), MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT
, &message
, sizeof(message
));
645 r
= wait_for_mm_msg_halt_rsp(mxman
);
648 * MM_MSG_HALT_RSP is not implemented in all versions of firmware, so don't treat it's non-arrival
651 SCSC_TAG_INFO(MXMAN
, "wait_for_MM_HALT_RSP completed");
657 static char *chip_version(u32 rf_hw_ver
)
659 switch (rf_hw_ver
& 0x00ff) {
663 if ((rf_hw_ver
& 0xff00) > 0x1000)
672 #ifndef CONFIG_SOC_EXYNOS9610
673 return "Error: check if RF chip is present";
682 * This function is used in this file and in mxproc.c to generate consistent
683 * RF CHIP VERSION string for logging on console and for storing the same
684 * in proc/drivers/mxman_info/rf_chip_version file.
686 int mxman_print_rf_hw_version(struct mxman
*mxman
, char *buf
, const size_t bufsz
)
690 r
= snprintf(buf
, bufsz
, "RF_CHIP_VERSION: 0x%04x: %s (0x%02x), EVT%x.%x\n",
692 chip_version(mxman
->rf_hw_ver
), (mxman
->rf_hw_ver
& 0x00ff),
693 ((mxman
->rf_hw_ver
>> 12) & 0xfU
), ((mxman
->rf_hw_ver
>> 8) & 0xfU
));
698 static void mxman_print_versions(struct mxman
*mxman
)
702 memset(buf
, '\0', sizeof(buf
));
704 (void)mxman_print_rf_hw_version(mxman
, buf
, sizeof(buf
));
706 SCSC_TAG_INFO(MXMAN
, "%s", buf
);
707 SCSC_TAG_INFO(MXMAN
, "WLBT FW: %s\n", mxman
->fw_build_id
);
708 SCSC_TAG_INFO(MXMAN
, "WLBT Driver: %d.%d.%d.%d\n",
709 SCSC_RELEASE_PRODUCT
, SCSC_RELEASE_ITERATION
, SCSC_RELEASE_CANDIDATE
, SCSC_RELEASE_POINT
);
710 #ifdef CONFIG_SCSC_WLBTD
711 scsc_wlbtd_get_and_print_build_type();
715 /** Receive handler for messages from the FW along the maxwell management transport */
716 static void mxman_message_handler(const void *message
, void *data
)
718 struct mxman
*mxman
= (struct mxman
*)data
;
720 /* Forward the message to the applicable service to deal with */
721 const struct ma_msg_packet
*msg
= message
;
723 switch (msg
->ma_msg
) {
725 /* The arg can be used to determine the WLBT/S610 hardware revision */
726 SCSC_TAG_INFO(MXMAN
, "Received MM_START_IND message from the firmware, arg=0x%04x\n", msg
->arg
);
727 mxman
->rf_hw_ver
= msg
->arg
;
728 mxman_print_versions(mxman
);
729 atomic_inc(&mxman
->boot_count
);
730 complete(&mxman
->mm_msg_start_ind_completion
);
733 complete(&mxman
->mm_msg_halt_rsp_completion
);
734 SCSC_TAG_INFO(MXMAN
, "Received MM_HALT_RSP message from the firmware\n");
736 case MM_LERNA_CONFIG
:
737 /* Message response to a firmware configuration query. */
738 SCSC_TAG_INFO(MXMAN
, "Received MM_LERNA_CONFIG message from firmware\n");
739 scsc_lerna_response(message
);
742 /* System Error report from firmware */
743 SCSC_TAG_INFO(MXMAN
, "Received MM_SYSERR_IND message from firmware\n");
744 mx_syserr_handler(mxman
, message
);
747 /* HERE: Unknown message, raise fault */
748 SCSC_TAG_WARNING(MXMAN
, "Received unknown message from the firmware: msg->ma_msg=%d\n", msg
->ma_msg
);
754 * This function calulates and checks two or three (depending on crc32_over_binary flag)
755 * crc32 values in the firmware header. The function will check crc32 over the firmware binary
756 * (i.e. everything in the file following the header) only if the crc32_over_binary is set to 'true'.
757 * This includes initialised data regions so it can be used to check when loading but will not be
758 * meaningful once execution starts.
760 static int do_fw_crc32_checks(char *fw
, u32 fw_image_size
, struct fwhdr
*fwhdr
, bool crc32_over_binary
)
764 if ((fwhdr
->fw_crc32
== 0 || fwhdr
->header_crc32
== 0 || fwhdr
->const_crc32
== 0) && crc_check_allow_none
== 0) {
765 SCSC_TAG_ERR(MXMAN
, "error: CRC is missing fw_crc32=%d header_crc32=%d crc_check_allow_none=%d\n",
766 fwhdr
->fw_crc32
, fwhdr
->header_crc32
, crc_check_allow_none
);
770 if (fwhdr
->header_crc32
== 0 && crc_check_allow_none
== 1) {
771 SCSC_TAG_INFO(MXMAN
, "Skipping CRC check header_crc32=%d crc_check_allow_none=%d\n",
772 fwhdr
->header_crc32
, crc_check_allow_none
);
775 * CRC-32-IEEE of all preceding header fields (including other CRCs).
776 * Always the last word in the header.
778 r
= fwimage_check_fw_header_crc(fw
, fwhdr
->hdr_length
, fwhdr
->header_crc32
);
780 SCSC_TAG_ERR(MXMAN
, "fwimage_check_fw_header_crc() failed\n");
785 if (fwhdr
->const_crc32
== 0 && crc_check_allow_none
== 1) {
786 SCSC_TAG_INFO(MXMAN
, "Skipping CRC check const_crc32=%d crc_check_allow_none=%d\n",
787 fwhdr
->const_crc32
, crc_check_allow_none
);
790 * CRC-32-IEEE over the constant sections grouped together at start of firmware binary.
791 * This CRC should remain valid during execution. It can be used by run-time checker on
792 * host to detect firmware corruption (not all memory masters are subject to MPUs).
794 r
= fwimage_check_fw_const_section_crc(fw
, fwhdr
->const_crc32
, fwhdr
->const_fw_length
, fwhdr
->hdr_length
);
796 SCSC_TAG_ERR(MXMAN
, "fwimage_check_fw_const_section_crc() failed\n");
801 if (crc32_over_binary
) {
802 if (fwhdr
->fw_crc32
== 0 && crc_check_allow_none
== 1)
803 SCSC_TAG_INFO(MXMAN
, "Skipping CRC check fw_crc32=%d crc_check_allow_none=%d\n",
804 fwhdr
->fw_crc32
, crc_check_allow_none
);
807 * CRC-32-IEEE over the firmware binary (i.e. everything
808 * in the file following this header).
809 * This includes initialised data regions so it can be used to
810 * check when loading but will not be meaningful once execution starts.
812 r
= fwimage_check_fw_crc(fw
, fw_image_size
, fwhdr
->hdr_length
, fwhdr
->fw_crc32
);
814 SCSC_TAG_ERR(MXMAN
, "fwimage_check_fw_crc() failed\n");
824 static void fw_crc_wq_start(struct mxman
*mxman
)
826 if (mxman
->check_crc
&& crc_check_period_ms
)
827 queue_delayed_work(mxman
->fw_crc_wq
, &mxman
->fw_crc_work
, msecs_to_jiffies(crc_check_period_ms
));
831 static void fw_crc_work_func(struct work_struct
*work
)
834 struct mxman
*mxman
= container_of((struct delayed_work
*)work
, struct mxman
, fw_crc_work
);
836 r
= do_fw_crc32_checks(mxman
->fw
, mxman
->fw_image_size
, &mxman
->fwhdr
, false);
838 SCSC_TAG_ERR(MXMAN
, "do_fw_crc32_checks() failed r=%d\n", r
);
839 mxman_fail(mxman
, SCSC_PANIC_CODE_HOST
<< 15, __func__
);
842 fw_crc_wq_start(mxman
);
846 static void fw_crc_wq_init(struct mxman
*mxman
)
848 mxman
->fw_crc_wq
= create_singlethread_workqueue("fw_crc_wq");
849 INIT_DELAYED_WORK(&mxman
->fw_crc_work
, fw_crc_work_func
);
852 static void fw_crc_wq_stop(struct mxman
*mxman
)
854 mxman
->check_crc
= false;
855 cancel_delayed_work(&mxman
->fw_crc_work
);
856 flush_workqueue(mxman
->fw_crc_wq
);
859 static void fw_crc_wq_deinit(struct mxman
*mxman
)
861 fw_crc_wq_stop(mxman
);
862 destroy_workqueue(mxman
->fw_crc_wq
);
865 static int transports_init(struct mxman
*mxman
)
867 struct mxconf
*mxconf
;
869 struct scsc_mx
*mx
= mxman
->mx
;
871 /* Initialise mx management stack */
872 r
= mxmgmt_transport_init(scsc_mx_get_mxmgmt_transport(mx
), mx
);
874 SCSC_TAG_ERR(MXMAN
, "mxmgmt_transport_init() failed %d\n", r
);
878 /* Initialise gdb transport for cortex-R4 */
879 r
= gdb_transport_init(scsc_mx_get_gdb_transport_r4(mx
), mx
, GDB_TRANSPORT_R4
);
881 SCSC_TAG_ERR(MXMAN
, "gdb_transport_init() failed %d\n", r
);
882 mxmgmt_transport_release(scsc_mx_get_mxmgmt_transport(mx
));
886 /* Initialise gdb transport for cortex-M4 */
887 r
= gdb_transport_init(scsc_mx_get_gdb_transport_m4(mx
), mx
, GDB_TRANSPORT_M4
);
889 SCSC_TAG_ERR(MXMAN
, "gdb_transport_init() failed %d\n", r
);
890 gdb_transport_release(scsc_mx_get_gdb_transport_r4(mx
));
891 mxmgmt_transport_release(scsc_mx_get_mxmgmt_transport(mx
));
894 #ifdef CONFIG_SCSC_MX450_GDB_SUPPORT
895 /* Initialise gdb transport for cortex-M4 */
896 r
= gdb_transport_init(scsc_mx_get_gdb_transport_m4_1(mx
), mx
, GDB_TRANSPORT_M4_1
);
898 SCSC_TAG_ERR(MXMAN
, "gdb_transport_init() failed %d\n", r
);
899 gdb_transport_release(scsc_mx_get_gdb_transport_r4(mx
));
900 mxmgmt_transport_release(scsc_mx_get_mxmgmt_transport(mx
));
905 /* Initialise mxlog transport */
906 r
= mxlog_transport_init(scsc_mx_get_mxlog_transport(mx
), mx
);
908 SCSC_TAG_ERR(MXMAN
, "mxlog_transport_init() failed %d\n", r
);
909 gdb_transport_release(scsc_mx_get_gdb_transport_m4(mx
));
910 #ifdef CONFIG_SCSC_MX450_GDB_SUPPORT
911 gdb_transport_release(scsc_mx_get_gdb_transport_m4_1(mx
));
913 gdb_transport_release(scsc_mx_get_gdb_transport_r4(mx
));
914 mxmgmt_transport_release(scsc_mx_get_mxmgmt_transport(mx
));
919 * Allocate & Initialise Infrastructre Config Structure
920 * including the mx management stack config information.
922 mxconf
= miframman_alloc(scsc_mx_get_ramman(mx
), sizeof(struct mxconf
), 4, MIFRAMMAN_OWNER_COMMON
);
924 SCSC_TAG_ERR(MXMAN
, "miframman_alloc() failed\n");
925 gdb_transport_release(scsc_mx_get_gdb_transport_m4(mx
));
926 #ifdef CONFIG_SCSC_MX450_GDB_SUPPORT
927 gdb_transport_release(scsc_mx_get_gdb_transport_m4_1(mx
));
929 gdb_transport_release(scsc_mx_get_gdb_transport_r4(mx
));
930 mxmgmt_transport_release(scsc_mx_get_mxmgmt_transport(mx
));
931 mxlog_transport_release(scsc_mx_get_mxlog_transport(mx
));
934 mxman
->mxconf
= mxconf
;
935 mxconf
->magic
= MXCONF_MAGIC
;
936 mxconf
->version
.major
= MXCONF_VERSION_MAJOR
;
937 mxconf
->version
.minor
= MXCONF_VERSION_MINOR
;
939 /* Pass pre-existing FM status to FW */
941 #ifdef CONFIG_SCSC_FM
942 mxconf
->flags
|= is_fm_on
? MXCONF_FLAGS_FM_ON
: 0;
944 SCSC_TAG_INFO(MXMAN
, "mxconf flags 0x%08x\n", mxconf
->flags
);
946 /* serialise mxmgmt transport */
947 mxmgmt_transport_config_serialise(scsc_mx_get_mxmgmt_transport(mx
), &mxconf
->mx_trans_conf
);
948 /* serialise Cortex-R4 gdb transport */
949 gdb_transport_config_serialise(scsc_mx_get_gdb_transport_r4(mx
), &mxconf
->mx_trans_conf_gdb_r4
);
950 /* serialise Cortex-M4 gdb transport */
951 gdb_transport_config_serialise(scsc_mx_get_gdb_transport_m4(mx
), &mxconf
->mx_trans_conf_gdb_m4
);
953 /* Default to Fleximac M4_1 monitor channel not in use.
954 * Allows CONFIG_SCSC_MX450_GDB_SUPPORT to be turned off in Kconfig even though mxconf
955 * struct v5 defines M4_1 channel
957 mxconf
->mx_trans_conf_gdb_m4_1
.from_ap_stream_conf
.buf_conf
.buffer_loc
= 0;
958 #ifdef CONFIG_SCSC_MX450_GDB_SUPPORT
959 /* serialise Cortex-M4 gdb transport */
960 gdb_transport_config_serialise(scsc_mx_get_gdb_transport_m4_1(mx
), &mxconf
->mx_trans_conf_gdb_m4_1
);
962 /* serialise mxlog transport */
963 mxlog_transport_config_serialise(scsc_mx_get_mxlog_transport(mx
), &mxconf
->mxlogconf
);
964 SCSC_TAG_DEBUG(MXMAN
, "read_bit_idx=%d write_bit_idx=%d buffer=%p num_packets=%d packet_size=%d read_index=%d write_index=%d\n",
965 scsc_mx_get_mxlog_transport(mx
)->mif_stream
.read_bit_idx
,
966 scsc_mx_get_mxlog_transport(mx
)->mif_stream
.write_bit_idx
,
967 scsc_mx_get_mxlog_transport(mx
)->mif_stream
.buffer
.buffer
,
968 scsc_mx_get_mxlog_transport(mx
)->mif_stream
.buffer
.num_packets
,
969 scsc_mx_get_mxlog_transport(mx
)->mif_stream
.buffer
.packet_size
,
970 *scsc_mx_get_mxlog_transport(mx
)->mif_stream
.buffer
.read_index
,
971 *scsc_mx_get_mxlog_transport(mx
)->mif_stream
.buffer
.write_index
974 /* Need to initialise fwconfig or else random data can make firmware data abort. */
975 mxconf
->fwconfig
.offset
= 0;
976 mxconf
->fwconfig
.size
= 0;
977 #ifdef CONFIG_SCSC_COMMON_HCF
978 /* Load Common Config HCF */
979 mxfwconfig_load(mxman
->mx
, &mxconf
->fwconfig
);
984 static void transports_release(struct mxman
*mxman
)
986 mxlog_transport_release(scsc_mx_get_mxlog_transport(mxman
->mx
));
987 mxmgmt_transport_release(scsc_mx_get_mxmgmt_transport(mxman
->mx
));
988 gdb_transport_release(scsc_mx_get_gdb_transport_r4(mxman
->mx
));
989 gdb_transport_release(scsc_mx_get_gdb_transport_m4(mxman
->mx
));
990 #ifdef CONFIG_SCSC_MX450_GDB_SUPPORT
991 gdb_transport_release(scsc_mx_get_gdb_transport_m4_1(mxman
->mx
));
993 miframman_free(scsc_mx_get_ramman(mxman
->mx
), mxman
->mxconf
);
996 static void mbox_init(struct mxman
*mxman
, u32 firmware_entry_point
)
1002 scsc_mifram_ref mifram_ref
;
1003 struct scsc_mx
*mx
= mxman
->mx
;
1004 struct scsc_mif_abs
*mif
= scsc_mx_get_mif_abs(mxman
->mx
);
1006 /* Place firmware entry address in MIF MBOX 0 so R4 ROM knows where to jump to! */
1007 mbox0
= mifmboxman_get_mbox_ptr(scsc_mx_get_mboxman(mx
), mif
, MBOX_INDEX_0
);
1008 mbox1
= mifmboxman_get_mbox_ptr(scsc_mx_get_mboxman(mx
), mif
, MBOX_INDEX_1
);
1010 /* Write (and flush) entry point to MailBox 0, config address to MBOX 1 */
1011 *mbox0
= firmware_entry_point
;
1012 mif
->get_mifram_ref(mif
, mxman
->mxconf
, &mifram_ref
);
1013 *mbox1
= mifram_ref
; /* must be R4-relative address here */
1014 /* CPU memory barrier */
1017 * write the magic number "0xbcdeedcb" to MIF Mailbox #2 &
1018 * copy the firmware_startup_flags to MIF Mailbox #3 before starting (reset = 0) the R4
1020 mbox2
= mifmboxman_get_mbox_ptr(scsc_mx_get_mboxman(mx
), mif
, MBOX_INDEX_2
);
1021 *mbox2
= MBOX2_MAGIC_NUMBER
;
1022 mbox3
= mifmboxman_get_mbox_ptr(scsc_mx_get_mboxman(mx
), mif
, MBOX_INDEX_3
);
1023 *mbox3
= firmware_startup_flags
;
1026 static int fwhdr_init(char *fw
, struct fwhdr
*fwhdr
, bool *fwhdr_parsed_ok
, bool *check_crc
)
1029 * Validate the fw image including checking the firmware header, majic #, version, checksum so on
1030 * then do CRC on the entire image
1032 * Derive some values from header -
1034 * PORT: assumes little endian
1037 *fwhdr_parsed_ok
= false; /* Allows the forced start address to be used */
1039 *fwhdr_parsed_ok
= fwhdr_parse(fw
, fwhdr
);
1041 if (*fwhdr_parsed_ok
) {
1042 SCSC_TAG_INFO(MXMAN
, "FW HEADER version: hdr_major: %d hdr_minor: %d\n", fwhdr
->hdr_major
, fwhdr
->hdr_minor
);
1043 switch (fwhdr
->hdr_major
) {
1045 switch (fwhdr
->hdr_minor
) {
1050 SCSC_TAG_ERR(MXMAN
, "Unsupported FW HEADER version: hdr_major: %d hdr_minor: %d\n",
1051 fwhdr
->hdr_major
, fwhdr
->hdr_minor
);
1059 SCSC_TAG_ERR(MXMAN
, "Unsupported FW HEADER version: hdr_major: %d hdr_minor: %d\n",
1060 fwhdr
->hdr_major
, fwhdr
->hdr_minor
);
1063 switch (fwhdr
->fwapi_major
) {
1065 switch (fwhdr
->fwapi_minor
) {
1067 SCSC_TAG_INFO(MXMAN
, "FWAPI version: fwapi_major: %d fwapi_minor: %d\n",
1068 fwhdr
->fwapi_major
, fwhdr
->fwapi_minor
);
1071 SCSC_TAG_ERR(MXMAN
, "Unsupported FWAPI version: fwapi_major: %d fwapi_minor: %d\n",
1072 fwhdr
->fwapi_major
, fwhdr
->fwapi_minor
);
1077 SCSC_TAG_ERR(MXMAN
, "Unsupported FWAPI version: fwapi_major: %d fwapi_minor: %d\n",
1078 fwhdr
->fwapi_major
, fwhdr
->fwapi_minor
);
1082 /* This is unidetified pre-header firmware - assume it is built to run at 0xb8000000 == 0 for bootrom */
1083 if (allow_unidentified_firmware
) {
1084 SCSC_TAG_INFO(MXMAN
, "Unidentified firmware override\n");
1085 fwhdr
->firmware_entry_point
= 0;
1086 fwhdr
->fw_runtime_length
= MX_FW_RUNTIME_LENGTH
;
1088 SCSC_TAG_ERR(MXMAN
, "Unidentified firmware is not allowed\n");
1095 static int fw_init(struct mxman
*mxman
, void *start_dram
, size_t size_dram
, bool *fwhdr_parsed_ok
)
1101 struct fwhdr
*fwhdr
= &mxman
->fwhdr
;
1102 char *fw
= start_dram
;
1104 r
= mx140_file_download_fw(mxman
->mx
, start_dram
, size_dram
, &fw_image_size
);
1106 SCSC_TAG_ERR(MXMAN
, "mx140_file_download_fw() failed (%d)\n", r
);
1110 r
= fwhdr_init(fw
, fwhdr
, fwhdr_parsed_ok
, &mxman
->check_crc
);
1112 SCSC_TAG_ERR(MXMAN
, "fwhdr_init() failed\n");
1116 mxman
->fw_image_size
= fw_image_size
;
1117 if (mxman
->check_crc
) {
1118 /* do CRC on the entire image */
1119 r
= do_fw_crc32_checks(fw
, fw_image_size
, &mxman
->fwhdr
, true);
1121 SCSC_TAG_ERR(MXMAN
, "do_fw_crc32_checks() failed\n");
1124 fw_crc_wq_start(mxman
);
1127 if (*fwhdr_parsed_ok
) {
1128 build_id
= fwhdr_get_build_id(fw
, fwhdr
);
1130 struct slsi_kic_service_info kic_info
;
1132 (void)snprintf(mxman
->fw_build_id
, sizeof(mxman
->fw_build_id
), "%s", build_id
);
1133 SCSC_TAG_INFO(MXMAN
, "Firmware BUILD_ID: %s\n", mxman
->fw_build_id
);
1134 memcpy(saved_fw_build_id
, mxman
->fw_build_id
,
1135 sizeof(saved_fw_build_id
));
1137 (void) snprintf(kic_info
.ver_str
,
1138 min(sizeof(mxman
->fw_build_id
), sizeof(kic_info
.ver_str
)),
1139 "%s", mxman
->fw_build_id
);
1140 kic_info
.fw_api_major
= fwhdr
->fwapi_major
;
1141 kic_info
.fw_api_minor
= fwhdr
->fwapi_minor
;
1142 kic_info
.release_product
= SCSC_RELEASE_PRODUCT
;
1143 kic_info
.host_release_iteration
= SCSC_RELEASE_ITERATION
;
1144 kic_info
.host_release_candidate
= SCSC_RELEASE_CANDIDATE
;
1146 slsi_kic_service_information(slsi_kic_technology_type_common
, &kic_info
);
1148 SCSC_TAG_ERR(MXMAN
, "Failed to get Firmware BUILD_ID\n");
1150 ttid
= fwhdr_get_ttid(fw
, fwhdr
);
1152 (void)snprintf(mxman
->fw_ttid
, sizeof(mxman
->fw_ttid
), "%s", ttid
);
1153 SCSC_TAG_INFO(MXMAN
, "Firmware ttid: %s\n", mxman
->fw_ttid
);
1157 SCSC_TAG_DEBUG(MXMAN
, "firmware_entry_point=0x%x fw_runtime_length=%d\n", fwhdr
->firmware_entry_point
, fwhdr
->fw_runtime_length
);
1163 static int mxman_start(struct mxman
*mxman
)
1166 size_t size_dram
= MX_DRAM_SIZE
;
1167 struct scsc_mif_abs
*mif
;
1168 struct fwhdr
*fwhdr
= &mxman
->fwhdr
;
1169 bool fwhdr_parsed_ok
;
1170 void *start_mifram_heap
;
1171 u32 length_mifram_heap
;
1172 void *start_mifram_heap2
;
1173 u32 length_mifram_heap2
;
1177 struct timeval tval
= ns_to_timeval(reset_failed_time
);
1179 SCSC_TAG_ERR(MXMAN
, "previous reset failed at [%6lu.%06ld], ignoring\n", tval
.tv_sec
, tval
.tv_usec
);
1183 (void)snprintf(mxman
->fw_build_id
, sizeof(mxman
->fw_build_id
), "unknown");
1185 /* If the option is set to skip header, we must allow unidentified f/w */
1187 SCSC_TAG_INFO(MXMAN
, "Ignoring firmware header block\n");
1188 allow_unidentified_firmware
= true;
1191 mif
= scsc_mx_get_mif_abs(mxman
->mx
);
1192 start_dram
= mif
->map(mif
, &size_dram
);
1195 SCSC_TAG_ERR(MXMAN
, "Error allocating dram\n");
1199 SCSC_TAG_INFO(MXMAN
, "Allocated %zu bytes\n", size_dram
);
1201 #ifdef CONFIG_SCSC_CHV_SUPPORT
1203 allow_unidentified_firmware
= true;
1204 /* Set up chv arguments. */
1208 mxman
->start_dram
= start_dram
;
1210 r
= fw_init(mxman
, start_dram
, size_dram
, &fwhdr_parsed_ok
);
1212 SCSC_TAG_ERR(MXMAN
, "fw_init() failed\n");
1213 mif
->unmap(mif
, mxman
->start_dram
);
1217 /* set up memory protection (read only) from start_dram to start_dram+fw_length
1218 * rounding up the size if required
1220 start_mifram_heap
= (char *)start_dram
+ fwhdr
->fw_runtime_length
;
1221 length_mifram_heap
= MX_DRAM_SIZE_SECTION_1
- fwhdr
->fw_runtime_length
;
1224 start_mifram_heap2
= (char *)start_dram
+ MX_DRAM_SIZE_SECTION_2
;
1226 /* ABox reserved at end so adjust length - round to multiple of PAGE_SIZE */
1227 length_mifram_heap2
= MX_DRAM_SIZE_SECTION_2
-
1228 ((sizeof(struct scsc_bt_audio_abox
) + PAGE_SIZE
- 1) & ~(PAGE_SIZE
- 1));
1230 miframman_init(scsc_mx_get_ramman(mxman
->mx
), start_mifram_heap
, length_mifram_heap
, start_dram
);
1231 miframman_init(scsc_mx_get_ramman2(mxman
->mx
), start_mifram_heap2
, length_mifram_heap2
, start_mifram_heap2
);
1232 miframabox_init(scsc_mx_get_aboxram(mxman
->mx
), start_mifram_heap2
+ length_mifram_heap2
);
1233 mifmboxman_init(scsc_mx_get_mboxman(mxman
->mx
));
1234 mifintrbit_init(scsc_mx_get_intrbit(mxman
->mx
), mif
);
1235 mxfwconfig_init(mxman
->mx
);
1237 /* Initialise transports */
1238 r
= transports_init(mxman
);
1240 SCSC_TAG_ERR(MXMAN
, "transports_init() failed\n");
1241 fw_crc_wq_stop(mxman
);
1242 mifintrbit_deinit(scsc_mx_get_intrbit(mxman
->mx
));
1243 miframman_deinit(scsc_mx_get_ramman(mxman
->mx
));
1244 miframman_deinit(scsc_mx_get_ramman2(mxman
->mx
));
1245 miframabox_deinit(scsc_mx_get_aboxram(mxman
->mx
));
1246 mifmboxman_deinit(scsc_mx_get_mboxman(mxman
->mx
));
1247 /* Release the MIF memory resources */
1248 mif
->unmap(mif
, mxman
->start_dram
);
1251 mbox_init(mxman
, fwhdr
->firmware_entry_point
);
1252 init_completion(&mxman
->mm_msg_start_ind_completion
);
1253 init_completion(&mxman
->mm_msg_halt_rsp_completion
);
1254 mxmgmt_transport_register_channel_handler(scsc_mx_get_mxmgmt_transport(mxman
->mx
),
1255 MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT
,
1256 &mxman_message_handler
, mxman
);
1258 mxlog_init(scsc_mx_get_mxlog(mxman
->mx
), mxman
->mx
, mxman
->fw_build_id
);
1259 #ifdef CONFIG_SCSC_MXLOGGER
1260 mxlogger_init(mxman
->mx
, scsc_mx_get_mxlogger(mxman
->mx
), MXL_POOL_SZ
);
1262 #ifdef CONFIG_SCSC_LOG_COLLECTION
1263 /* Register minimoredump client */
1264 mini_moredump_client
.prv
= mxman
;
1265 scsc_log_collector_register_client(&mini_moredump_client
);
1268 #ifdef CONFIG_SCSC_SMAPPER
1269 /* Initialize SMAPPER */
1270 mifsmapper_init(scsc_mx_get_smapper(mxman
->mx
), mif
);
1272 #ifdef CONFIG_SCSC_QOS
1273 mifqos_init(scsc_mx_get_qos(mxman
->mx
), mif
);
1276 #ifdef CONFIG_SCSC_CHV_SUPPORT
1280 u32
*p
= (u32
*)((u8
*)start_dram
+ SCSC_CHV_ARGV_ADDR_OFFSET
);
1282 if (chv_argc
== 0) {
1284 * Setup the chv f/w arguments.
1285 * Argument of 0 means run once (driver never set this).
1286 * Argument of 1 means run forever.
1288 SCSC_TAG_INFO(MXMAN
, "Setting up CHV arguments: start_dram=%p arg=%p, chv_run=%d\n", start_dram
, p
, chv_run
);
1289 *p
++ = 1; /* argc */
1290 *p
++ = chv_run
== 1 ? 0 : 1; /* arg */
1292 /* Pass separate args */
1293 *p
++ = chv_argc
; /* argc */
1294 SCSC_TAG_INFO(MXMAN
, "Setting up additional CHV args: chv_argc = %d\n", chv_argc
);
1296 for (i
= 0; i
< chv_argc
; i
++) {
1297 SCSC_TAG_INFO(MXMAN
, "Setting up additional CHV args: chv_argv[%d]: *(%p) = 0x%x\n", i
, p
, (u32
)chv_argv
[i
]);
1298 *p
++ = (u32
)chv_argv
[i
]; /* arg */
1303 mxproc_create_ctrl_proc_dir(&mxman
->mxproc
, mxman
);
1304 panicmon_init(scsc_mx_get_panicmon(mxman
->mx
), mxman
->mx
);
1306 /* Change state to STARTING to allow coredump as we come out of reset */
1307 mxman
->mxman_state
= MXMAN_STATE_STARTING
;
1309 /* release Maxwell from reset */
1310 r
= mif
->reset(mif
, 0);
1312 reset_failed
= true;
1313 SCSC_TAG_INFO(MXMAN
, "HW reset deassertion failed\n");
1315 /* Save log at point of failure */
1316 #ifdef CONFIG_SCSC_LOG_COLLECTION
1317 scsc_log_collector_schedule_collection(SCSC_LOG_HOST_COMMON
, SCSC_LOG_HOST_COMMON_REASON_START
);
1322 if (fwhdr_parsed_ok
) {
1323 r
= wait_for_mm_msg_start_ind(mxman
);
1325 SCSC_TAG_ERR(MXMAN
, "wait_for_MM_START_IND() failed: r=%d\n", r
);
1326 print_mailboxes(mxman
);
1327 if (skip_mbox0_check
) {
1328 SCSC_TAG_ERR(MXMAN
, "timeout ignored in skip_mbox0_check mode\n");
1334 #ifdef CONFIG_SCSC_MXLOGGER
1335 mxlogger_start(scsc_mx_get_mxlogger(mxman
->mx
));
1338 msleep(WAIT_FOR_FW_TO_START_DELAY_MS
);
1344 static bool is_bug_on_enabled(struct scsc_mx
*mx
)
1346 bool bug_on_enabled
;
1347 const struct firmware
*firm
;
1350 if ((memdump
== 3) && (disable_recovery_handling
== MEMDUMP_FILE_FOR_RECOVERY
))
1351 bug_on_enabled
= true;
1353 bug_on_enabled
= false;
1354 #ifdef CONFIG_SCSC_LOG_COLLECTION
1355 (void)firm
; /* unused */
1356 (void)r
; /* unused */
1357 return bug_on_enabled
;
1359 /* non SABLE platforms should also follow /sys/wifi/memdump if enabled */
1360 if (disable_recovery_handling
== MEMDUMP_FILE_FOR_RECOVERY
)
1361 return bug_on_enabled
;
1363 /* for legacy platforms (including Andorid P) using .memdump.info */
1364 #if defined(ANDROID_VERSION) && (ANDROID_VERSION >= 90000)
1365 #define MX140_MEMDUMP_INFO_FILE "/data/vendor/conn/.memdump.info"
1367 #define MX140_MEMDUMP_INFO_FILE "/data/misc/conn/.memdump.info"
1370 SCSC_TAG_INFO(MX_FILE
, "Loading %s file\n", MX140_MEMDUMP_INFO_FILE
);
1371 r
= mx140_request_file(mx
, MX140_MEMDUMP_INFO_FILE
, &firm
);
1373 SCSC_TAG_WARNING(MX_FILE
, "Error Loading %s file %d\n", MX140_MEMDUMP_INFO_FILE
, r
);
1374 return bug_on_enabled
;
1376 if (firm
->size
< sizeof(char))
1377 SCSC_TAG_WARNING(MX_FILE
, "file is too small\n");
1378 else if (*firm
->data
== '3')
1379 bug_on_enabled
= true;
1380 mx140_release_file(mx
, firm
);
1381 SCSC_TAG_INFO(MX_FILE
, "bug_on_enabled %d\n", bug_on_enabled
);
1382 return bug_on_enabled
;
1383 #endif //CONFIG_SCSC_LOG_COLLECTION
1386 static void print_panic_code_legacy(u16 code
)
1388 u16 tech
= code
& SCSC_PANIC_TECH_MASK
;
1389 u16 origin
= code
& SCSC_PANIC_ORIGIN_MASK
;
1391 SCSC_TAG_INFO(MXMAN
, "Decoding panic code=0x%x:\n", code
);
1394 SCSC_TAG_INFO(MXMAN
, "Failed to identify panic origin\n");
1396 case SCSC_PANIC_ORIGIN_FW
:
1397 SCSC_TAG_INFO(MXMAN
, "SCSC_PANIC_ORIGIN_FW\n");
1399 case SCSC_PANIC_ORIGIN_HOST
:
1400 SCSC_TAG_INFO(MXMAN
, "SCSC_PANIC_ORIGIN_HOST\n");
1406 SCSC_TAG_INFO(MXMAN
, "Failed to identify panic technology\n");
1408 case SCSC_PANIC_TECH_WLAN
:
1409 SCSC_TAG_INFO(MXMAN
, "SCSC_PANIC_TECH_WLAN\n");
1411 case SCSC_PANIC_TECH_CORE
:
1412 SCSC_TAG_INFO(MXMAN
, "SCSC_PANIC_TECH_CORE\n");
1414 case SCSC_PANIC_TECH_BT
:
1415 SCSC_TAG_INFO(MXMAN
, "SCSC_PANIC_TECH_BT\n");
1417 case SCSC_PANIC_TECH_UNSP
:
1418 SCSC_TAG_INFO(MXMAN
, "PANIC_TECH_UNSP\n");
1421 SCSC_TAG_INFO(MXMAN
, "panic subcode=0x%x\n", code
& SCSC_PANIC_SUBCODE_MASK_LEGACY
);
1424 static void print_panic_code(u16 code
)
1426 u16 origin
= code
& SCSC_PANIC_ORIGIN_MASK
; /* Panic origin (host/fw) */
1427 u16 subcode
= code
& SCSC_PANIC_SUBCODE_MASK
; /* The panic code */
1429 SCSC_TAG_INFO(MXMAN
, "Decoding panic code=0x%x:\n", code
);
1430 SCSC_TAG_INFO(MXMAN
, "panic subcode=0x%x\n", code
& SCSC_PANIC_SUBCODE_MASK
);
1434 SCSC_TAG_INFO(MXMAN
, "Failed to identify panic origin\n");
1436 case SCSC_PANIC_ORIGIN_FW
:
1437 SCSC_TAG_INFO(MXMAN
, "WLBT FW PANIC: 0x%02x\n", subcode
);
1439 case SCSC_PANIC_ORIGIN_HOST
:
1440 SCSC_TAG_INFO(MXMAN
, "WLBT HOST detected FW failure, service:\n");
1441 switch (subcode
>> SCSC_SYSERR_HOST_SERVICE_SHIFT
) {
1442 case SCSC_SERVICE_ID_WLAN
:
1443 SCSC_TAG_INFO(MXMAN
, " WLAN\n");
1445 case SCSC_SERVICE_ID_BT
:
1446 SCSC_TAG_INFO(MXMAN
, " BT\n");
1448 case SCSC_SERVICE_ID_ANT
:
1449 SCSC_TAG_INFO(MXMAN
, " ANT\n");
1451 case SCSC_SERVICE_ID_CLK20MHZ
:
1452 SCSC_TAG_INFO(MXMAN
, " CLK20MHZ\n");
1455 SCSC_TAG_INFO(MXMAN
, " Service 0x%x\n", subcode
);
1463 * Print the last panic record collected to aid in post mortem.
1465 * Helps when all we have is kernel log showing WLBT failed some time ago
1467 * Only prints the R4 record
1469 void mxman_show_last_panic(struct mxman
*mxman
)
1471 u32 r4_panic_record_length
= 0; /* in u32s */
1473 /* Any valid panic? */
1474 if (mxman
->scsc_panic_code
== 0)
1477 SCSC_TAG_INFO(MXMAN
, "\n\n--- DETAILS OF LAST WLBT FAILURE ---\n\n");
1479 switch (mxman
->scsc_panic_code
& SCSC_PANIC_ORIGIN_MASK
) {
1480 case SCSC_PANIC_ORIGIN_HOST
:
1481 SCSC_TAG_INFO(MXMAN
, "Last panic was host induced:\n");
1484 case SCSC_PANIC_ORIGIN_FW
:
1485 SCSC_TAG_INFO(MXMAN
, "Last panic was FW:\n");
1486 fw_parse_r4_panic_record(mxman
->last_panic_rec_r
, &r4_panic_record_length
);
1490 SCSC_TAG_INFO(MXMAN
, "Last panic unknown origin %d\n", mxman
->scsc_panic_code
& SCSC_PANIC_ORIGIN_MASK
);
1494 print_panic_code(mxman
->scsc_panic_code
);
1496 SCSC_TAG_INFO(MXMAN
, "Reason: '%s'\n", mxman
->failure_reason
[0] ? mxman
->failure_reason
: "<null>");
1497 SCSC_TAG_INFO(MXMAN
, "Auto-recovery: %s\n", disable_recovery_handling
? "off" : "on");
1499 if (mxman_recovery_disabled()) {
1500 /* Labour the point that a reboot is needed when autorecovery is disabled */
1501 SCSC_TAG_INFO(MXMAN
, "\n\n*** HANDSET REBOOT NEEDED TO RESTART WLAN AND BT ***\n\n");
1504 SCSC_TAG_INFO(MXMAN
, "\n\n--- END DETAILS OF LAST WLBT FAILURE ---\n\n");
1507 static void process_panic_record(struct mxman
*mxman
)
1509 u32
*r4_panic_record
= NULL
;
1510 u32
*m4_panic_record
= NULL
;
1511 #ifdef CONFIG_SCSC_MX450_GDB_SUPPORT
1512 u32
*m4_1_panic_record
= NULL
;
1514 u32 r4_panic_record_length
= 0; /* in u32s */
1515 u32 m4_panic_record_length
= 0; /* in u32s */
1516 #ifdef CONFIG_SCSC_MX450_GDB_SUPPORT
1517 u32 m4_1_panic_record_length
= 0; /* in u32s */
1519 u32 full_panic_code
= 0;
1520 bool r4_panic_record_ok
= false;
1521 bool m4_panic_record_ok
= false;
1522 #ifdef CONFIG_SCSC_MX450_GDB_SUPPORT
1523 bool m4_1_panic_record_ok
= false;
1525 bool r4_sympathetic_panic_flag
= false;
1526 bool m4_sympathetic_panic_flag
= false;
1527 #ifdef CONFIG_SCSC_MX450_GDB_SUPPORT
1528 bool m4_1_sympathetic_panic_flag
= false;
1531 /* some configurable delay before accessing the panic record */
1532 msleep(panic_record_delay
);
1534 * Check if the panic was trigered by MX and set the subcode if so.
1536 if ((mxman
->scsc_panic_code
& SCSC_PANIC_ORIGIN_MASK
) == SCSC_PANIC_ORIGIN_FW
) {
1537 if (mxman
->fwhdr
.r4_panic_record_offset
) {
1538 r4_panic_record
= (u32
*)(mxman
->fw
+ mxman
->fwhdr
.r4_panic_record_offset
);
1539 r4_panic_record_ok
= fw_parse_r4_panic_record(r4_panic_record
, &r4_panic_record_length
);
1541 SCSC_TAG_INFO(MXMAN
, "R4 panic record doesn't exist in the firmware header\n");
1543 if (mxman
->fwhdr
.m4_panic_record_offset
) {
1544 m4_panic_record
= (u32
*)(mxman
->fw
+ mxman
->fwhdr
.m4_panic_record_offset
);
1545 m4_panic_record_ok
= fw_parse_m4_panic_record(m4_panic_record
, &m4_panic_record_length
);
1546 #ifdef CONFIG_SCSC_MX450_GDB_SUPPORT
1547 } else if (mxman
->fwhdr
.m4_1_panic_record_offset
) {
1548 m4_1_panic_record
= (u32
*)(mxman
->fw
+ mxman
->fwhdr
.m4_1_panic_record_offset
);
1549 m4_1_panic_record_ok
= fw_parse_m4_panic_record(m4_1_panic_record
, &m4_1_panic_record_length
);
1552 SCSC_TAG_INFO(MXMAN
, "M4 panic record doesn't exist in the firmware header\n");
1555 /* Extract and print the panic code */
1556 switch (r4_panic_record_length
) {
1558 SCSC_TAG_WARNING(MXMAN
, "Bad panic record length/subversion\n");
1560 case SCSC_R4_V2_MINOR_52
:
1561 if (r4_panic_record_ok
) {
1562 full_panic_code
= r4_panic_record
[2];
1563 mxman
->scsc_panic_code
|= SCSC_PANIC_CODE_MASK
& full_panic_code
;
1564 } else if (m4_panic_record_ok
)
1565 mxman
->scsc_panic_code
|= SCSC_PANIC_CODE_MASK
& m4_panic_record
[2];
1566 #ifdef CONFIG_SCSC_MX450_GDB_SUPPORT
1567 else if (m4_1_panic_record_ok
)
1568 mxman
->scsc_panic_code
|= SCSC_PANIC_CODE_MASK
& m4_1_panic_record
[2];
1570 /* Set unspecified technology for now */
1571 mxman
->scsc_panic_code
|= SCSC_PANIC_TECH_UNSP
;
1572 print_panic_code_legacy(mxman
->scsc_panic_code
);
1574 case SCSC_R4_V2_MINOR_53
:
1575 if (r4_panic_record_ok
) {
1576 /* Save the last R4 panic record for future display */
1577 BUG_ON(sizeof(mxman
->last_panic_rec_r
) < SCSC_R4_V2_MINOR_53
* sizeof(u32
));
1578 memcpy((u8
*)mxman
->last_panic_rec_r
, (u8
*)r4_panic_record
, SCSC_R4_V2_MINOR_53
* sizeof(u32
));
1579 mxman
->last_panic_rec_sz
= r4_panic_record_length
;
1581 r4_sympathetic_panic_flag
= fw_parse_get_r4_sympathetic_panic_flag(r4_panic_record
);
1582 SCSC_TAG_INFO(MXMAN
, "r4_panic_record_ok=%d r4_sympathetic_panic_flag=%d\n",
1584 r4_sympathetic_panic_flag
1586 if (r4_sympathetic_panic_flag
== false) {
1587 /* process R4 record */
1588 SCSC_TAG_INFO(MXMAN
, "process R4 record\n");
1589 full_panic_code
= r4_panic_record
[3];
1590 mxman
->scsc_panic_code
|= SCSC_PANIC_CODE_MASK
& full_panic_code
;
1591 print_panic_code(mxman
->scsc_panic_code
);
1595 if (m4_panic_record_ok
) {
1596 m4_sympathetic_panic_flag
= fw_parse_get_m4_sympathetic_panic_flag(m4_panic_record
);
1597 SCSC_TAG_INFO(MXMAN
, "m4_panic_record_ok=%d m4_sympathetic_panic_flag=%d\n",
1599 m4_sympathetic_panic_flag
1601 if (m4_sympathetic_panic_flag
== false) {
1602 /* process M4 record */
1603 SCSC_TAG_INFO(MXMAN
, "process M4 record\n");
1604 mxman
->scsc_panic_code
|= SCSC_PANIC_CODE_MASK
& m4_panic_record
[3];
1605 } else if (r4_panic_record_ok
) {
1606 /* process R4 record */
1607 SCSC_TAG_INFO(MXMAN
, "process R4 record\n");
1608 mxman
->scsc_panic_code
|= SCSC_PANIC_CODE_MASK
& r4_panic_record
[3];
1610 print_panic_code(mxman
->scsc_panic_code
);
1612 #ifdef CONFIG_SCSC_MX450_GDB_SUPPORT /* this is wrong but not sure what is "right" */
1613 /* "sympathetic panics" are not really a thing on the Neus architecture unless */
1614 /* generated by the host */
1615 if (m4_1_panic_record_ok
) {
1616 m4_1_sympathetic_panic_flag
= fw_parse_get_m4_sympathetic_panic_flag(m4_panic_record
);
1617 SCSC_TAG_INFO(MXMAN
, "m4_1_panic_record_ok=%d m4_1_sympathetic_panic_flag=%d\n",
1618 m4_1_panic_record_ok
,
1619 m4_1_sympathetic_panic_flag
1621 if (m4_1_sympathetic_panic_flag
== false) {
1622 /* process M4 record */
1623 SCSC_TAG_INFO(MXMAN
, "process M4_1 record\n");
1624 mxman
->scsc_panic_code
|= SCSC_PANIC_SUBCODE_MASK
& m4_1_panic_record
[3];
1625 } else if (r4_panic_record_ok
) {
1626 /* process R4 record */
1627 SCSC_TAG_INFO(MXMAN
, "process R4 record\n");
1628 mxman
->scsc_panic_code
|= SCSC_PANIC_SUBCODE_MASK
& r4_panic_record
[3];
1630 print_panic_code(mxman
->scsc_panic_code
);
1636 if (r4_panic_record_ok
) {
1637 /* Populate syserr info with panic equivalent */
1638 mxman
->last_syserr
.subsys
= (u8
) ((full_panic_code
>> SYSERR_SUB_SYSTEM_POSN
) & SYSERR_SUB_SYSTEM_MASK
);
1639 mxman
->last_syserr
.level
= MX_SYSERR_LEVEL_7
;
1640 mxman
->last_syserr
.type
= (u8
) ((full_panic_code
>> SYSERR_TYPE_POSN
) & SYSERR_TYPE_MASK
);
1641 mxman
->last_syserr
.subcode
= (u16
) ((full_panic_code
>> SYSERR_SUB_CODE_POSN
) & SYSERR_SUB_CODE_MASK
);
1645 #define MAX_UHELP_TMO_MS 20000
1649 static void mxman_failure_work(struct work_struct
*work
)
1651 struct mxman
*mxman
= container_of(work
, struct mxman
, failure_work
);
1652 struct srvman
*srvman
;
1653 struct scsc_mx
*mx
= mxman
->mx
;
1654 struct scsc_mif_abs
*mif
= scsc_mx_get_mif_abs(mxman
->mx
);
1655 int used
= 0, r
= 0;
1657 #ifdef CONFIG_ANDROID
1658 wake_lock(&mxman
->failure_recovery_wake_lock
);
1660 /* Take mutex shared with syserr recovery */
1661 mutex_lock(&mxman
->mxman_recovery_mutex
);
1663 slsi_kic_system_event(slsi_kic_system_event_category_error
,
1664 slsi_kic_system_events_subsystem_crashed
, GFP_KERNEL
);
1666 blocking_notifier_call_chain(&firmware_chain
, SCSC_FW_EVENT_FAILURE
, NULL
);
1668 SCSC_TAG_INFO(MXMAN
, "Complete mm_msg_start_ind_completion\n");
1669 complete(&mxman
->mm_msg_start_ind_completion
);
1670 mutex_lock(&mxman
->mxman_mutex
);
1671 srvman
= scsc_mx_get_srvman(mxman
->mx
);
1673 if (mxman
->mxman_state
!= MXMAN_STATE_STARTED
&& mxman
->mxman_state
!= MXMAN_STATE_STARTING
) {
1674 SCSC_TAG_WARNING(MXMAN
, "Not in started state: mxman->mxman_state=%d\n", mxman
->mxman_state
);
1675 #ifdef CONFIG_ANDROID
1676 wake_unlock(&mxman
->failure_recovery_wake_lock
);
1678 mutex_unlock(&mxman
->mxman_mutex
);
1679 mutex_unlock(&mxman
->mxman_recovery_mutex
);
1684 * Set error on mxlog and unregister mxlog msg-handlers.
1685 * mxlog ISR and kthread will ignore further messages
1686 * but mxlog_thread is NOT stopped here.
1688 mxlog_transport_set_error(scsc_mx_get_mxlog_transport(mx
));
1689 mxlog_release(scsc_mx_get_mxlog(mx
));
1690 /* unregister channel handler */
1691 mxmgmt_transport_register_channel_handler(scsc_mx_get_mxmgmt_transport(mx
), MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT
,
1693 mxmgmt_transport_set_error(scsc_mx_get_mxmgmt_transport(mx
));
1694 srvman_set_error(srvman
);
1695 fw_crc_wq_stop(mxman
);
1697 mxman
->mxman_state
= mxman
->mxman_next_state
;
1699 /* Mark any single service recovery as no longer in progress */
1700 mxman
->syserr_recovery_in_progress
= false;
1701 mxman
->last_syserr_recovery_time
= 0;
1703 if (mxman
->mxman_state
!= MXMAN_STATE_FAILED
1704 && mxman
->mxman_state
!= MXMAN_STATE_FROZEN
) {
1705 WARN_ON(mxman
->mxman_state
!= MXMAN_STATE_FAILED
1706 && mxman
->mxman_state
!= MXMAN_STATE_FROZEN
);
1707 SCSC_TAG_ERR(MXMAN
, "Bad state=%d\n", mxman
->mxman_state
);
1708 #ifdef CONFIG_ANDROID
1709 wake_unlock(&mxman
->failure_recovery_wake_lock
);
1711 mutex_unlock(&mxman
->mxman_mutex
);
1712 mutex_unlock(&mxman
->mxman_recovery_mutex
);
1715 /* Signal panic to r4 and m4 processors */
1716 SCSC_TAG_INFO(MXMAN
, "Setting MIFINTRBIT_RESERVED_PANIC_R4\n");
1717 mif
->irq_bit_set(mif
, MIFINTRBIT_RESERVED_PANIC_R4
, SCSC_MIF_ABS_TARGET_R4
); /* SCSC_MIFINTR_TARGET_R4 */
1718 #ifdef CONFIG_SCSC_MX450_GDB_SUPPORT
1719 SCSC_TAG_INFO(MXMAN
, "Setting MIFINTRBIT_RESERVED_PANIC_M4\n");
1720 mif
->irq_bit_set(mif
, MIFINTRBIT_RESERVED_PANIC_M4
, SCSC_MIF_ABS_TARGET_M4
); /* SCSC_MIFINTR_TARGET_M4 */
1721 SCSC_TAG_INFO(MXMAN
, "Setting MIFINTRBIT_RESERVED_PANIC_M4_1\n");
1722 mif
->irq_bit_set(mif
, MIFINTRBIT_RESERVED_PANIC_M4_1
, SCSC_MIF_ABS_TARGET_M4_1
); /* SCSC_MIFINTR_TARGET_M4 */
1724 SCSC_TAG_INFO(MXMAN
, "Setting MIFINTRBIT_RESERVED_PANIC_M4\n");
1725 mif
->irq_bit_set(mif
, MIFINTRBIT_RESERVED_PANIC_M4
, SCSC_MIF_ABS_TARGET_M4
); /* SCSC_MIFINTR_TARGET_M4 */
1727 srvman_freeze_services(srvman
, &mxman
->last_syserr
);
1728 if (mxman
->mxman_state
== MXMAN_STATE_FAILED
) {
1729 mxman
->last_panic_time
= local_clock();
1730 process_panic_record(mxman
);
1731 SCSC_TAG_INFO(MXMAN
, "Trying to schedule coredump\n");
1732 SCSC_TAG_INFO(MXMAN
, "scsc_release %d.%d.%d.%d\n",
1733 SCSC_RELEASE_PRODUCT
,
1734 SCSC_RELEASE_ITERATION
,
1735 SCSC_RELEASE_CANDIDATE
,
1736 SCSC_RELEASE_POINT
);
1737 SCSC_TAG_INFO(MXMAN
, "Auto-recovery: %s\n", mxman_recovery_disabled() ? "off" : "on");
1738 #ifdef CONFIG_SCSC_WLBTD
1739 scsc_wlbtd_get_and_print_build_type();
1742 /* schedule coredump and wait for it to finish */
1743 if (disable_auto_coredump
) {
1744 SCSC_TAG_INFO(MXMAN
, "Driver automatic coredump disabled, not launching coredump helper\n");
1747 * Releasing mxman_mutex here gives way to any
1748 * eventually running resume process while waiting for
1749 * the usermode helper subsystem to be resurrected,
1750 * since this last will be re-enabled right at the end
1751 * of the resume process itself.
1753 mutex_unlock(&mxman
->mxman_mutex
);
1754 SCSC_TAG_INFO(MXMAN
,
1755 "waiting up to %dms for usermode_helper subsystem.\n",
1757 /* Waits for the usermode_helper subsytem to be re-enabled. */
1758 if (usermodehelper_read_lock_wait(msecs_to_jiffies(MAX_UHELP_TMO_MS
))) {
1760 * Release immediately the rwsem on usermode_helper
1761 * enabled since we anyway already hold a wakelock here
1763 usermodehelper_read_unlock();
1765 * We claim back the mxman_mutex immediately to avoid anyone
1766 * shutting down the chip while we are dumping the coredump.
1768 mutex_lock(&mxman
->mxman_mutex
);
1769 SCSC_TAG_INFO(MXMAN
, "Invoking coredump helper\n");
1770 slsi_kic_system_event(slsi_kic_system_event_category_recovery
,
1771 slsi_kic_system_events_coredump_in_progress
,
1773 #ifdef CONFIG_SCSC_WLBTD
1774 /* we can safely call call_wlbtd as we are
1775 * in workqueue context
1777 #ifdef CONFIG_SCSC_LOG_COLLECTION
1778 /* Collect mxlogger logs */
1779 scsc_log_collector_schedule_collection(SCSC_LOG_FW_PANIC
, mxman
->scsc_panic_code
);
1781 r
= call_wlbtd(SCSC_SCRIPT_MOREDUMP
);
1784 r
= coredump_helper();
1787 slsi_kic_system_event(slsi_kic_system_event_category_recovery
,
1788 slsi_kic_system_events_coredump_done
, GFP_KERNEL
);
1791 used
= snprintf(panic_record_dump
,
1792 PANIC_RECORD_DUMP_BUFFER_SZ
,
1793 "RF HW Ver: 0x%X\n", mxman
->rf_hw_ver
);
1794 used
+= snprintf(panic_record_dump
+ used
,
1795 PANIC_RECORD_DUMP_BUFFER_SZ
- used
,
1796 "SCSC Panic Code:: 0x%X\n", mxman
->scsc_panic_code
);
1797 used
+= snprintf(panic_record_dump
+ used
,
1798 PANIC_RECORD_DUMP_BUFFER_SZ
- used
,
1799 "SCSC Last Panic Time:: %lld\n", mxman
->last_panic_time
);
1800 panic_record_dump_buffer("r4", mxman
->last_panic_rec_r
,
1801 mxman
->last_panic_rec_sz
,
1802 panic_record_dump
+ used
,
1803 PANIC_RECORD_DUMP_BUFFER_SZ
- used
);
1805 /* Print the host code/reason again so it's near the FW panic
1806 * record in the kernel log
1808 print_panic_code(mxman
->scsc_panic_code
);
1809 SCSC_TAG_INFO(MXMAN
, "Reason: '%s'\n", mxman
->failure_reason
[0] ? mxman
->failure_reason
: "<null>");
1811 blocking_notifier_call_chain(&firmware_chain
,
1812 SCSC_FW_EVENT_MOREDUMP_COMPLETE
,
1813 &panic_record_dump
);
1815 SCSC_TAG_INFO(MXMAN
,
1816 "timed out waiting for usermode_helper. Skipping coredump.\n");
1817 mutex_lock(&mxman
->mxman_mutex
);
1821 if (is_bug_on_enabled(mx
)) {
1822 SCSC_TAG_ERR(MX_FILE
, "Deliberately panic the kernel due to WLBT firmware failure!\n");
1823 SCSC_TAG_ERR(MX_FILE
, "calling BUG_ON(1)\n");
1826 /* Clean up the MIF following error handling */
1827 if (mif
->mif_cleanup
&& mxman_recovery_disabled())
1828 mif
->mif_cleanup(mif
);
1830 /* Populate syserr info with panic equivalent for host induced panic */
1831 mxman
->last_syserr
.subsys
= SYSERR_SUB_SYSTEM_HOST
;
1832 mxman
->last_syserr
.level
= MX_SYSERR_LEVEL_7
;
1833 mxman
->last_syserr
.type
= 0;
1834 mxman
->last_syserr
.subcode
= mxman
->scsc_panic_code
;
1837 SCSC_TAG_INFO(MXMAN
, "Auto-recovery: %s\n",
1838 mxman_recovery_disabled() ? "off" : "on");
1840 if (!mxman_recovery_disabled())
1841 srvman_clear_error(srvman
);
1842 mutex_unlock(&mxman
->mxman_mutex
);
1843 if (!mxman_recovery_disabled()) {
1844 SCSC_TAG_INFO(MXMAN
, "Calling srvman_unfreeze_services\n");
1845 srvman_unfreeze_services(srvman
, mxman
->scsc_panic_code
);
1846 if (scsc_mx_module_reset() < 0)
1847 SCSC_TAG_INFO(MXMAN
, "failed to call scsc_mx_module_reset\n");
1848 atomic_inc(&mxman
->recovery_count
);
1852 * If recovery is disabled and an scsc_mx_service_open has been hold up,
1853 * release it, rather than wait for the recovery_completion to timeout.
1855 if (mxman_recovery_disabled())
1856 complete(&mxman
->recovery_completion
);
1858 /* Safe to allow syserr recovery thread to run */
1859 mutex_unlock(&mxman
->mxman_recovery_mutex
);
1861 #ifdef CONFIG_ANDROID
1862 wake_unlock(&mxman
->failure_recovery_wake_lock
);
1866 static void failure_wq_init(struct mxman
*mxman
)
1868 mxman
->failure_wq
= create_singlethread_workqueue("failure_wq");
1869 INIT_WORK(&mxman
->failure_work
, mxman_failure_work
);
1872 static void failure_wq_stop(struct mxman
*mxman
)
1874 cancel_work_sync(&mxman
->failure_work
);
1875 flush_workqueue(mxman
->failure_wq
);
1878 static void failure_wq_deinit(struct mxman
*mxman
)
1880 failure_wq_stop(mxman
);
1881 destroy_workqueue(mxman
->failure_wq
);
1884 static void failure_wq_start(struct mxman
*mxman
)
1886 if (disable_error_handling
)
1887 SCSC_TAG_INFO(MXMAN
, "error handling disabled\n");
1889 queue_work(mxman
->failure_wq
, &mxman
->failure_work
);
1895 static void mxman_syserr_recovery_work(struct work_struct
*work
)
1897 struct mxman
*mxman
= container_of(work
, struct mxman
, syserr_recovery_work
);
1898 struct srvman
*srvman
;
1900 #ifdef CONFIG_ANDROID
1901 wake_lock(&mxman
->syserr_recovery_wake_lock
);
1903 if (!mutex_trylock(&mxman
->mxman_recovery_mutex
)) {
1904 SCSC_TAG_WARNING(MXMAN
, "Syserr during full reset - ignored\n");
1905 #ifdef CONFIG_ANDROID
1906 wake_unlock(&mxman
->syserr_recovery_wake_lock
);
1911 mutex_lock(&mxman
->mxman_mutex
);
1913 if (mxman
->mxman_state
!= MXMAN_STATE_STARTED
&& mxman
->mxman_state
!= MXMAN_STATE_STARTING
) {
1914 SCSC_TAG_WARNING(MXMAN
, "Syserr reset ignored: mxman->mxman_state=%d\n", mxman
->mxman_state
);
1915 #ifdef CONFIG_ANDROID
1916 wake_unlock(&mxman
->syserr_recovery_wake_lock
);
1918 mutex_unlock(&mxman
->mxman_mutex
);
1922 srvman
= scsc_mx_get_srvman(mxman
->mx
);
1924 srvman_freeze_sub_system(srvman
, &mxman
->last_syserr
);
1926 #ifdef CONFIG_SCSC_WLBTD
1927 #ifdef CONFIG_SCSC_LOG_COLLECTION
1928 /* Wait for log generation if not finished */
1929 SCSC_TAG_INFO(MXMAN
, "Wait for syserr sable logging\n");
1930 scsc_wlbtd_wait_for_sable_logging();
1931 SCSC_TAG_INFO(MXMAN
, "Syserr sable logging complete\n");
1935 srvman_unfreeze_sub_system(srvman
, &mxman
->last_syserr
);
1937 #ifdef CONFIG_ANDROID
1938 wake_unlock(&mxman
->syserr_recovery_wake_lock
);
1940 mutex_unlock(&mxman
->mxman_recovery_mutex
);
1941 mutex_unlock(&mxman
->mxman_mutex
);
1944 static void syserr_recovery_wq_init(struct mxman
*mxman
)
1946 mxman
->syserr_recovery_wq
= create_singlethread_workqueue("syserr_recovery_wq");
1947 INIT_WORK(&mxman
->syserr_recovery_work
, mxman_syserr_recovery_work
);
1950 static void syserr_recovery_wq_stop(struct mxman
*mxman
)
1952 cancel_work_sync(&mxman
->syserr_recovery_work
);
1953 flush_workqueue(mxman
->syserr_recovery_wq
);
1956 static void syserr_recovery_wq_deinit(struct mxman
*mxman
)
1958 syserr_recovery_wq_stop(mxman
);
1959 destroy_workqueue(mxman
->syserr_recovery_wq
);
1962 static void syserr_recovery_wq_start(struct mxman
*mxman
)
1964 queue_work(mxman
->syserr_recovery_wq
, &mxman
->syserr_recovery_work
);
1967 static void print_mailboxes(struct mxman
*mxman
)
1969 struct scsc_mif_abs
*mif
;
1970 struct mifmboxman
*mboxman
;
1973 mif
= scsc_mx_get_mif_abs(mxman
->mx
);
1974 mboxman
= scsc_mx_get_mboxman(mxman
->mx
);
1976 SCSC_TAG_INFO(MXMAN
, "Printing mailbox values:\n");
1977 for (i
= 0; i
< MIFMBOX_NUM
; i
++)
1978 SCSC_TAG_INFO(MXMAN
, "MBOX_%d: 0x%x\n", i
, *mifmboxman_get_mbox_ptr(mboxman
, mif
, i
));
1980 #ifdef CONFIG_SCSC_WLBTD
1981 static void wlbtd_work_func(struct work_struct
*work
)
1983 /* require sleep-able workqueue to run successfully */
1984 #ifdef CONFIG_SCSC_LOG_COLLECTION
1985 /* Collect mxlogger logs */
1986 /* Extend to scsc_log_collector_collect() if required */
1988 call_wlbtd(SCSC_SCRIPT_LOGGER_DUMP
);
1992 static void wlbtd_wq_init(struct mxman
*mx
)
1994 INIT_WORK(&wlbtd_work
, wlbtd_work_func
);
1997 static void wlbtd_wq_deinit(struct mxman
*mx
)
1999 /* flush and block until work is complete */
2000 flush_work(&wlbtd_work
);
2004 * Check for matching f/w and h/w
2006 * Returns 0: f/w and h/w match
2007 * 1: f/w and h/w mismatch, try the next config
2010 static int mxman_hw_ver_check(struct mxman
*mxman
)
2012 if (mx140_file_supported_hw(mxman
->mx
, mxman
->rf_hw_ver
))
2019 * Select the f/w version to load next
2021 static int mxman_select_next_fw(struct mxman
*mxman
)
2023 return mx140_file_select_fw(mxman
->mx
, mxman
->rf_hw_ver
);
2026 /* Boot MX140 with given f/w */
2027 static int __mxman_open(struct mxman
*mxman
)
2030 struct srvman
*srvman
;
2032 mx140_basedir_file(mxman
->mx
);
2034 mutex_lock(&mxman
->mxman_mutex
);
2035 if (mxman
->scsc_panic_code
) {
2036 SCSC_TAG_INFO(MXMAN
, "Previously recorded crash panic code: scsc_panic_code=0x%x\n", mxman
->scsc_panic_code
);
2037 SCSC_TAG_INFO(MXMAN
, "Reason: '%s'\n", mxman
->failure_reason
[0] ? mxman
->failure_reason
: "<null>");
2038 print_panic_code(mxman
->scsc_panic_code
);
2040 SCSC_TAG_INFO(MXMAN
, "Auto-recovery: %s\n", mxman_recovery_disabled() ? "off" : "on");
2041 srvman
= scsc_mx_get_srvman(mxman
->mx
);
2042 if (srvman
&& srvman
->error
) {
2043 mutex_unlock(&mxman
->mxman_mutex
);
2044 SCSC_TAG_INFO(MXMAN
, "Called during error - ignore\n");
2048 /* Reset the state after a previous crash during f/w boot */
2049 if (mxman
->mxman_state
== MXMAN_STATE_STARTING
)
2050 mxman
->mxman_state
= MXMAN_STATE_STOPPED
;
2052 if (mxman
->mxman_state
== MXMAN_STATE_STARTED
) {
2053 /* if in the STARTED state there MUST already be some users */
2054 if (WARN_ON(!mxman
->users
)) {
2055 SCSC_TAG_ERR(MXMAN
, "ERROR mxman->mxman_state=%d users=%d\n", mxman
->mxman_state
, mxman
->users
);
2056 mutex_unlock(&mxman
->mxman_mutex
);
2060 SCSC_TAG_INFO(MXMAN
, "Already opened: users=%d\n", mxman
->users
);
2061 mxman_print_versions(mxman
);
2062 mutex_unlock(&mxman
->mxman_mutex
);
2064 } else if (mxman
->mxman_state
== MXMAN_STATE_STOPPED
) {
2065 r
= mxman_start(mxman
);
2067 SCSC_TAG_ERR(MXMAN
, "maxwell_manager_start() failed r=%d users=%d\n", r
, mxman
->users
);
2068 mutex_unlock(&mxman
->mxman_mutex
);
2072 mxman
->mxman_state
= MXMAN_STATE_STARTED
;
2073 mutex_unlock(&mxman
->mxman_mutex
);
2074 /* Start mxlogger */
2075 if (!disable_logger
) {
2076 static char mxlbin
[128];
2078 r
= mx140_exe_path(NULL
, mxlbin
, sizeof(mxlbin
), "mx_logger.sh");
2081 SCSC_TAG_ERR(MXMAN
, "mx_logger.sh path error\n");
2084 _mx_exec(mxlbin
, UMH_WAIT_EXEC
);
2089 WARN_ON(mxman
->mxman_state
!= MXMAN_STATE_STARTED
&& mxman
->mxman_state
!= MXMAN_STATE_STOPPED
);
2090 SCSC_TAG_ERR(MXMAN
, "Bad state: mxman->mxman_state=%d\n", mxman
->mxman_state
);
2091 mutex_unlock(&mxman
->mxman_mutex
);
2095 int mxman_open(struct mxman
*mxman
)
2100 struct scsc_mif_abs
*mif
= scsc_mx_get_mif_abs(mxman
->mx
);
2102 for (try = 0; try < 2; try++) {
2103 /* Boot WLBT. This will determine the h/w version */
2104 r
= __mxman_open(mxman
);
2108 /* On retries, restore USBPLL owner as WLBT */
2109 if (try > 0 && mif
->mif_restart
)
2110 mif
->mif_restart(mif
);
2112 /* Check the h/w and f/w versions are compatible */
2113 r
= mxman_hw_ver_check(mxman
);
2115 /* Not compatible, so try next f/w */
2116 SCSC_TAG_INFO(MXMAN
, "Incompatible h/w 0x%04x vs f/w, close and try next\n", mxman
->rf_hw_ver
);
2118 /* Temporarily return USBPLL owner to AP to keep USB alive */
2119 if (mif
->mif_cleanup
)
2120 mif
->mif_cleanup(mif
);
2125 /* Select the new f/w for this hw ver */
2126 mxman_select_next_fw(mxman
);
2128 break; /* Running or given up */
2131 #ifdef CONFIG_SCSC_FM
2132 /* If we have stored FM radio parameters, deliver them to FW now */
2133 if (r
== 0 && mxman
->fm_params_pending
) {
2134 SCSC_TAG_INFO(MXMAN
, "Send pending FM params\n");
2135 mxman_fm_set_params(&mxman
->fm_params
);
2142 static void mxman_stop(struct mxman
*mxman
)
2145 struct scsc_mif_abs
*mif
;
2147 SCSC_TAG_INFO(MXMAN
, "\n");
2149 /* If reset is failed, prevent new resets */
2151 struct timeval tval
= ns_to_timeval(reset_failed_time
);
2153 SCSC_TAG_ERR(MXMAN
, "previous reset failed at [%6lu.%06ld], ignoring\n", tval
.tv_sec
, tval
.tv_usec
);
2157 (void)snprintf(mxman
->fw_build_id
, sizeof(mxman
->fw_build_id
), "unknown");
2159 mxproc_remove_ctrl_proc_dir(&mxman
->mxproc
);
2161 /* Shutdown the hardware */
2162 mif
= scsc_mx_get_mif_abs(mxman
->mx
);
2163 r
= mif
->reset(mif
, 1);
2165 reset_failed_time
= local_clock();
2166 SCSC_TAG_INFO(MXMAN
, "HW reset failed\n");
2167 reset_failed
= true;
2169 /* Save log at point of failure */
2170 #ifdef CONFIG_SCSC_LOG_COLLECTION
2171 scsc_log_collector_schedule_collection(SCSC_LOG_HOST_COMMON
, SCSC_LOG_HOST_COMMON_REASON_STOP
);
2177 panicmon_deinit(scsc_mx_get_panicmon(mxman
->mx
));
2178 transports_release(mxman
);
2179 mxfwconfig_unload(mxman
->mx
);
2181 mxlog_release(scsc_mx_get_mxlog(mxman
->mx
));
2182 /* unregister channel handler */
2183 mxmgmt_transport_register_channel_handler(scsc_mx_get_mxmgmt_transport(mxman
->mx
), MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT
,
2185 fw_crc_wq_stop(mxman
);
2187 /* Unitialise components (they may perform some checks - e.g. all memory freed) */
2188 mxfwconfig_deinit(mxman
->mx
);
2189 mifintrbit_deinit(scsc_mx_get_intrbit(mxman
->mx
));
2190 miframman_deinit(scsc_mx_get_ramman(mxman
->mx
));
2191 miframman_deinit(scsc_mx_get_ramman2(mxman
->mx
));
2192 miframabox_deinit(scsc_mx_get_aboxram(mxman
->mx
));
2193 mifmboxman_deinit(scsc_mx_get_mboxman(mxman
->mx
));
2194 #ifdef CONFIG_SCSC_SMAPPER
2195 mifsmapper_deinit(scsc_mx_get_smapper(mxman
->mx
));
2197 #ifdef CONFIG_SCSC_QOS
2198 mifqos_deinit(scsc_mx_get_qos(mxman
->mx
));
2200 /* Release the MIF memory resources */
2201 mif
->unmap(mif
, mxman
->start_dram
);
2204 void mxman_close(struct mxman
*mxman
)
2207 struct srvman
*srvman
;
2209 mutex_lock(&mxman
->mxman_mutex
);
2210 srvman
= scsc_mx_get_srvman(mxman
->mx
);
2211 if (srvman
&& srvman
->error
) {
2212 mutex_unlock(&mxman
->mxman_mutex
);
2213 SCSC_TAG_INFO(MXMAN
, "Called during error - ignore\n");
2217 SCSC_TAG_INFO(MXMAN
, "\n");
2219 if (mxman
->mxman_state
== MXMAN_STATE_STARTED
) {
2220 if (WARN_ON(!mxman
->users
)) {
2221 SCSC_TAG_ERR(MXMAN
, "ERROR users=%d\n", mxman
->users
);
2222 mutex_unlock(&mxman
->mxman_mutex
);
2227 SCSC_TAG_INFO(MXMAN
, "Current number of users=%d\n", mxman
->users
);
2228 mutex_unlock(&mxman
->mxman_mutex
);
2231 #ifdef CONFIG_SCSC_MXLOGGER
2232 #ifdef CONFIG_SCSC_LOG_COLLECTION
2233 /* Unregister minimoredump client */
2234 scsc_log_collector_unregister_client(&mini_moredump_client
);
2237 * Deinit mxlogger on last service stop...BUT before asking for HALT
2239 mxlogger_deinit(mxman
->mx
, scsc_mx_get_mxlogger(mxman
->mx
));
2242 * Ask the subsystem to stop (MM_STOP_REQ), and wait
2243 * for response (MM_STOP_RSP).
2245 r
= send_mm_msg_stop_blocking(mxman
);
2247 SCSC_TAG_ERR(MXMAN
, "send_mm_msg_stop_blocking failed: r=%d\n", r
);
2250 mxman
->mxman_state
= MXMAN_STATE_STOPPED
;
2251 mutex_unlock(&mxman
->mxman_mutex
);
2252 } else if (mxman
->mxman_state
== MXMAN_STATE_FAILED
) {
2253 if (WARN_ON(!mxman
->users
))
2254 SCSC_TAG_ERR(MXMAN
, "ERROR users=%d\n", mxman
->users
);
2258 SCSC_TAG_INFO(MXMAN
, "Current number of users=%d\n", mxman
->users
);
2259 mutex_unlock(&mxman
->mxman_mutex
);
2262 #ifdef CONFIG_SCSC_MXLOGGER
2263 #ifdef CONFIG_SCSC_LOG_COLLECTION
2264 /* Unregister minimoredump client */
2265 scsc_log_collector_unregister_client(&mini_moredump_client
);
2268 * Deinit mxlogger on last service stop...BUT before asking for HALT
2270 mxlogger_deinit(mxman
->mx
, scsc_mx_get_mxlogger(mxman
->mx
));
2274 mxman
->mxman_state
= MXMAN_STATE_STOPPED
;
2275 mutex_unlock(&mxman
->mxman_mutex
);
2276 complete(&mxman
->recovery_completion
);
2278 WARN_ON(mxman
->mxman_state
!= MXMAN_STATE_STARTED
);
2279 SCSC_TAG_ERR(MXMAN
, "Bad state: mxman->mxman_state=%d\n", mxman
->mxman_state
);
2280 mutex_unlock(&mxman
->mxman_mutex
);
2285 void mxman_syserr(struct mxman
*mxman
, struct mx_syserr_decode
*syserr
)
2287 mxman
->syserr_recovery_in_progress
= true;
2289 mxman
->last_syserr
.subsys
= syserr
->subsys
;
2290 mxman
->last_syserr
.level
= syserr
->level
;
2291 mxman
->last_syserr
.type
= syserr
->type
;
2292 mxman
->last_syserr
.subcode
= syserr
->subcode
;
2294 syserr_recovery_wq_start(mxman
);
2297 void mxman_fail(struct mxman
*mxman
, u16 scsc_panic_code
, const char *reason
)
2299 SCSC_TAG_WARNING(MXMAN
, "WLBT FW failure\n");
2301 /* The STARTING state allows a crash during firmware boot to be handled */
2302 if (mxman
->mxman_state
== MXMAN_STATE_STARTED
|| mxman
->mxman_state
== MXMAN_STATE_STARTING
) {
2303 mxman
->mxman_next_state
= MXMAN_STATE_FAILED
;
2304 mxman
->scsc_panic_code
= scsc_panic_code
;
2305 strlcpy(mxman
->failure_reason
, reason
, sizeof(mxman
->failure_reason
));
2306 /* If recovery is disabled, don't let it be
2307 * re-enabled from now on. Device must reboot
2309 if (mxman_recovery_disabled())
2310 disable_recovery_until_reboot
= true;
2312 failure_wq_start(mxman
);
2314 SCSC_TAG_WARNING(MXMAN
, "Not in MXMAN_STATE_STARTED state, ignore (state %d)\n", mxman
->mxman_state
);
2317 /* Populate syserr info with panic equivalent or best we can */
2318 mxman
->last_syserr
.subsys
= scsc_panic_code
>> SYSERR_SUB_SYSTEM_POSN
;
2319 mxman
->last_syserr
.level
= MX_SYSERR_LEVEL_7
;
2320 mxman
->last_syserr
.type
= scsc_panic_code
;
2321 mxman
->last_syserr
.subcode
= scsc_panic_code
;
2324 void mxman_freeze(struct mxman
*mxman
)
2326 SCSC_TAG_WARNING(MXMAN
, "WLBT FW frozen\n");
2328 if (mxman
->mxman_state
== MXMAN_STATE_STARTED
) {
2329 mxman
->mxman_next_state
= MXMAN_STATE_FROZEN
;
2330 failure_wq_start(mxman
);
2332 SCSC_TAG_WARNING(MXMAN
, "Not in MXMAN_STATE_STARTED state, ignore (state %d)\n", mxman
->mxman_state
);
2336 void mxman_init(struct mxman
*mxman
, struct scsc_mx
*mx
)
2339 mxman
->suspended
= 0;
2340 #ifdef CONFIG_SCSC_FM
2341 mxman
->on_halt_ldos_on
= 0;
2342 mxman
->fm_params_pending
= 0;
2344 fw_crc_wq_init(mxman
);
2345 failure_wq_init(mxman
);
2346 syserr_recovery_wq_init(mxman
);
2347 #ifdef CONFIG_SCSC_WLBTD
2348 wlbtd_wq_init(mxman
);
2350 mutex_init(&mxman
->mxman_mutex
);
2351 mutex_init(&mxman
->mxman_recovery_mutex
);
2352 init_completion(&mxman
->recovery_completion
);
2353 #ifdef CONFIG_ANDROID
2354 wake_lock_init(&mxman
->failure_recovery_wake_lock
, WAKE_LOCK_SUSPEND
, "mxman_recovery");
2355 wake_lock_init(&mxman
->syserr_recovery_wake_lock
, WAKE_LOCK_SUSPEND
, "mxman_syserr_recovery");
2357 mxman
->syserr_recovery_in_progress
= false;
2358 mxman
->last_syserr_recovery_time
= 0;
2360 /* set the initial state */
2361 mxman
->mxman_state
= MXMAN_STATE_STOPPED
;
2362 (void)snprintf(mxman
->fw_build_id
, sizeof(mxman
->fw_build_id
), "unknown");
2363 memcpy(saved_fw_build_id
, mxman
->fw_build_id
,
2364 sizeof(saved_fw_build_id
));
2365 (void)snprintf(mxman
->fw_ttid
, sizeof(mxman
->fw_ttid
), "unknown");
2366 mxproc_create_info_proc_dir(&mxman
->mxproc
, mxman
);
2367 active_mxman
= mxman
;
2369 #if defined(ANDROID_VERSION) && ANDROID_VERSION >= 90000
2370 mxman_create_sysfs_memdump();
2375 void mxman_deinit(struct mxman
*mxman
)
2377 scsc_lerna_deinit();
2378 #if defined(ANDROID_VERSION) && ANDROID_VERSION >= 90000
2379 mxman_destroy_sysfs_memdump();
2381 active_mxman
= NULL
;
2382 mxproc_remove_info_proc_dir(&mxman
->mxproc
);
2383 fw_crc_wq_deinit(mxman
);
2384 failure_wq_deinit(mxman
);
2385 syserr_recovery_wq_deinit(mxman
);
2386 #ifdef CONFIG_SCSC_WLBTD
2387 wlbtd_wq_deinit(mxman
);
2389 #ifdef CONFIG_ANDROID
2390 wake_lock_destroy(&mxman
->failure_recovery_wake_lock
);
2391 wake_lock_destroy(&mxman
->syserr_recovery_wake_lock
);
2393 mutex_destroy(&mxman
->mxman_recovery_mutex
);
2394 mutex_destroy(&mxman
->mxman_mutex
);
2397 int mxman_force_panic(struct mxman
*mxman
)
2399 struct srvman
*srvman
;
2400 struct ma_msg_packet message
= { .ma_msg
= MM_FORCE_PANIC
};
2402 mutex_lock(&mxman
->mxman_mutex
);
2403 srvman
= scsc_mx_get_srvman(mxman
->mx
);
2404 if (srvman
&& srvman
->error
) {
2405 mutex_unlock(&mxman
->mxman_mutex
);
2406 SCSC_TAG_INFO(MXMAN
, "Called during error - ignore\n");
2410 if (mxman
->mxman_state
== MXMAN_STATE_STARTED
) {
2411 mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(mxman
->mx
), MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT
, &message
, sizeof(message
));
2412 mutex_unlock(&mxman
->mxman_mutex
);
2415 mutex_unlock(&mxman
->mxman_mutex
);
2419 int mxman_suspend(struct mxman
*mxman
)
2421 struct srvman
*srvman
;
2422 struct ma_msg_packet message
= { .ma_msg
= MM_HOST_SUSPEND
};
2425 SCSC_TAG_INFO(MXMAN
, "\n");
2427 mutex_lock(&mxman
->mxman_mutex
);
2428 srvman
= scsc_mx_get_srvman(mxman
->mx
);
2429 if (srvman
&& srvman
->error
) {
2430 mutex_unlock(&mxman
->mxman_mutex
);
2431 SCSC_TAG_INFO(MXMAN
, "Called during error - ignore\n");
2435 /* Call Service suspend callbacks */
2436 ret
= srvman_suspend_services(srvman
);
2438 mutex_unlock(&mxman
->mxman_mutex
);
2439 SCSC_TAG_INFO(MXMAN
, "Service Suspend canceled - ignore %d\n", ret
);
2443 if (mxman
->mxman_state
== MXMAN_STATE_STARTED
) {
2444 SCSC_TAG_INFO(MXMAN
, "MM_HOST_SUSPEND\n");
2445 #ifdef CONFIG_SCSC_MXLOGGER
2446 mxlogger_generate_sync_record(scsc_mx_get_mxlogger(mxman
->mx
), MXLOGGER_SYN_SUSPEND
);
2448 mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(mxman
->mx
), MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT
, &message
, sizeof(message
));
2449 mxman
->suspended
= 1;
2450 atomic_inc(&mxman
->suspend_count
);
2452 mutex_unlock(&mxman
->mxman_mutex
);
2456 #ifdef CONFIG_SCSC_FM
2457 void mxman_fm_on_halt_ldos_on(void)
2459 /* Should always be an active mxman unless module is unloaded */
2460 if (!active_mxman
) {
2461 SCSC_TAG_ERR(MXMAN
, "No active MXMAN\n");
2465 active_mxman
->on_halt_ldos_on
= 1;
2467 /* FM status to pass into FW at next FW init,
2468 * by which time driver context is lost.
2469 * This is required, because now WLBT gates
2470 * LDOs with TCXO instead of leaving them
2471 * always on, to save power in deep sleep.
2472 * FM, however, needs them always on. So
2473 * we need to know when to leave the LDOs
2474 * alone at WLBT boot.
2479 void mxman_fm_on_halt_ldos_off(void)
2481 /* Should always be an active mxman unless module is unloaded */
2482 if (!active_mxman
) {
2483 SCSC_TAG_ERR(MXMAN
, "No active MXMAN\n");
2487 /* Newer FW no longer need set shared LDOs
2488 * always-off at WLBT halt, as TCXO gating
2489 * has the same effect. But pass the "off"
2490 * request for backwards compatibility
2493 active_mxman
->on_halt_ldos_on
= 0;
2497 /* Update parameters passed to WLBT FM */
2498 int mxman_fm_set_params(struct wlbt_fm_params
*params
)
2500 /* Should always be an active mxman unless module is unloaded */
2501 if (!active_mxman
) {
2502 SCSC_TAG_ERR(MXMAN
, "No active MXMAN\n");
2506 /* Params are no longer valid (FM stopped) */
2508 active_mxman
->fm_params_pending
= 0;
2509 SCSC_TAG_INFO(MXMAN
, "FM params cleared\n");
2513 /* Once set the value needs to be remembered for each time WLBT starts */
2514 active_mxman
->fm_params
= *params
;
2515 active_mxman
->fm_params_pending
= 1;
2517 if (send_fm_params_to_active_mxman(params
)) {
2518 SCSC_TAG_INFO(MXMAN
, "FM params sent to FW\n");
2522 /* Stored for next time FW is up */
2523 SCSC_TAG_INFO(MXMAN
, "FM params stored\n");
2529 void mxman_resume(struct mxman
*mxman
)
2531 struct srvman
*srvman
;
2532 struct ma_msg_packet message
= { .ma_msg
= MM_HOST_RESUME
};
2535 SCSC_TAG_INFO(MXMAN
, "\n");
2537 mutex_lock(&mxman
->mxman_mutex
);
2538 srvman
= scsc_mx_get_srvman(mxman
->mx
);
2539 if (srvman
&& srvman
->error
) {
2540 mutex_unlock(&mxman
->mxman_mutex
);
2541 SCSC_TAG_INFO(MXMAN
, "Called during error - ignore\n");
2545 if (mxman
->mxman_state
== MXMAN_STATE_STARTED
) {
2546 SCSC_TAG_INFO(MXMAN
, "MM_HOST_RESUME\n");
2547 #ifdef CONFIG_SCSC_MXLOGGER
2548 mxlogger_generate_sync_record(scsc_mx_get_mxlogger(mxman
->mx
), MXLOGGER_SYN_RESUME
);
2550 mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(mxman
->mx
), MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT
, &message
, sizeof(message
));
2551 mxman
->suspended
= 0;
2554 /* Call Service Resume callbacks */
2555 ret
= srvman_resume_services(srvman
);
2557 SCSC_TAG_INFO(MXMAN
, "Service Resume error %d\n", ret
);
2559 mutex_unlock(&mxman
->mxman_mutex
);
2562 static void _mx_exec_cleanup(struct subprocess_info
*sp_info
)
2565 SCSC_TAG_ERR(MXMAN
, "sp_info is null\n");
2568 if (!sp_info
->argv
) {
2569 SCSC_TAG_ERR(MXMAN
, "argv is null\n");
2573 SCSC_TAG_INFO(MXMAN
, "0x%p\n", sp_info
->argv
);
2574 argv_free(sp_info
->argv
);
2577 /* prog - full path to programme
2578 * wait_exec - one of UMH_WAIT_EXEC, UMH_WAIT_PROC, UMH_KILLABLE, UMH_NO_WAIT
2580 static int _mx_exec(char *prog
, int wait_exec
)
2583 * ENV vars ANDROID_ROOT and ANDROID_DATA are needed to have
2584 * the UMH spawned process working properly (as an example finding
2587 static char const *envp
[] = { "HOME=/", "PATH=/sbin:/system/sbin:/system/bin:/system/xbin:/vendor/bin:/vendor/xbin",
2588 "ANDROID_ROOT=/system", "ANDROID_DATA=/data", NULL
};
2590 char argv_str
[STRING_BUFFER_MAX_LENGTH
];
2591 int argc
, result
, len
;
2592 struct subprocess_info
*sp_info
;
2594 len
= snprintf(argv_str
, STRING_BUFFER_MAX_LENGTH
, "%s", prog
);
2595 if (len
>= STRING_BUFFER_MAX_LENGTH
) {
2596 /* snprintf() returns a value of buffer size of greater if it had to truncate the format string. */
2598 "exec string buffer insufficient (buffer size=%d, actual string=%d)\n",
2599 STRING_BUFFER_MAX_LENGTH
, len
);
2603 /* Kernel library function argv_split() will allocate memory for argv. */
2605 argv
= argv_split(GFP_KERNEL
, argv_str
, &argc
);
2607 SCSC_TAG_ERR(MXMAN
, "failed to allocate argv for userspace helper\n");
2611 /* Check the argument count just to avoid future abuse */
2612 if (argc
> NUMBER_OF_STRING_ARGS
) {
2614 "exec string has the wrong number of arguments (has %d, should be %d)\n",
2615 argc
, NUMBER_OF_STRING_ARGS
);
2620 /* Allocate sp_info and initialise pointers to argv and envp. */
2621 sp_info
= call_usermodehelper_setup(argv
[0], argv
, (char **)envp
,
2622 GFP_KERNEL
, NULL
, _mx_exec_cleanup
,
2626 SCSC_TAG_ERR(MXMAN
, "call_usermodehelper_setup() failed\n");
2631 /* Put sp_info into work queue for processing by khelper. */
2632 SCSC_TAG_INFO(MXMAN
, "Launch %s\n", prog
);
2634 result
= call_usermodehelper_exec(sp_info
, wait_exec
);
2638 * call_usermodehelper_exec() will free sp_info and call any cleanup function
2639 * whether it succeeds or fails, so do not free argv.
2641 if (result
== -ENOENT
)
2642 SCSC_TAG_ERR(MXMAN
, "call_usermodehelper() failed with %d, Executable not found %s'\n",
2645 SCSC_TAG_ERR(MXMAN
, "call_usermodehelper_exec() failed with %d\n", result
);
2650 #if defined(CONFIG_SCSC_PRINTK) && !defined(CONFIG_SCSC_WLBTD)
2651 static int __stat(const char *file
)
2659 r
= vfs_stat(file
, &stat
);
2666 int mx140_log_dump(void)
2668 #ifdef CONFIG_SCSC_PRINTK
2670 # ifdef CONFIG_SCSC_WLBTD
2671 r
= schedule_work(&wlbtd_work
);
2675 r
= mx140_exe_path(NULL
, mxlbin
, sizeof(mxlbin
), "mx_logger_dump.sh");
2677 SCSC_TAG_ERR(MXMAN
, "mx_logger_dump.sh path error\n");
2680 * Test presence of script before invoking, to suppress
2681 * unnecessary error message if not installed.
2685 SCSC_TAG_DEBUG(MXMAN
, "%s not installed\n", mxlbin
);
2688 SCSC_TAG_INFO(MXMAN
, "Invoking mx_logger_dump.sh UHM\n");
2689 r
= _mx_exec(mxlbin
, UMH_WAIT_EXEC
);
2691 SCSC_TAG_ERR(MXMAN
, "mx_logger_dump.sh err:%d\n", r
);
2693 # endif /* CONFIG_SCSC_WLBTD */
2699 EXPORT_SYMBOL(mx140_log_dump
);
2701 bool mxman_recovery_disabled(void)
2703 #ifdef CONFIG_SCSC_WLBT_AUTORECOVERY_PERMANENT_DISABLE
2704 /* Add option to kill autorecovery, ignoring module parameter
2705 * to work around platform that enables it against our wishes
2707 SCSC_TAG_ERR(MXMAN
, "CONFIG_SCSC_WLBT_AUTORECOVERY_PERMANENT_DISABLE is set\n");
2710 /* If FW has panicked when recovery was disabled, don't allow it to
2711 * be enabled. The horse has bolted.
2713 if (disable_recovery_until_reboot
)
2716 if (disable_recovery_handling
== MEMDUMP_FILE_FOR_RECOVERY
)
2717 return disable_recovery_from_memdump_file
;
2719 return disable_recovery_handling
? true : false;
2721 EXPORT_SYMBOL(mxman_recovery_disabled
);
2724 * This returns the last known loaded FW build_id
2725 * even when the fw is NOT running at the time of the request.
2727 * It could be used anytime by Android Enhanced Logging
2728 * to query for fw version.
2730 void mxman_get_fw_version(char *version
, size_t ver_sz
)
2732 /* unavailable only if chip not probed ! */
2733 snprintf(version
, ver_sz
, "%s", saved_fw_build_id
);
2735 EXPORT_SYMBOL(mxman_get_fw_version
);
2737 void mxman_get_driver_version(char *version
, size_t ver_sz
)
2739 /* IMPORTANT - Do not change the formatting as User space tooling is parsing the string
2740 * to read SAP fapi versions. */
2741 snprintf(version
, ver_sz
, "drv_ver: %u.%u.%u.%u",
2742 SCSC_RELEASE_PRODUCT
, SCSC_RELEASE_ITERATION
, SCSC_RELEASE_CANDIDATE
, SCSC_RELEASE_POINT
);
2743 #ifdef CONFIG_SCSC_WLBTD
2744 scsc_wlbtd_get_and_print_build_type();
2747 EXPORT_SYMBOL(mxman_get_driver_version
);
2749 int mxman_register_firmware_notifier(struct notifier_block
*nb
)
2751 return blocking_notifier_chain_register(&firmware_chain
, nb
);
2753 EXPORT_SYMBOL(mxman_register_firmware_notifier
);
2755 int mxman_unregister_firmware_notifier(struct notifier_block
*nb
)
2757 return blocking_notifier_chain_unregister(&firmware_chain
, nb
);
2759 EXPORT_SYMBOL(mxman_unregister_firmware_notifier
);
2762 int mxman_lerna_send(struct mxman
*mxman
, void *message
, u32 message_size
)
2764 struct srvman
*srvman
= NULL
;
2766 /* May be called when WLBT is off, so find the context in this case */
2768 mxman
= active_mxman
;
2770 if (!active_mxman
) {
2771 SCSC_TAG_ERR(MXMAN
, "No active MXMAN\n");
2775 if (!message
|| (message_size
== 0)) {
2776 SCSC_TAG_INFO(MXMAN
, "No lerna request provided.\n");
2780 mutex_lock(&active_mxman
->mxman_mutex
);
2781 srvman
= scsc_mx_get_srvman(active_mxman
->mx
);
2782 if (srvman
&& srvman
->error
) {
2783 mutex_unlock(&active_mxman
->mxman_mutex
);
2784 SCSC_TAG_INFO(MXMAN
, "Lerna configuration called during error - ignore\n");
2788 if (active_mxman
->mxman_state
== MXMAN_STATE_STARTED
) {
2789 SCSC_TAG_INFO(MXMAN
, "MM_LERNA_CONFIG\n");
2790 mxmgmt_transport_send(scsc_mx_get_mxmgmt_transport(active_mxman
->mx
),
2791 MMTRANS_CHAN_ID_MAXWELL_MANAGEMENT
, message
,
2793 mutex_unlock(&active_mxman
->mxman_mutex
);
2797 SCSC_TAG_INFO(MXMAN
, "MXMAN is NOT STARTED...cannot send MM_LERNA_CONFIG msg.\n");
2798 mutex_unlock(&active_mxman
->mxman_mutex
);