mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-08 12:58:12 -04:00
usb: mass_storage: Add support for SC_REBOOT
Add support for a vendor specific SCSI pass through command to trigger reboot. SC_REBOOT (0xd7) - triggers reboot into fastboot mode SC_REBOOT_1 (0xd8) - triggers reboot into normal mode. Propagated from (CR) Change-Id: I4fc4839968135a63c594dca69b1dc93699e4a9bc Reviewed-on: https://gerrit.mot.com/1750946 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Zonghua Liu <a17671@motorola.com> Reviewed-by: Yuecai Liu <liuyc20@motorola.com> Reviewed-by: Jianqi Yang <yangj@motorola.com> Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/2053807 Reviewed-by: Xiaojun Ji <jixj@motorola.com>
This commit is contained in:
parent
391d66619c
commit
bbabbcb7a0
1 changed files with 67 additions and 0 deletions
|
|
@ -209,6 +209,7 @@
|
|||
#include <linux/kthread.h>
|
||||
#include <linux/sched/signal.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
|
@ -235,6 +236,11 @@
|
|||
|
||||
static const char fsg_string_interface[] = "Mass Storage";
|
||||
|
||||
enum fsg_restart_type {
|
||||
FSG_RESTART_NONE,
|
||||
FSG_REBOOT,
|
||||
FSG_REBOOT_BL,
|
||||
};
|
||||
|
||||
/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
|
||||
static struct usb_string fsg_strings[] = {
|
||||
|
|
@ -352,6 +358,9 @@ struct fsg_common {
|
|||
void *private_data;
|
||||
|
||||
char inquiry_string[INQUIRY_STRING_LEN];
|
||||
|
||||
enum fsg_restart_type restart_type;
|
||||
struct delayed_work restart_work;
|
||||
};
|
||||
|
||||
struct fsg_dev {
|
||||
|
|
@ -1315,6 +1324,8 @@ static int check_command(struct fsg_common *common, int cmnd_size,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define SC_REBOOT 0xd7
|
||||
#define SC_REBOOT_2 0xd8
|
||||
static int do_scsi_command(struct fsg_common *common)
|
||||
{
|
||||
struct fsg_buffhd *bh;
|
||||
|
|
@ -1427,6 +1438,35 @@ static int do_scsi_command(struct fsg_common *common)
|
|||
"TEST UNIT READY");
|
||||
break;
|
||||
|
||||
case SC_REBOOT:
|
||||
common->data_size_from_cmnd = 0;
|
||||
reply = check_command(common, common->cmnd_size,
|
||||
DATA_DIR_NONE, 0, 0, "REBOOT BL");
|
||||
if (reply == 0) {
|
||||
common->curlun->sense_data = SS_INVALID_COMMAND;
|
||||
reply = -EINVAL;
|
||||
} else {
|
||||
pr_err("Triggered Reboot from SCSI Command\n");
|
||||
common->restart_type = FSG_REBOOT;
|
||||
schedule_delayed_work(&common->restart_work,
|
||||
msecs_to_jiffies(1000));
|
||||
}
|
||||
break;
|
||||
case SC_REBOOT_2:
|
||||
common->data_size_from_cmnd = 0;
|
||||
reply = check_command(common, common->cmnd_size,
|
||||
DATA_DIR_NONE, 0, 0, "REBOOT");
|
||||
if (reply == 0) {
|
||||
common->curlun->sense_data = SS_INVALID_COMMAND;
|
||||
reply = -EINVAL;
|
||||
} else {
|
||||
pr_err("Triggered Reboot BL from SCSI Command\n");
|
||||
common->restart_type = FSG_REBOOT_BL;
|
||||
schedule_delayed_work(&common->restart_work,
|
||||
msecs_to_jiffies(1000));
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
* Some mandatory commands that we recognize but don't implement.
|
||||
* They don't mean much in this setting. It's left as an exercise
|
||||
|
|
@ -1959,6 +1999,32 @@ static void fsg_lun_release(struct device *dev)
|
|||
/* Nothing needs to be done */
|
||||
}
|
||||
|
||||
static int disable_restarts;
|
||||
module_param(disable_restarts, int, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(disable_restarts, "Disable SCSI Initiated Reboots");
|
||||
static void fsg_restart_work(struct work_struct *work)
|
||||
{
|
||||
struct fsg_common *common = container_of(work,
|
||||
struct fsg_common,
|
||||
restart_work.work);
|
||||
|
||||
if (disable_restarts) {
|
||||
pr_err("SCSI Reboots Disabled\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (common->restart_type) {
|
||||
case FSG_REBOOT:
|
||||
kernel_restart("");
|
||||
break;
|
||||
case FSG_REBOOT_BL:
|
||||
kernel_restart("bootloader");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct fsg_common *fsg_common_setup(struct fsg_common *common)
|
||||
{
|
||||
if (!common) {
|
||||
|
|
@ -1974,6 +2040,7 @@ static struct fsg_common *fsg_common_setup(struct fsg_common *common)
|
|||
init_completion(&common->thread_notifier);
|
||||
init_waitqueue_head(&common->io_wait);
|
||||
init_waitqueue_head(&common->fsg_wait);
|
||||
INIT_DELAYED_WORK(&common->restart_work, fsg_restart_work);
|
||||
common->state = FSG_STATE_TERMINATED;
|
||||
memset(common->luns, 0, sizeof(common->luns));
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue