mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-05 19:31:57 -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/1785335 Reviewed-by: Huosheng Liao <liaohs@motorola.com>
This commit is contained in:
parent
28c524fc00
commit
d19025e7dd
2 changed files with 69 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>
|
||||
|
|
@ -231,6 +232,13 @@
|
|||
#define FSG_DRIVER_DESC "Mass Storage Function"
|
||||
#define FSG_DRIVER_VERSION "2009/09/11"
|
||||
|
||||
enum fsg_restart_type {
|
||||
FSG_RESTART_NONE,
|
||||
FSG_REBOOT,
|
||||
FSG_REBOOT_BL,
|
||||
};
|
||||
|
||||
|
||||
static const char fsg_string_interface[] = "Mass Storage";
|
||||
|
||||
#include "storage_common.h"
|
||||
|
|
@ -314,6 +322,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 {
|
||||
|
|
@ -2115,6 +2126,35 @@ static int do_scsi_command(struct fsg_common *common)
|
|||
reply = do_write(common);
|
||||
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
|
||||
|
|
@ -2661,6 +2701,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) {
|
||||
|
|
@ -2676,6 +2742,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));
|
||||
|
||||
|
|
|
|||
|
|
@ -169,6 +169,8 @@
|
|||
|
||||
/* Vendor specific CDBs start here */
|
||||
#define VENDOR_SPECIFIC_CDB 0xc0
|
||||
#define SC_REBOOT 0xd7
|
||||
#define SC_REBOOT_2 0xd8
|
||||
|
||||
/*
|
||||
* SCSI command lengths
|
||||
|
|
|
|||
Loading…
Reference in a new issue