Commit 1670d856 authored by Sebastian Reichel's avatar Sebastian Reichel
Browse files

Merge tag 'tags/restart-handler-for-v3.18' into next

Immutable branch with restart handler patches for v3.18
parents b08fec22 6cd6d94d
Loading
Loading
Loading
Loading
+5 −7
Original line number Original line Diff line number Diff line
@@ -114,18 +114,13 @@ void soft_restart(unsigned long addr)
	BUG();
	BUG();
}
}


static void null_restart(enum reboot_mode reboot_mode, const char *cmd)
{
}

/*
/*
 * Function pointers to optional machine specific functions
 * Function pointers to optional machine specific functions
 */
 */
void (*pm_power_off)(void);
void (*pm_power_off)(void);
EXPORT_SYMBOL(pm_power_off);
EXPORT_SYMBOL(pm_power_off);


void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd) = null_restart;
void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
EXPORT_SYMBOL_GPL(arm_pm_restart);


/*
/*
 * This is our default idle handler.
 * This is our default idle handler.
@@ -230,7 +225,10 @@ void machine_restart(char *cmd)
	local_irq_disable();
	local_irq_disable();
	smp_send_stop();
	smp_send_stop();


	if (arm_pm_restart)
		arm_pm_restart(reboot_mode, cmd);
		arm_pm_restart(reboot_mode, cmd);
	else
		do_kernel_restart(cmd);


	/* Give a grace period for failure to restart of 1s */
	/* Give a grace period for failure to restart of 1s */
	mdelay(1000);
	mdelay(1000);
+2 −1
Original line number Original line Diff line number Diff line
@@ -98,7 +98,6 @@ void (*pm_power_off)(void);
EXPORT_SYMBOL_GPL(pm_power_off);
EXPORT_SYMBOL_GPL(pm_power_off);


void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
EXPORT_SYMBOL_GPL(arm_pm_restart);


/*
/*
 * This is our default idle handler.
 * This is our default idle handler.
@@ -180,6 +179,8 @@ void machine_restart(char *cmd)
	/* Now call the architecture specific reboot code. */
	/* Now call the architecture specific reboot code. */
	if (arm_pm_restart)
	if (arm_pm_restart)
		arm_pm_restart(reboot_mode, cmd);
		arm_pm_restart(reboot_mode, cmd);
	else
		do_kernel_restart(cmd);


	/*
	/*
	 * Whoops - the architecture was unable to reboot.
	 * Whoops - the architecture was unable to reboot.
+2 −1
Original line number Original line Diff line number Diff line
@@ -20,7 +20,8 @@


static void restart_poweroff_do_poweroff(void)
static void restart_poweroff_do_poweroff(void)
{
{
	arm_pm_restart(REBOOT_HARD, NULL);
	reboot_mode = REBOOT_HARD;
	machine_restart(NULL);
}
}


static int restart_poweroff_probe(struct platform_device *pdev)
static int restart_poweroff_probe(struct platform_device *pdev)
+32 −10
Original line number Original line Diff line number Diff line
@@ -301,6 +301,28 @@ static struct miscdevice wdt_miscdev = {
	.fops	=	&wdt_fops,
	.fops	=	&wdt_fops,
};
};


static int wdt_restart_handle(struct notifier_block *this, unsigned long mode,
			      void *cmd)
{
	/*
	 * Cobalt devices have no way of rebooting themselves other
	 * than getting the watchdog to pull reset, so we restart the
	 * watchdog on reboot with no heartbeat.
	 */
	wdt_change(WDT_ENABLE);

	/* loop until the watchdog fires */
	while (true)
		;

	return NOTIFY_DONE;
}

static struct notifier_block wdt_restart_handler = {
	.notifier_call = wdt_restart_handle,
	.priority = 128,
};

/*
/*
 *	Notifier for system down
 *	Notifier for system down
 */
 */
@@ -311,15 +333,6 @@ static int wdt_notify_sys(struct notifier_block *this,
	if (code == SYS_DOWN || code == SYS_HALT)
	if (code == SYS_DOWN || code == SYS_HALT)
		wdt_turnoff();
		wdt_turnoff();


	if (code == SYS_RESTART) {
		/*
		 * Cobalt devices have no way of rebooting themselves other
		 * than getting the watchdog to pull reset, so we restart the
		 * watchdog on reboot with no heartbeat
		 */
		wdt_change(WDT_ENABLE);
		pr_info("Watchdog timer is now enabled with no heartbeat - should reboot in ~1 second\n");
	}
	return NOTIFY_DONE;
	return NOTIFY_DONE;
}
}


@@ -338,6 +351,7 @@ static void __exit alim7101_wdt_unload(void)
	/* Deregister */
	/* Deregister */
	misc_deregister(&wdt_miscdev);
	misc_deregister(&wdt_miscdev);
	unregister_reboot_notifier(&wdt_notifier);
	unregister_reboot_notifier(&wdt_notifier);
	unregister_restart_handler(&wdt_restart_handler);
	pci_dev_put(alim7101_pmu);
	pci_dev_put(alim7101_pmu);
}
}


