关于系统reboot
在使用spi flash时,执行reboot命令,有时会无法重启,这里追查下原因。
正常重启信息
# reboot
# Stopping network: OK
Saving random seed--- done.
Stopping logging: OK
umount: devtmpfs busy - remounted read-only
[ 16.812893] EXT4-fs (mmcblk0p2): re-mounted. Opts: (null)
Sent SIGTERM to all processes
Sent SIGKILL to all processes
Requesting system reboot
[ 18.830716] reboot: Restarting system
void kernel_restart(char *cmd)
{
kernel_restart_prepare(cmd);
migrate_to_reboot_cpu();
syscore_shutdown();
if (!cmd)
pr_emerg("Restarting system\n");
else
pr_emerg("Restarting system with command '%s'\n", cmd);
kmsg_dump(KMSG_DUMP_RESTART);
machine_restart(cmd);
}
arch/arm/kernel/setup.c: arm_pm_restart = mdesc->restart;
重启失败
void machine_restart(char *cmd)
{
local_irq_disable();
smp_send_stop();
if (arm_pm_restart)
arm_pm_restart(reboot_mode, cmd);
else
do_kernel_restart(cmd);
//正常来说不会走到这里
/* Give a grace period for failure to restart of 1s */
mdelay(1000);
/* Whoops - the platform was unable to reboot. Tell the user! */
printk("Reboot failed -- System halted\n");
while (1);
}
void do_kernel_restart(char *cmd)
{
atomic_notifier_call_chain(&restart_handler_list, reboot_mode, cmd);
}
register_restart_handler
int atomic_notifier_call_chain(struct atomic_notifier_head *nh,
unsigned long val, void *v)
{
return __atomic_notifier_call_chain(nh, val, v, -1, NULL);
}
spi flash问题
[ 312.719945] INFO: trying to register non-static key.
[ 312.724967] the code is fine but needs lockdep annotation.
[ 312.730448] turning off the locking correctness validator.
[ 312.735943] CPU: 0 PID: 162 Comm: sync Not tainted 4.13.0-licheepi-zero+ #55
[ 312.742981] Hardware name: Allwinner sun8i Family
[ 312.747734] [<c010e8a8>] (unwind_backtrace) from [<c010b594>] (show_stack+0x10/0x14)
[ 312.755483] [<c010b594>] (show_stack) from [<c048ec4c>] (dump_stack+0x84/0x98)
[ 312.762711] [<c048ec4c>] (dump_stack) from [<c015e698>] (register_lock_class+0x3f8/0x624)
[ 312.770886] [<c015e698>] (register_lock_class) from [<c015fb0c>] (__lock_acquire.constprop.7+0x60/0x954)
[ 312.780358] [<c015fb0c>] (__lock_acquire.constprop.7) from [<c0160468>] (lock_acquire+0x68/0x84)
[ 312.789143] [<c0160468>] (lock_acquire) from [<c0132498>] (flush_work+0x50/0x290)
[ 312.796624] [<c0132498>] (flush_work) from [<c0133f00>] (__cancel_work_timer+0xec/0x1c4)
[ 312.804722] [<c0133f00>] (__cancel_work_timer) from [<c028d1b4>] (jffs2_sync_fs+0x14/0x38)
[ 312.812995] [<c028d1b4>] (jffs2_sync_fs) from [<c0207e30>] (iterate_supers+0xc0/0x120)
[ 312.820912] [<c0207e30>] (iterate_supers) from [<c0233708>] (sys_sync+0x44/0xa4)
[ 312.828310] [<c0233708>] (sys_sync) from [<c0107620>] (ret_fast_syscall+0x0/0x3c)
static int jffs2_sync_fs(struct super_block *sb, int wait)
{
struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
cancel_delayed_work_sync(&c->wbuf_dwork);
#endif
mutex_lock(&c->alloc_sem);
jffs2_flush_wbuf_pad(c);
mutex_unlock(&c->alloc_sem);
return 0;
}
bool cancel_delayed_work_sync(struct delayed_work *dwork)
{
return __cancel_work_timer(&dwork->work, true);
}
EXPORT_SYMBOL(cancel_delayed_work_sync);
CONFIG_JFFS2_FS_WRITEBUFFER 去掉,可以不出现oops信息
原因
是使用了32Mflash,在重启的时候,没有退出4-byte地址模式导致。(因为板子上没有PMU,没有对flash进行复位)
static void spi_nor_set_4byte_opcodes(struct spi_nor *nor,
const struct flash_info *info)
{
/* Do some manufacturer fixups first */
switch (JEDEC_MFR(info)) {
case SNOR_MFR_SPANSION:
/* No small sector erase for 4-byte command set */
nor->erase_opcode = SPINOR_OP_SE;
nor->mtd.erasesize = info->sector_size;
break;
default:
break;
}
nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode);
nor->program_opcode = spi_nor_convert_3to4_program(nor->program_opcode);
nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode);
}
/* Enable/disable 4-byte addressing mode. */
static inline int set_4byte(struct spi_nor *nor, const struct flash_info *info,
int enable)
{
int status;
bool need_wren = false;
u8 cmd;
switch (JEDEC_MFR(info)) {
case SNOR_MFR_MICRON:
/* Some Micron need WREN command; all will accept it */
need_wren = true;
case SNOR_MFR_MACRONIX:
case SNOR_MFR_WINBOND:
if (need_wren)
write_enable(nor); //nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0);
cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B;
status = nor->write_reg(nor, cmd, NULL, 0);
if (need_wren)
write_disable(nor);
return status;
default:
/* Spansion style */
nor->cmd_buf[0] = enable << 7;
return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1);
}
}
struct m25p {
struct spi_device *spi;
struct spi_nor spi_nor;
u8 command[MAX_CMD_SIZE];
};
static int m25p_remove(struct spi_device *spi)
{
struct m25p *flash = spi_get_drvdata(spi);
//add to exit 4-byte address mode
/* Clean up MTD stuff. */
return mtd_device_unregister(&flash->spi_nor.mtd);
}
新增关机接口
static void m25p_shutdown(struct spi_device *spi)
{
struct m25p *flash = spi_get_drvdata(spi);
struct spi_nor nor = flash->spi_nor;
int status;
//add to exit 4-byte address mode
nor.write_reg(&nor, SPINOR_OP_WREN, NULL, 0);
status = nor.write_reg(&nor, SPINOR_OP_EX4B, NULL, 0);
printk("remove spi flash!\n");
/* Clean up MTD stuff. */
mtd_device_unregister(&flash->spi_nor.mtd);
return;
}
static struct spi_driver m25p80_driver = {
.driver = {
.name = "m25p80",
.of_match_table = m25p_of_table,
},
.id_table = m25p_ids,
.probe = m25p_probe,
.remove = m25p_remove,
.shutdown = m25p_shutdown,
/* REVISIT: many of these chips have deep power-down modes, which
* should clearly be entered on suspend() to minimize power use.
* And also when they're otherwise idle---
*/
};
CONFIG_SPI_FLASH_BAR