提交 4ee9f611 编写于 作者: L Linus Torvalds

Merge tag 'platform-drivers-x86-v3.18-1' of...

Merge tag 'platform-drivers-x86-v3.18-1' of git://git.infradead.org/users/dvhart/linux-platform-drivers-x86

Pull x86 platform driver updates from Darren Hart:
 "The following have all spent at least a few days in linux-next, most
  for more than a week.  These are mostly cleanups and error handling
  improvements with a few updates to extend existing support to newer
  hardware.

  Details:
   - dell-wmi: fix access out of memory
   - eeepc-laptop: cleanups, refactoring, sysfs perms, and improved
     error handling
   - intel-rst: ACPI and error handling cleanups
   - thinkpad-acpi: whitespace cleanup
   - toshiba_acpi: HCI/SCI interface update, keyboard backlight type 2
     support, new scancodes, cleanups"

* tag 'platform-drivers-x86-v3.18-1' of git://git.infradead.org/users/dvhart/linux-platform-drivers-x86: (23 commits)
  toshiba_acpi: Adapt kbd_bl_timeout_store to the new kbd type
  toshiba_acpi: Change HCI/SCI functions return code type
  toshiba_acpi: Unify return codes prefix from HCI/SCI to TOS
  toshiba_acpi: Rename hci_raw to tci_raw
  dell-wmi: Fix access out of memory
  eeepc-laptop: clean up control flow in *_rfkill_notifier
  eeepc-laptop: store_cpufv: return error if set_acpi fails
  eeepc-laptop: check proper return values in get_cpufv
  eeepc-laptop: make fan1_input really read-only
  eeepc-laptop: pull out SENSOR_STORE_FUNC and SENSOR_SHOW_FUNC macros
  eeepc-laptop: tell sysfs that the disp attribute is write-only
  eeepc-laptop: pull out ACPI_STORE_FUNC and ACPI_SHOW_FUNC macros
  eeepc-laptop: use DEVICE_ATTR* to instantiate device_attributes
  eeepc-laptop: change sysfs function names to API expectations
  eeepc-laptop: clean up coding style
  eeepc-laptop: simplify parse_arg()
  intel-rst: Clean up ACPI add function
  intel-rst: Use ACPI_FAILURE() macro instead !ACPI_SUCCESS() for error checking
  x86: thinkpad_acpi.c: fixed spacing coding style issue
  toshiba_acpi: Support new keyboard backlight type
  ...