@@ -390,11 +404,17 @@ static int __init alim7101_wdt_init(void)
		goto err_out;
		goto err_out;
	}
	}


	rc = register_restart_handler(&wdt_restart_handler);
	if (rc) {
		pr_err("cannot register restart handler (err=%d)\n", rc);
		goto err_out_reboot;
	}

	rc = misc_register(&wdt_miscdev);
	rc = misc_register(&wdt_miscdev);
	if (rc) {
	if (rc) {
		pr_err("cannot register miscdev on minor=%d (err=%d)\n",
		pr_err("cannot register miscdev on minor=%d (err=%d)\n",
		       wdt_miscdev.minor, rc);
		       wdt_miscdev.minor, rc);
		goto err_out_reboot;
		goto err_out_restart;
	}
	}


	if (nowayout)
	if (nowayout)
@@ -404,6 +424,8 @@ static int __init alim7101_wdt_init(void)
		timeout, nowayout);
		timeout, nowayout);
	return 0;
	return 0;


err_out_restart:
	unregister_restart_handler(&wdt_restart_handler);
err_out_reboot:
err_out_reboot:
	unregister_reboot_notifier(&wdt_notifier);
	unregister_reboot_notifier(&wdt_notifier);
err_out:
err_out:
+20 −12
Original line number Original line Diff line number Diff line
@@ -15,12 +15,12 @@
#include <linux/module.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/notifier.h>
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <linux/watchdog.h>
#include <linux/watchdog.h>
#include <linux/moduleparam.h>
#include <linux/moduleparam.h>


#include <asm/system_misc.h>

#define REG_COUNT			0x4
#define REG_COUNT			0x4
#define REG_MODE			0x8
#define REG_MODE			0x8
#define REG_ENABLE			0xC
#define REG_ENABLE			0xC
@@ -29,17 +29,22 @@ struct moxart_wdt_dev {
	struct watchdog_device dev;
	struct watchdog_device dev;
	void __iomem *base;
	void __iomem *base;
	unsigned int clock_frequency;
	unsigned int clock_frequency;
	struct notifier_block restart_handler;
};
};


static struct moxart_wdt_dev *moxart_restart_ctx;

static int heartbeat;
static int heartbeat;


static void moxart_wdt_restart(enum reboot_mode reboot_mode, const char *cmd)
static int moxart_restart_handle(struct notifier_block *this,
				 unsigned long mode, void *cmd)
{
{
	writel(1, moxart_restart_ctx->base + REG_COUNT);
	struct moxart_wdt_dev *moxart_wdt = container_of(this,
	writel(0x5ab9, moxart_restart_ctx->base + REG_MODE);
							 struct moxart_wdt_dev,
	writel(0x03, moxart_restart_ctx->base + REG_ENABLE);
							 restart_handler);
	writel(1, moxart_wdt->base + REG_COUNT);
	writel(0x5ab9, moxart_wdt->base + REG_MODE);
	writel(0x03, moxart_wdt->base + REG_ENABLE);

	return NOTIFY_DONE;
}
}


static int moxart_wdt_stop(struct watchdog_device *wdt_dev)
static int moxart_wdt_stop(struct watchdog_device *wdt_dev)
@@ -136,8 +141,12 @@ static int moxart_wdt_probe(struct platform_device *pdev)
	if (err)
	if (err)
		return err;
		return err;


	moxart_restart_ctx = moxart_wdt;
	moxart_wdt->restart_handler.notifier_call = moxart_restart_handle;
	arm_pm_restart = moxart_wdt_restart;
	moxart_wdt->restart_handler.priority = 128;
	err = register_restart_handler(&moxart_wdt->restart_handler);
	if (err)
		dev_err(dev, "cannot register restart notifier (err=%d)\n",
			err);


	dev_dbg(dev, "Watchdog enabled (heartbeat=%d sec, nowayout=%d)\n",
	dev_dbg(dev, "Watchdog enabled (heartbeat=%d sec, nowayout=%d)\n",
		moxart_wdt->dev.timeout, nowayout);
		moxart_wdt->dev.timeout, nowayout);
@@ -149,9 +158,8 @@ static int moxart_wdt_remove(struct platform_device *pdev)
{
{
	struct moxart_wdt_dev *moxart_wdt = platform_get_drvdata(pdev);
	struct moxart_wdt_dev *moxart_wdt = platform_get_drvdata(pdev);


	arm_pm_restart = NULL;
	unregister_restart_handler(&moxart_wdt->restart_handler);
	moxart_wdt_stop(&moxart_wdt->dev);
	moxart_wdt_stop(&moxart_wdt->dev);
	watchdog_unregister_device(&moxart_wdt->dev);


	return 0;
	return 0;
}
}
Loading