diff --git a/drivers/misc/mods/mods.h b/drivers/misc/mods/mods.h index 46f6e7ef..0bcfda6b 100644 --- a/drivers/misc/mods/mods.h +++ b/drivers/misc/mods/mods.h @@ -24,7 +24,7 @@ /* Driver version */ #define MODS_DRIVER_VERSION_MAJOR 3 -#define MODS_DRIVER_VERSION_MINOR 78 +#define MODS_DRIVER_VERSION_MINOR 79 #define MODS_DRIVER_VERSION ((MODS_DRIVER_VERSION_MAJOR << 8) | \ ((MODS_DRIVER_VERSION_MINOR/10) << 4) | \ (MODS_DRIVER_VERSION_MINOR%10)) @@ -1207,5 +1207,9 @@ struct MODS_GET_NVLINK_LINE_RATE { #define MODS_ESC_GET_NVLINK_LINE_RATE \ _IOWR(MODS_IOC_MAGIC, 103, \ struct MODS_GET_NVLINK_LINE_RATE) +#define MODS_ESC_SUSPEND_CONSOLE \ + _IO(MODS_IOC_MAGIC, 104) +#define MODS_ESC_RESUME_CONSOLE \ + _IO(MODS_IOC_MAGIC, 105) #endif /* _MODS_H_ */ diff --git a/drivers/misc/mods/mods_internal.h b/drivers/misc/mods/mods_internal.h index 6144165f..80e64dd5 100644 --- a/drivers/misc/mods/mods_internal.h +++ b/drivers/misc/mods/mods_internal.h @@ -26,6 +26,7 @@ #include #include #include +#include #include "mods_config.h" #include "mods.h" @@ -76,6 +77,7 @@ struct mods_file_private_data { int mods_id; struct mem_type mem_type; struct mutex mtx; + int mods_fb_suspended[FB_MAX]; }; typedef struct mods_file_private_data *MODS_PRIV; diff --git a/drivers/misc/mods/mods_krnl.c b/drivers/misc/mods/mods_krnl.c index 291d251a..de058da2 100644 --- a/drivers/misc/mods/mods_krnl.c +++ b/drivers/misc/mods/mods_krnl.c @@ -27,6 +27,10 @@ #include #ifdef MODS_HAS_CONSOLE_LOCK # include +# include +# include +# include +# include #endif /*********************************************************************** @@ -279,6 +283,8 @@ static void mods_disable_all_devices(struct mods_file_private_data *priv) #endif } +static int mods_resume_console(struct file *pfile); + /********************* * MAPPING FUNCTIONS * *********************/ @@ -531,6 +537,7 @@ static int mods_krnl_open(struct inode *ip, struct file *fp) #endif struct mods_file_private_data *private_data; int id = 0; + int i = 0; LOG_ENT(); @@ -633,6 +640,9 @@ static int mods_krnl_open(struct inode *ip, struct file *fp) mutex_init(&private_data->mtx); + for (i = 0; i < FB_MAX; i++) + private_data->mods_fb_suspended[i] = 0; + init_waitqueue_head(&private_data->interrupt_event); fp->private_data = private_data; @@ -656,6 +666,8 @@ static int mods_krnl_close(struct inode *ip, struct file *fp) return -EINVAL; } + mods_resume_console(fp); + mods_free_channel(id); mods_irq_dev_clr_pri(id); @@ -950,6 +962,92 @@ int esc_mods_unlock_console(struct file *pfile) #endif } +int esc_mods_suspend_console(struct file *pfile) +{ + int ret = -EINVAL; + + LOG_ENT(); + +#if defined(CONFIG_FB) && defined(MODS_HAS_CONSOLE_LOCK) + if (num_registered_fb) { + /* tell the os to block fb accesses */ + MODS_PRIV private_data = pfile->private_data; + int i = 0; + + for (i = 0; i < num_registered_fb; i++) { + console_lock(); + if (registered_fb[i]->state != FBINFO_STATE_SUSPENDED) { + fb_set_suspend(registered_fb[i], 1); + private_data->mods_fb_suspended[i] = 1; + } + console_unlock(); + } + ret = OK; + } +#endif + +#if defined(MODS_HAS_CONSOLE_BINDING) && defined(MODS_HAS_CONSOLE_LOCK) + if (&vga_con == vc_cons[fg_console].d->vc_sw) { + /* if the current console is the vga console driver, + * have the dummy driver take over. + */ + console_lock(); + do_take_over_console(&dummy_con, 0, 0, 0); + console_unlock(); + ret = OK; + } +#endif + + LOG_EXT(); + + return ret; +} + +int esc_mods_resume_console(struct file *pfile) +{ + return mods_resume_console(pfile); +} + +static int mods_resume_console(struct file *pfile) +{ + int ret = -EINVAL; + + LOG_ENT(); + +#if defined(CONFIG_FB) && defined(MODS_HAS_CONSOLE_LOCK) + if (num_registered_fb) { + MODS_PRIV private_data = pfile->private_data; + int i = 0; + + for (i = 0; i < num_registered_fb; i++) { + console_lock(); + if (private_data->mods_fb_suspended[i]) { + fb_set_suspend(registered_fb[i], 0); + private_data->mods_fb_suspended[i] = 0; + } + console_unlock(); + } + ret = OK; + } +#endif + +#if defined(MODS_HAS_CONSOLE_BINDING) && defined(MODS_HAS_CONSOLE_LOCK) + if (&dummy_con == vc_cons[fg_console].d->vc_sw) { + /* try to unbind the dummy driver, + * the system driver should take over. + */ + console_lock(); + do_unbind_con_driver(vc_cons[fg_console].d->vc_sw, 0, 0, 0); + console_unlock(); + ret = OK; + } +#endif + + LOG_EXT(); + + return ret; +} + /************** * IO control * **************/ @@ -1562,6 +1660,14 @@ static long mods_krnl_ioctl(struct file *fp, MODS_IOCTL_VOID(MODS_ESC_UNLOCK_CONSOLE, esc_mods_unlock_console); break; + case MODS_ESC_SUSPEND_CONSOLE: + MODS_IOCTL_VOID(MODS_ESC_SUSPEND_CONSOLE, + esc_mods_suspend_console); + break; + case MODS_ESC_RESUME_CONSOLE: + MODS_IOCTL_VOID(MODS_ESC_RESUME_CONSOLE, + esc_mods_resume_console); + break; #if defined(MODS_TEGRA) case MODS_ESC_TEGRA_PROD_IS_SUPPORTED: