25 #include <linux/errno.h>
28 #include <linux/kernel.h>
30 #include <linux/module.h>
31 #include <linux/reboot.h>
32 #include <linux/sched.h>
35 #include <linux/string.h>
36 #include <linux/types.h>
42 #define DRIVER_NAME "dcdbas"
43 #define DRIVER_VERSION "5.6.0-3.2"
44 #define DRIVER_DESCRIPTION "Dell Systems Management Base Driver"
48 static u8 *smi_data_buf;
50 static unsigned long smi_data_buf_size;
51 static u32 smi_data_buf_phys_addr;
54 static unsigned int host_control_action;
55 static unsigned int host_control_smi_type;
56 static unsigned int host_control_on_shutdown;
61 static void smi_data_buf_free(
void)
66 dev_dbg(&dcdbas_pdev->
dev,
"%s: phys: %x size: %lu\n",
67 __func__, smi_data_buf_phys_addr, smi_data_buf_size);
72 smi_data_buf_handle = 0;
73 smi_data_buf_phys_addr = 0;
74 smi_data_buf_size = 0;
80 static int smi_data_buf_realloc(
unsigned long size)
85 if (smi_data_buf_size >= size)
95 "%s: failed to allocate memory size %lu\n",
102 memcpy(buf, smi_data_buf, smi_data_buf_size);
109 smi_data_buf_handle =
handle;
111 smi_data_buf_size =
size;
113 dev_dbg(&dcdbas_pdev->
dev,
"%s: phys: %x size: %lu\n",
114 __func__, smi_data_buf_phys_addr, smi_data_buf_size);
123 return sprintf(buf,
"%x\n", smi_data_buf_phys_addr);
130 return sprintf(buf,
"%lu\n", smi_data_buf_size);
135 const char *buf,
size_t count)
144 ret = smi_data_buf_realloc(buf_size);
154 char *buf, loff_t
pos,
size_t count)
167 char *buf, loff_t
pos,
size_t count)
176 ret = smi_data_buf_realloc(pos + count);
180 memcpy(smi_data_buf + pos, buf, count);
191 return sprintf(buf,
"%u\n", host_control_action);
196 const char *buf,
size_t count)
202 ret = smi_data_buf_realloc(
sizeof(
struct apm_cmd));
211 static ssize_t host_control_smi_type_show(
struct device *dev,
215 return sprintf(buf,
"%u\n", host_control_smi_type);
218 static ssize_t host_control_smi_type_store(
struct device *dev,
220 const char *buf,
size_t count)
226 static ssize_t host_control_on_shutdown_show(
struct device *dev,
230 return sprintf(buf,
"%u\n", host_control_on_shutdown);
233 static ssize_t host_control_on_shutdown_store(
struct device *dev,
235 const char *buf,
size_t count)
252 dev_info(&dcdbas_pdev->
dev,
"%s: invalid magic value\n",
258 if (!alloc_cpumask_var(&old_mask,
GFP_KERNEL))
261 cpumask_copy(old_mask, &
current->cpus_allowed);
264 dev_dbg(&dcdbas_pdev->
dev,
"%s: failed to get CPU 0\n",
284 set_cpus_allowed_ptr(
current, old_mask);
285 free_cpumask_var(old_mask);
302 const char *buf,
size_t count)
310 if (smi_data_buf_size <
sizeof(
struct smi_cmd)) {
314 smi_cmd = (
struct smi_cmd *)smi_data_buf;
331 memset(smi_data_buf, 0, smi_data_buf_size);
350 static int host_control_smi(
void)
359 apm_cmd = (
struct apm_cmd *)smi_data_buf;
362 switch (host_control_smi_type) {
366 data = (
u8 *)&smi_data_buf_phys_addr;
382 spin_unlock_irqrestore(&rtc_lock, flags);
398 data = (
u8 *)&smi_data_buf_phys_addr;
414 spin_unlock_irqrestore(&rtc_lock, flags);
429 dev_dbg(&dcdbas_pdev->
dev,
"%s: invalid SMI type %u\n",
430 __func__, host_control_smi_type);
446 static void dcdbas_host_control(
void)
448 struct apm_cmd *apm_cmd;
454 action = host_control_action;
458 dev_dbg(&dcdbas_pdev->
dev,
"%s: no SMI buffer\n", __func__);
462 if (smi_data_buf_size <
sizeof(
struct apm_cmd)) {
463 dev_dbg(&dcdbas_pdev->
dev,
"%s: SMI buffer too small\n",
468 apm_cmd = (
struct apm_cmd *)smi_data_buf;
474 *((
s16 *)&apm_cmd->parameters.shortreq.
parm[0]) = (
s16) 0;
479 *((
s16 *)&apm_cmd->parameters.shortreq.
parm[0]) = (
s16) 20;
494 if (host_control_on_shutdown) {
497 "action to complete...\n");
498 dcdbas_host_control();
507 .notifier_call = dcdbas_reboot_notify,
526 static struct attribute *dcdbas_dev_attrs[] = {
527 &dev_attr_smi_data_buf_size.attr,
528 &dev_attr_smi_data_buf_phys_addr.attr,
529 &dev_attr_smi_request.attr,
530 &dev_attr_host_control_action.attr,
531 &dev_attr_host_control_smi_type.attr,
532 &dev_attr_host_control_on_shutdown.attr,
537 .attrs = dcdbas_dev_attrs,
552 dcdbas_pdev->
dev.dma_mask = &dcdbas_pdev->
dev.coherent_dma_mask;
558 for (i = 0; dcdbas_bin_attrs[
i]; i++) {
560 dcdbas_bin_attrs[i]);
564 dcdbas_bin_attrs[i]);
583 for (i = 0; dcdbas_bin_attrs[
i]; i++)
595 .probe = dcdbas_probe,
602 static int __init dcdbas_init(
void)
613 goto err_unregister_driver;
618 goto err_free_device;
624 err_unregister_driver:
632 static void __exit dcdbas_exit(
void)