......@@ -163,18 +163,24 @@ static void dell_wmi_notify(u32 value, void *context)
const struct key_entry *key;
int reported_key;
u16 *buffer_entry = (u16 *)obj->buffer.pointer;
int buffer_size = obj->buffer.length/2;
if (dell_new_hk_type && (buffer_entry[1] != 0x10)) {
if (buffer_size >= 2 && dell_new_hk_type && buffer_entry[1] != 0x10) {
pr_info("Received unknown WMI event (0x%x)\n",
buffer_entry[1]);
kfree(obj);
return;
}
if (dell_new_hk_type || buffer_entry[1] == 0x0)
if (buffer_size >= 3 && (dell_new_hk_type || buffer_entry[1] == 0x0))
reported_key = (int)buffer_entry[2];
else
else if (buffer_size >= 2)
reported_key = (int)buffer_entry[1] & 0xffff;
else {
pr_info("Received unknown WMI event\n");
kfree(obj);
return;
}
key = sparse_keymap_entry_from_scancode(dell_wmi_input_dev,
reported_key);
......
......@@ -263,13 +263,11 @@ static int acpi_setter_handle(struct eeepc_laptop *eeepc, int cm,
/*
* Sys helpers
*/
static int parse_arg(const char *buf, unsigned long count, int *val)
static int parse_arg(const char *buf, int *val)
{
if (!count)
return 0;
if (sscanf(buf, "%i", val) != 1)
return -EINVAL;
return count;
return 0;
}
static ssize_t store_sys_acpi(struct device *dev, int cm,
......@@ -278,12 +276,13 @@ static ssize_t store_sys_acpi(struct device *dev, int cm,
struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
int rv, value;
rv = parse_arg(buf, count, &value);
if (rv > 0)
value = set_acpi(eeepc, cm, value);
if (value < 0)
rv = parse_arg(buf, &value);
if (rv < 0)
return rv;
rv = set_acpi(eeepc, cm, value);
if (rv < 0)
return -EIO;
return rv;
return count;
}
static ssize_t show_sys_acpi(struct device *dev, int cm, char *buf)
......@@ -296,30 +295,34 @@ static ssize_t show_sys_acpi(struct device *dev, int cm, char *buf)
return sprintf(buf, "%d\n", value);
}
#define EEEPC_CREATE_DEVICE_ATTR(_name, _mode, _cm) \
static ssize_t show_##_name(struct device *dev, \
#define EEEPC_ACPI_SHOW_FUNC(_name, _cm) \
static ssize_t _name##_show(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
return show_sys_acpi(dev, _cm, buf); \
} \
static ssize_t store_##_name(struct device *dev, \
}
#define EEEPC_ACPI_STORE_FUNC(_name, _cm) \
static ssize_t _name##_store(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return store_sys_acpi(dev, _cm, buf, count); \
} \
static struct device_attribute dev_attr_##_name = { \
.attr = { \
.name = __stringify(_name), \
.mode = _mode }, \
.show = show_##_name, \
.store = store_##_name, \
}
EEEPC_CREATE_DEVICE_ATTR(camera, 0644, CM_ASL_CAMERA);
EEEPC_CREATE_DEVICE_ATTR(cardr, 0644, CM_ASL_CARDREADER);
EEEPC_CREATE_DEVICE_ATTR(disp, 0200, CM_ASL_DISPLAYSWITCH);
#define EEEPC_CREATE_DEVICE_ATTR_RW(_name, _cm) \
EEEPC_ACPI_SHOW_FUNC(_name, _cm) \
EEEPC_ACPI_STORE_FUNC(_name, _cm) \
static DEVICE_ATTR_RW(_name)
#define EEEPC_CREATE_DEVICE_ATTR_WO(_name, _cm) \
EEEPC_ACPI_STORE_FUNC(_name, _cm) \
static DEVICE_ATTR_WO(_name)
EEEPC_CREATE_DEVICE_ATTR_RW(camera, CM_ASL_CAMERA);
EEEPC_CREATE_DEVICE_ATTR_RW(cardr, CM_ASL_CARDREADER);
EEEPC_CREATE_DEVICE_ATTR_WO(disp, CM_ASL_DISPLAYSWITCH);
struct eeepc_cpufv {
int num;
......@@ -329,14 +332,17 @@ struct eeepc_cpufv {
static int get_cpufv(struct eeepc_laptop *eeepc, struct eeepc_cpufv *c)
{
c->cur = get_acpi(eeepc, CM_ASL_CPUFV);
if (c->cur < 0)
return -ENODEV;
c->num = (c->cur >> 8) & 0xff;
c->cur &= 0xff;
if (c->cur < 0 || c->num <= 0 || c->num > 12)
if (c->num == 0 || c->num > 12)
return -ENODEV;
return 0;
}
static ssize_t show_available_cpufv(struct device *dev,
static ssize_t available_cpufv_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
......@@ -353,7 +359,7 @@ static ssize_t show_available_cpufv(struct device *dev,
return len;
}
static ssize_t show_cpufv(struct device *dev,
static ssize_t cpufv_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
......@@ -365,7 +371,7 @@ static ssize_t show_cpufv(struct device *dev,
return sprintf(buf, "%#x\n", (c.num << 8) | c.cur);
}
static ssize_t store_cpufv(struct device *dev,
static ssize_t cpufv_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
......@@ -377,16 +383,18 @@ static ssize_t store_cpufv(struct device *dev,
return -EPERM;
if (get_cpufv(eeepc, &c))
return -ENODEV;
rv = parse_arg(buf, count, &value);
rv = parse_arg(buf, &value);
if (rv < 0)
return rv;
if (!rv || value < 0 || value >= c.num)
if (value < 0 || value >= c.num)
return -EINVAL;
set_acpi(eeepc, CM_ASL_CPUFV, value);
return rv;
rv = set_acpi(eeepc, CM_ASL_CPUFV, value);
if (rv)
return rv;
return count;
}
static ssize_t show_cpufv_disabled(struct device *dev,
static ssize_t cpufv_disabled_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
......@@ -395,14 +403,14 @@ static ssize_t show_cpufv_disabled(struct device *dev,
return sprintf(buf, "%d\n", eeepc->cpufv_disabled);
}
static ssize_t store_cpufv_disabled(struct device *dev,
static ssize_t cpufv_disabled_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
int rv, value;
rv = parse_arg(buf, count, &value);
rv = parse_arg(buf, &value);
if (rv < 0)
return rv;
......@@ -412,7 +420,7 @@ static ssize_t store_cpufv_disabled(struct device *dev,
pr_warn("cpufv enabled (not officially supported "
"on this model)\n");
eeepc->cpufv_disabled = false;
return rv;
return count;
case 1:
return -EPERM;
default:
......@@ -421,29 +429,9 @@ static ssize_t store_cpufv_disabled(struct device *dev,
}
static struct device_attribute dev_attr_cpufv = {
.attr = {
.name = "cpufv",
.mode = 0644 },
.show = show_cpufv,
.store = store_cpufv
};
static struct device_attribute dev_attr_available_cpufv = {
.attr = {
.name = "available_cpufv",
.mode = 0444 },
.show = show_available_cpufv
};
static struct device_attribute dev_attr_cpufv_disabled = {
.attr = {
.name = "cpufv_disabled",
.mode = 0644 },
.show = show_cpufv_disabled,
.store = store_cpufv_disabled
};
static DEVICE_ATTR_RW(cpufv);
static DEVICE_ATTR_RO(available_cpufv);
static DEVICE_ATTR_RW(cpufv_disabled);
static struct attribute *platform_attributes[] = {
&dev_attr_camera.attr,
......@@ -545,7 +533,7 @@ static int eeepc_led_init(struct eeepc_laptop *eeepc)
eeepc->tpd_led.name = "eeepc::touchpad";
eeepc->tpd_led.brightness_set = tpd_led_set;
if (get_acpi(eeepc, CM_ASL_TPD) >= 0) /* if method is available */
eeepc->tpd_led.brightness_get = tpd_led_get;
eeepc->tpd_led.brightness_get = tpd_led_get;
eeepc->tpd_led.max_brightness = 1;
rv = led_classdev_register(&eeepc->platform_device->dev,
......@@ -680,22 +668,21 @@ static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc,
status = acpi_get_handle(NULL, node, &handle);
if (ACPI_SUCCESS(status)) {
status = acpi_install_notify_handler(handle,
ACPI_SYSTEM_NOTIFY,
eeepc_rfkill_notify,
eeepc);
if (ACPI_FAILURE(status))
pr_warn("Failed to register notify on %s\n", node);
/*
* Refresh pci hotplug in case the rfkill state was
* changed during setup.
*/
eeepc_rfkill_hotplug(eeepc, handle);
} else
if (ACPI_FAILURE(status))
return -ENODEV;
status = acpi_install_notify_handler(handle,
ACPI_SYSTEM_NOTIFY,
eeepc_rfkill_notify,
eeepc);
if (ACPI_FAILURE(status))
pr_warn("Failed to register notify on %s\n", node);
/*
* Refresh pci hotplug in case the rfkill state was
* changed during setup.
*/
eeepc_rfkill_hotplug(eeepc, handle);
return 0;
}
......@@ -707,20 +694,21 @@ static void eeepc_unregister_rfkill_notifier(struct eeepc_laptop *eeepc,
status = acpi_get_handle(NULL, node, &handle);
if (ACPI_SUCCESS(status)) {
status = acpi_remove_notify_handler(handle,
ACPI_SYSTEM_NOTIFY,
eeepc_rfkill_notify);
if (ACPI_FAILURE(status))
pr_err("Error removing rfkill notify handler %s\n",
node);
/*
* Refresh pci hotplug in case the rfkill
* state was changed after
* eeepc_unregister_rfkill_notifier()
*/
eeepc_rfkill_hotplug(eeepc, handle);
}
if (ACPI_FAILURE(status))
return;
status = acpi_remove_notify_handler(handle,
ACPI_SYSTEM_NOTIFY,
eeepc_rfkill_notify);
if (ACPI_FAILURE(status))
pr_err("Error removing rfkill notify handler %s\n",
node);
/*
* Refresh pci hotplug in case the rfkill
* state was changed after
* eeepc_unregister_rfkill_notifier()
*/
eeepc_rfkill_hotplug(eeepc, handle);
}
static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
......@@ -1042,10 +1030,11 @@ static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
{
int rv, value;
rv = parse_arg(buf, count, &value);
if (rv > 0)
set(value);
return rv;
rv = parse_arg(buf, &value);
if (rv < 0)
return rv;
set(value);
return count;
}
static ssize_t show_sys_hwmon(int (*get)(void), char *buf)
......@@ -1053,26 +1042,36 @@ static ssize_t show_sys_hwmon(int (*get)(void), char *buf)
return sprintf(buf, "%d\n", get());
}
#define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _get, _set) \
static ssize_t show_##_name(struct device *dev, \
#define EEEPC_SENSOR_SHOW_FUNC(_name, _get) \
static ssize_t _name##_show(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
return show_sys_hwmon(_get, buf); \
} \
static ssize_t store_##_name(struct device *dev, \
}
#define EEEPC_SENSOR_STORE_FUNC(_name, _set) \
static ssize_t _name##_store(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return store_sys_hwmon(_set, buf, count); \
} \
static DEVICE_ATTR(_name, _mode, show_##_name, store_##_name)
}
#define EEEPC_CREATE_SENSOR_ATTR_RW(_name, _get, _set) \
EEEPC_SENSOR_SHOW_FUNC(_name, _get) \
EEEPC_SENSOR_STORE_FUNC(_name, _set) \
static DEVICE_ATTR_RW(_name)
EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL);
EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR,
eeepc_get_fan_pwm, eeepc_set_fan_pwm);
EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
eeepc_get_fan_ctrl, eeepc_set_fan_ctrl);
#define EEEPC_CREATE_SENSOR_ATTR_RO(_name, _get) \
EEEPC_SENSOR_SHOW_FUNC(_name, _get) \
static DEVICE_ATTR_RO(_name)
EEEPC_CREATE_SENSOR_ATTR_RO(fan1_input, eeepc_get_fan_rpm);
EEEPC_CREATE_SENSOR_ATTR_RW(pwm1, eeepc_get_fan_pwm,
eeepc_set_fan_pwm);
EEEPC_CREATE_SENSOR_ATTR_RW(pwm1_enable, eeepc_get_fan_ctrl,
eeepc_set_fan_ctrl);
static struct attribute *hwmon_attrs[] = {
&dev_attr_pwm1.attr,
......@@ -1424,8 +1423,9 @@ static int eeepc_acpi_add(struct acpi_device *device)
result = eeepc_backlight_init(eeepc);
if (result)
goto fail_backlight;
} else
} else {
pr_info("Backlight controlled by ACPI video driver\n");
}
result = eeepc_input_init(eeepc);
if (result)
......
......@@ -35,7 +35,7 @@ static ssize_t irst_show_wakeup_events(struct device *dev,
acpi = to_acpi_device(dev);
status = acpi_evaluate_integer(acpi->handle, "GFFS", NULL, &value);
if (!ACPI_SUCCESS(status))
if (ACPI_FAILURE(status))
return -EINVAL;
return sprintf(buf, "%lld\n", value);
......@@ -59,7 +59,7 @@ static ssize_t irst_store_wakeup_events(struct device *dev,
status = acpi_execute_simple_method(acpi->handle, "SFFS", value);
if (!ACPI_SUCCESS(status))
if (ACPI_FAILURE(status))
return -EINVAL;
return count;
......@@ -81,7 +81,7 @@ static ssize_t irst_show_wakeup_time(struct device *dev,
acpi = to_acpi_device(dev);
status = acpi_evaluate_integer(acpi->handle, "GFTV", NULL, &value);
if (!ACPI_SUCCESS(status))
if (ACPI_FAILURE(status))
return -EINVAL;
return sprintf(buf, "%lld\n", value);
......@@ -105,7 +105,7 @@ static ssize_t irst_store_wakeup_time(struct device *dev,
status = acpi_execute_simple_method(acpi->handle, "SFTV", value);
if (!ACPI_SUCCESS(status))
if (ACPI_FAILURE(status))
return -EINVAL;
return count;
......@@ -119,21 +119,16 @@ static struct device_attribute irst_timeout_attr = {
static int irst_add(struct acpi_device *acpi)
{
int error = 0;
int error;
error = device_create_file(&acpi->dev, &irst_timeout_attr);
if (error)
goto out;
if (unlikely(error))
return error;
error = device_create_file(&acpi->dev, &irst_wakeup_attr);
if (error)
goto out_timeout;
if (unlikely(error))
device_remove_file(&acpi->dev, &irst_timeout_attr);
return 0;
out_timeout:
device_remove_file(&acpi->dev, &irst_timeout_attr);
out:
return error;
}
......
......@@ -3440,7 +3440,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj);
hotkey_dev_attributes = NULL;
return (res < 0)? res : 1;
return (res < 0) ? res : 1;
}
/* Thinkpad X1 Carbon support 5 modes including Home mode, Web browser
......@@ -4576,7 +4576,7 @@ static int __init video_init(struct ibm_init_struct *iibm)
str_supported(video_supported != TPACPI_VIDEO_NONE),
video_supported);
return (video_supported != TPACPI_VIDEO_NONE)? 0 : 1;
return (video_supported != TPACPI_VIDEO_NONE) ? 0 : 1;
}
static void video_exit(void)
......@@ -4669,7 +4669,7 @@ static int video_outputsw_set(int status)
return -ENOSYS;
}
return (res)? 0 : -EIO;
return (res) ? 0 : -EIO;
}
static int video_autosw_get(void)
......@@ -4695,7 +4695,7 @@ static int video_autosw_get(void)
static int video_autosw_set(int enable)
{
if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", (enable)? 1 : 0))
if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", (enable) ? 1 : 0))
return -EIO;
return 0;
}
......@@ -4730,20 +4730,20 @@ static int video_outputsw_cycle(void)
return -EIO;
}
return (res)? 0 : -EIO;
return (res) ? 0 : -EIO;
}
static int video_expand_toggle(void)
{
switch (video_supported) {
case TPACPI_VIDEO_570:
return acpi_evalf(ec_handle, NULL, "_Q17", "v")?
return acpi_evalf(ec_handle, NULL, "_Q17", "v") ?
0 : -EIO;
case TPACPI_VIDEO_770:
return acpi_evalf(vid_handle, NULL, "VEXP", "v")?
return acpi_evalf(vid_handle, NULL, "VEXP", "v") ?
0 : -EIO;
case TPACPI_VIDEO_NEW:
return acpi_evalf(NULL, NULL, "\\VEXP", "v")?
return acpi_evalf(NULL, NULL, "\\VEXP", "v") ?
0 : -EIO;
default:
return -ENOSYS;
......@@ -4887,14 +4887,14 @@ static int light_set_status(int status)
if (tp_features.light) {
if (cmos_handle) {
rc = acpi_evalf(cmos_handle, NULL, NULL, "vd",
(status)?
(status) ?
TP_CMOS_THINKLIGHT_ON :
TP_CMOS_THINKLIGHT_OFF);
} else {
rc = acpi_evalf(lght_handle, NULL, NULL, "vd",
(status)? 1 : 0);
(status) ? 1 : 0);
}
return (rc)? 0 : -EIO;
return (rc) ? 0 : -EIO;
}
return -ENXIO;
......@@ -4923,7 +4923,7 @@ static void light_sysfs_set(struct led_classdev *led_cdev,
static enum led_brightness light_sysfs_get(struct led_classdev *led_cdev)
{
return (light_get_status() == 1)? LED_FULL : LED_OFF;
return (light_get_status() == 1) ? LED_FULL : LED_OFF;
}
static struct tpacpi_led_classdev tpacpi_led_thinklight = {
......@@ -5045,7 +5045,7 @@ static ssize_t cmos_command_store(struct device *dev,
return -EINVAL;
res = issue_thinkpad_cmos_command(cmos_cmd);
return (res)? res : count;
return (res) ? res : count;
}
static struct device_attribute dev_attr_cmos_command =
......@@ -5069,7 +5069,7 @@ static int __init cmos_init(struct ibm_init_struct *iibm)
if (res)
return res;
return (cmos_handle)? 0 : 1;
return (cmos_handle) ? 0 : 1;
}
static void cmos_exit(void)
......@@ -5179,9 +5179,9 @@ static int led_get_status(const unsigned int led)
if (!acpi_evalf(ec_handle,
&status, "GLED", "dd", 1 << led))
return -EIO;
led_s = (status == 0)?
led_s = (status == 0) ?
TPACPI_LED_OFF :
((status == 1)?
((status == 1) ?
TPACPI_LED_ON :
TPACPI_LED_BLINK);
tpacpi_led_state_cache[led] = led_s;
......@@ -5578,7 +5578,7 @@ static int __init beep_init(struct ibm_init_struct *iibm)
tp_features.beep_needs_two_args = !!(quirks & TPACPI_BEEP_Q1);
return (beep_handle)? 0 : 1;
return (beep_handle) ? 0 : 1;
}
static int beep_read(struct seq_file *m)
......@@ -6527,7 +6527,7 @@ static int brightness_write(char *buf)
if (!rc && ibm_backlight_device)
backlight_force_update(ibm_backlight_device,
BACKLIGHT_UPDATE_SYSFS);
return (rc == -EINTR)? -ERESTARTSYS : rc;
return (rc == -EINTR) ? -ERESTARTSYS : rc;
}
static struct ibm_struct brightness_driver_data = {
......@@ -7984,7 +7984,7 @@ static ssize_t fan_pwm1_store(struct device *dev,
}
mutex_unlock(&fan_mutex);
return (rc)? rc : count;
return (rc) ? rc : count;
}
static struct device_attribute dev_attr_fan_pwm1 =
......@@ -8662,7 +8662,7 @@ static const char * __init str_supported(int is_supported)
{
static char text_unsupported[] __initdata = "not supported";
return (is_supported)? &text_unsupported[4] : &text_unsupported[0];
return (is_supported) ? &text_unsupported[4] : &text_unsupported[0];
}
#endif /* CONFIG_THINKPAD_ACPI_DEBUG */
......@@ -8783,7 +8783,7 @@ static int __init ibm_init(struct ibm_init_struct *iibm)
ibm->name, ret);
ibm_exit(ibm);
return (ret < 0)? ret : 0;
return (ret < 0) ? ret : 0;
}
/* Probing */
......@@ -8794,7 +8794,7 @@ static bool __pure __init tpacpi_is_fw_digit(const char c)
}
/* Most models: xxyTkkWW (#.##c); Ancient 570/600 and -SL lacks (#.##c) */
static bool __pure __init tpacpi_is_valid_fw_id(const char* const s,
static bool __pure __init tpacpi_is_valid_fw_id(const char * const s,
const char t)
{
return s && strlen(s) >= 8 &&
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册