aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-11-01 11:42:21 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-11-01 11:42:21 -0400
commiteb7046e9bf466cebfcfbcdf640e41d9e3a80086c (patch)
tree7d998f56e306de4c1a78355f219e38b75cfe3866 /drivers/firmware
parent5b7449810ae6d652629c550d3974c8453836d229 (diff)
parent3b692c55e58d06ba9b17c66784cab5a95ba5be9b (diff)
Merge tag 'platform-drivers-x86-v4.20-1' of git://git.infradead.org/linux-platform-drivers-x86
Pull x86 platform driver updates from Darren Hart: - Move the Dell dcdbas and dell_rbu drivers into platform/drivers/x86 as they are closely coupled with other drivers in this location. - Improve _init* usage for acerhdf and fix some usage issues with messages and module parameters. - Simplify asus-wmi by calling ACPI/WMI methods directly, eliminating workqueue overhead, eliminate double reporting of keyboard backlight. - Fix wake from USB failure on Bay Trail devices (intel_int0002_vgpio). - Notify intel_telemetry users when IPC1 device is not enabled. - Update various drivers with new laptop model IDs. - Update several intel drivers to use SPDX identifers and order headers alphabetically. * tag 'platform-drivers-x86-v4.20-1' of git://git.infradead.org/linux-platform-drivers-x86: (64 commits) HID: asus: only support backlight when it's not driven by WMI platform/x86: asus-wmi: export function for evaluating WMI methods platform/x86: asus-wmi: Only notify kbd LED hw_change by fn-key pressed platform/x86: wmi: declare device_type structure as constant platform/x86: ideapad: Add Y530-15ICH to no_hw_rfkill platform/x86: Add Intel AtomISP2 dummy / power-management driver platform/x86: touchscreen_dmi: Add min-x and min-y settings for various models platform/x86: touchscreen_dmi: Add info for the Onda V80 Plus v3 tablet platform/x86: touchscreen_dmi: Add info for the Trekstor Primetab T13B tablet platform/x86: intel_telemetry: Get rid of custom macro platform/x86: intel_telemetry: report debugfs failure MAINTAINERS: intel_telemetry: Update maintainers info platform/x86: Add LG Gram laptop special features driver platform/x86: asus-wmi: Simplify the keyboard brightness updating process platform/x86: touchscreen_dmi: Add info for the Trekstor Primebook C11 convertible platform/x86: mlx-platform: Properly use mlxplat_mlxcpld_msn201x_items MAINTAINERS: intel_pmc_core: Update MAINTAINERS firmware: dcdbas: include linux/io.h platform/x86: intel-wmi-thunderbolt: Add dynamic debugging platform/x86: intel-wmi-thunderbolt: Convert to use SPDX identifier ...
Diffstat (limited to 'drivers/firmware')
-rw-r--r--drivers/firmware/Kconfig28
-rw-r--r--drivers/firmware/Makefile2
-rw-r--r--drivers/firmware/dcdbas.c650
-rw-r--r--drivers/firmware/dcdbas.h107
-rw-r--r--drivers/firmware/dell_rbu.c745
5 files changed, 0 insertions, 1532 deletions
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 7670e8dda829..7273e5082b41 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -145,34 +145,6 @@ config EFI_PCDP
145 See DIG64_HCDPv20_042804.pdf available from 145 See DIG64_HCDPv20_042804.pdf available from
146 <http://www.dig64.org/specifications/> 146 <http://www.dig64.org/specifications/>
147 147
148config DELL_RBU
149 tristate "BIOS update support for DELL systems via sysfs"
150 depends on X86
151 select FW_LOADER
152 select FW_LOADER_USER_HELPER
153 help
154 Say m if you want to have the option of updating the BIOS for your
155 DELL system. Note you need a Dell OpenManage or Dell Update package (DUP)
156 supporting application to communicate with the BIOS regarding the new
157 image for the image update to take effect.
158 See <file:Documentation/dell_rbu.txt> for more details on the driver.
159
160config DCDBAS
161 tristate "Dell Systems Management Base Driver"
162 depends on X86
163 help
164 The Dell Systems Management Base Driver provides a sysfs interface
165 for systems management software to perform System Management
166 Interrupts (SMIs) and Host Control Actions (system power cycle or
167 power off after OS shutdown) on certain Dell systems.
168
169 See <file:Documentation/dcdbas.txt> for more details on the driver
170 and the Dell systems on which Dell systems management software makes
171 use of this driver.
172
173 Say Y or M here to enable the driver for use by Dell systems
174 management software such as Dell OpenManage.
175
176config DMIID 148config DMIID
177 bool "Export DMI identification via sysfs to userspace" 149 bool "Export DMI identification via sysfs to userspace"
178 depends on DMI 150 depends on DMI
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 13660a951437..3158dffd9914 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -11,8 +11,6 @@ obj-$(CONFIG_DMI) += dmi_scan.o
11obj-$(CONFIG_DMI_SYSFS) += dmi-sysfs.o 11obj-$(CONFIG_DMI_SYSFS) += dmi-sysfs.o
12obj-$(CONFIG_EDD) += edd.o 12obj-$(CONFIG_EDD) += edd.o
13obj-$(CONFIG_EFI_PCDP) += pcdp.o 13obj-$(CONFIG_EFI_PCDP) += pcdp.o
14obj-$(CONFIG_DELL_RBU) += dell_rbu.o
15obj-$(CONFIG_DCDBAS) += dcdbas.o
16obj-$(CONFIG_DMIID) += dmi-id.o 14obj-$(CONFIG_DMIID) += dmi-id.o
17obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o 15obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o
18obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o 16obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
deleted file mode 100644
index 0bdea60c65dd..000000000000
--- a/drivers/firmware/dcdbas.c
+++ /dev/null
@@ -1,650 +0,0 @@
1/*
2 * dcdbas.c: Dell Systems Management Base Driver
3 *
4 * The Dell Systems Management Base Driver provides a sysfs interface for
5 * systems management software to perform System Management Interrupts (SMIs)
6 * and Host Control Actions (power cycle or power off after OS shutdown) on
7 * Dell systems.
8 *
9 * See Documentation/dcdbas.txt for more information.
10 *
11 * Copyright (C) 1995-2006 Dell Inc.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License v2.0 as published by
15 * the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 */
22
23#include <linux/platform_device.h>
24#include <linux/dma-mapping.h>
25#include <linux/errno.h>
26#include <linux/cpu.h>
27#include <linux/gfp.h>
28#include <linux/init.h>
29#include <linux/kernel.h>
30#include <linux/mc146818rtc.h>
31#include <linux/module.h>
32#include <linux/reboot.h>
33#include <linux/sched.h>
34#include <linux/smp.h>
35#include <linux/spinlock.h>
36#include <linux/string.h>
37#include <linux/types.h>
38#include <linux/mutex.h>
39#include <asm/io.h>
40
41#include "dcdbas.h"
42
43#define DRIVER_NAME "dcdbas"
44#define DRIVER_VERSION "5.6.0-3.2"
45#define DRIVER_DESCRIPTION "Dell Systems Management Base Driver"
46
47static struct platform_device *dcdbas_pdev;
48
49static u8 *smi_data_buf;
50static dma_addr_t smi_data_buf_handle;
51static unsigned long smi_data_buf_size;
52static u32 smi_data_buf_phys_addr;
53static DEFINE_MUTEX(smi_data_lock);
54
55static unsigned int host_control_action;
56static unsigned int host_control_smi_type;
57static unsigned int host_control_on_shutdown;
58
59/**
60 * smi_data_buf_free: free SMI data buffer
61 */
62static void smi_data_buf_free(void)
63{
64 if (!smi_data_buf)
65 return;
66
67 dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
68 __func__, smi_data_buf_phys_addr, smi_data_buf_size);
69
70 dma_free_coherent(&dcdbas_pdev->dev, smi_data_buf_size, smi_data_buf,
71 smi_data_buf_handle);
72 smi_data_buf = NULL;
73 smi_data_buf_handle = 0;
74 smi_data_buf_phys_addr = 0;
75 smi_data_buf_size = 0;
76}
77
78/**
79 * smi_data_buf_realloc: grow SMI data buffer if needed
80 */
81static int smi_data_buf_realloc(unsigned long size)
82{
83 void *buf;
84 dma_addr_t handle;
85
86 if (smi_data_buf_size >= size)
87 return 0;
88
89 if (size > MAX_SMI_DATA_BUF_SIZE)
90 return -EINVAL;
91
92 /* new buffer is needed */
93 buf = dma_alloc_coherent(&dcdbas_pdev->dev, size, &handle, GFP_KERNEL);
94 if (!buf) {
95 dev_dbg(&dcdbas_pdev->dev,
96 "%s: failed to allocate memory size %lu\n",
97 __func__, size);
98 return -ENOMEM;
99 }
100 /* memory zeroed by dma_alloc_coherent */
101
102 if (smi_data_buf)
103 memcpy(buf, smi_data_buf, smi_data_buf_size);
104
105 /* free any existing buffer */
106 smi_data_buf_free();
107
108 /* set up new buffer for use */
109 smi_data_buf = buf;
110 smi_data_buf_handle = handle;
111 smi_data_buf_phys_addr = (u32) virt_to_phys(buf);
112 smi_data_buf_size = size;
113
114 dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
115 __func__, smi_data_buf_phys_addr, smi_data_buf_size);
116
117 return 0;
118}
119
120static ssize_t smi_data_buf_phys_addr_show(struct device *dev,
121 struct device_attribute *attr,
122 char *buf)
123{
124 return sprintf(buf, "%x\n", smi_data_buf_phys_addr);
125}
126
127static ssize_t smi_data_buf_size_show(struct device *dev,
128 struct device_attribute *attr,
129 char *buf)
130{
131 return sprintf(buf, "%lu\n", smi_data_buf_size);
132}
133
134static ssize_t smi_data_buf_size_store(struct device *dev,
135 struct device_attribute *attr,
136 const char *buf, size_t count)
137{
138 unsigned long buf_size;
139 ssize_t ret;
140
141 buf_size = simple_strtoul(buf, NULL, 10);
142
143 /* make sure SMI data buffer is at least buf_size */
144 mutex_lock(&smi_data_lock);
145 ret = smi_data_buf_realloc(buf_size);
146 mutex_unlock(&smi_data_lock);
147 if (ret)
148 return ret;
149
150 return count;
151}
152
153static ssize_t smi_data_read(struct file *filp, struct kobject *kobj,
154 struct bin_attribute *bin_attr,
155 char *buf, loff_t pos, size_t count)
156{
157 ssize_t ret;
158
159 mutex_lock(&smi_data_lock);
160 ret = memory_read_from_buffer(buf, count, &pos, smi_data_buf,
161 smi_data_buf_size);
162 mutex_unlock(&smi_data_lock);
163 return ret;
164}
165
166static ssize_t smi_data_write(struct file *filp, struct kobject *kobj,
167 struct bin_attribute *bin_attr,
168 char *buf, loff_t pos, size_t count)
169{
170 ssize_t ret;
171
172 if ((pos + count) > MAX_SMI_DATA_BUF_SIZE)
173 return -EINVAL;
174
175 mutex_lock(&smi_data_lock);
176
177 ret = smi_data_buf_realloc(pos + count);
178 if (ret)
179 goto out;
180
181 memcpy(smi_data_buf + pos, buf, count);
182 ret = count;
183out:
184 mutex_unlock(&smi_data_lock);
185 return ret;
186}
187
188static ssize_t host_control_action_show(struct device *dev,
189 struct device_attribute *attr,
190 char *buf)
191{
192 return sprintf(buf, "%u\n", host_control_action);
193}
194
195static ssize_t host_control_action_store(struct device *dev,
196 struct device_attribute *attr,
197 const char *buf, size_t count)
198{
199 ssize_t ret;
200
201 /* make sure buffer is available for host control command */
202 mutex_lock(&smi_data_lock);
203 ret = smi_data_buf_realloc(sizeof(struct apm_cmd));
204 mutex_unlock(&smi_data_lock);
205 if (ret)
206 return ret;
207
208 host_control_action = simple_strtoul(buf, NULL, 10);
209 return count;
210}
211
212static ssize_t host_control_smi_type_show(struct device *dev,
213 struct device_attribute *attr,
214 char *buf)
215{
216 return sprintf(buf, "%u\n", host_control_smi_type);
217}
218
219static ssize_t host_control_smi_type_store(struct device *dev,
220 struct device_attribute *attr,
221 const char *buf, size_t count)
222{
223 host_control_smi_type = simple_strtoul(buf, NULL, 10);
224 return count;
225}
226
227static ssize_t host_control_on_shutdown_show(struct device *dev,
228 struct device_attribute *attr,
229 char *buf)
230{
231 return sprintf(buf, "%u\n", host_control_on_shutdown);
232}
233
234static ssize_t host_control_on_shutdown_store(struct device *dev,
235 struct device_attribute *attr,
236 const char *buf, size_t count)
237{
238 host_control_on_shutdown = simple_strtoul(buf, NULL, 10);
239 return count;
240}
241
242static int raise_smi(void *par)
243{
244 struct smi_cmd *smi_cmd = par;
245
246 if (smp_processor_id() != 0) {
247 dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n",
248 __func__);
249 return -EBUSY;
250 }
251
252 /* generate SMI */
253 /* inb to force posted write through and make SMI happen now */
254 asm volatile (
255 "outb %b0,%w1\n"
256 "inb %w1"
257 : /* no output args */
258 : "a" (smi_cmd->command_code),
259 "d" (smi_cmd->command_address),
260 "b" (smi_cmd->ebx),
261 "c" (smi_cmd->ecx)
262 : "memory"
263 );
264
265 return 0;
266}
267/**
268 * dcdbas_smi_request: generate SMI request
269 *
270 * Called with smi_data_lock.
271 */
272int dcdbas_smi_request(struct smi_cmd *smi_cmd)
273{
274 int ret;
275
276 if (smi_cmd->magic != SMI_CMD_MAGIC) {
277 dev_info(&dcdbas_pdev->dev, "%s: invalid magic value\n",
278 __func__);
279 return -EBADR;
280 }
281
282 /* SMI requires CPU 0 */
283 get_online_cpus();
284 ret = smp_call_on_cpu(0, raise_smi, smi_cmd, true);
285 put_online_cpus();
286
287 return ret;
288}
289
290/**
291 * smi_request_store:
292 *
293 * The valid values are:
294 * 0: zero SMI data buffer
295 * 1: generate calling interface SMI
296 * 2: generate raw SMI
297 *
298 * User application writes smi_cmd to smi_data before telling driver
299 * to generate SMI.
300 */
301static ssize_t smi_request_store(struct device *dev,
302 struct device_attribute *attr,
303 const char *buf, size_t count)
304{
305 struct smi_cmd *smi_cmd;
306 unsigned long val = simple_strtoul(buf, NULL, 10);
307 ssize_t ret;
308
309 mutex_lock(&smi_data_lock);
310
311 if (smi_data_buf_size < sizeof(struct smi_cmd)) {
312 ret = -ENODEV;
313 goto out;
314 }
315 smi_cmd = (struct smi_cmd *)smi_data_buf;
316
317 switch (val) {
318 case 2:
319 /* Raw SMI */
320 ret = dcdbas_smi_request(smi_cmd);
321 if (!ret)
322 ret = count;
323 break;
324 case 1:
325 /* Calling Interface SMI */
326 smi_cmd->ebx = (u32) virt_to_phys(smi_cmd->command_buffer);
327 ret = dcdbas_smi_request(smi_cmd);
328 if (!ret)
329 ret = count;
330 break;
331 case 0:
332 memset(smi_data_buf, 0, smi_data_buf_size);
333 ret = count;
334 break;
335 default:
336 ret = -EINVAL;
337 break;
338 }
339
340out:
341 mutex_unlock(&smi_data_lock);
342 return ret;
343}
344EXPORT_SYMBOL(dcdbas_smi_request);
345
346/**
347 * host_control_smi: generate host control SMI
348 *
349 * Caller must set up the host control command in smi_data_buf.
350 */
351static int host_control_smi(void)
352{
353 struct apm_cmd *apm_cmd;
354 u8 *data;
355 unsigned long flags;
356 u32 num_ticks;
357 s8 cmd_status;
358 u8 index;
359
360 apm_cmd = (struct apm_cmd *)smi_data_buf;
361 apm_cmd->status = ESM_STATUS_CMD_UNSUCCESSFUL;
362
363 switch (host_control_smi_type) {
364 case HC_SMITYPE_TYPE1:
365 spin_lock_irqsave(&rtc_lock, flags);
366 /* write SMI data buffer physical address */
367 data = (u8 *)&smi_data_buf_phys_addr;
368 for (index = PE1300_CMOS_CMD_STRUCT_PTR;
369 index < (PE1300_CMOS_CMD_STRUCT_PTR + 4);
370 index++, data++) {
371 outb(index,
372 (CMOS_BASE_PORT + CMOS_PAGE2_INDEX_PORT_PIIX4));
373 outb(*data,
374 (CMOS_BASE_PORT + CMOS_PAGE2_DATA_PORT_PIIX4));
375 }
376
377 /* first set status to -1 as called by spec */
378 cmd_status = ESM_STATUS_CMD_UNSUCCESSFUL;
379 outb((u8) cmd_status, PCAT_APM_STATUS_PORT);
380
381 /* generate SMM call */
382 outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT);
383 spin_unlock_irqrestore(&rtc_lock, flags);
384
385 /* wait a few to see if it executed */
386 num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING;
387 while ((cmd_status = inb(PCAT_APM_STATUS_PORT))
388 == ESM_STATUS_CMD_UNSUCCESSFUL) {
389 num_ticks--;
390 if (num_ticks == EXPIRED_TIMER)
391 return -ETIME;
392 }
393 break;
394
395 case HC_SMITYPE_TYPE2:
396 case HC_SMITYPE_TYPE3:
397 spin_lock_irqsave(&rtc_lock, flags);
398 /* write SMI data buffer physical address */
399 data = (u8 *)&smi_data_buf_phys_addr;
400 for (index = PE1400_CMOS_CMD_STRUCT_PTR;
401 index < (PE1400_CMOS_CMD_STRUCT_PTR + 4);
402 index++, data++) {
403 outb(index, (CMOS_BASE_PORT + CMOS_PAGE1_INDEX_PORT));
404 outb(*data, (CMOS_BASE_PORT + CMOS_PAGE1_DATA_PORT));
405 }
406
407 /* generate SMM call */
408 if (host_control_smi_type == HC_SMITYPE_TYPE3)
409 outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT);
410 else
411 outb(ESM_APM_CMD, PE1400_APM_CONTROL_PORT);
412
413 /* restore RTC index pointer since it was written to above */
414 CMOS_READ(RTC_REG_C);
415 spin_unlock_irqrestore(&rtc_lock, flags);
416
417 /* read control port back to serialize write */
418 cmd_status = inb(PE1400_APM_CONTROL_PORT);
419
420 /* wait a few to see if it executed */
421 num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING;
422 while (apm_cmd->status == ESM_STATUS_CMD_UNSUCCESSFUL) {
423 num_ticks--;
424 if (num_ticks == EXPIRED_TIMER)
425 return -ETIME;
426 }
427 break;
428
429 default:
430 dev_dbg(&dcdbas_pdev->dev, "%s: invalid SMI type %u\n",
431 __func__, host_control_smi_type);
432 return -ENOSYS;
433 }
434
435 return 0;
436}
437
438/**
439 * dcdbas_host_control: initiate host control
440 *
441 * This function is called by the driver after the system has
442 * finished shutting down if the user application specified a
443 * host control action to perform on shutdown. It is safe to
444 * use smi_data_buf at this point because the system has finished
445 * shutting down and no userspace apps are running.
446 */
447static void dcdbas_host_control(void)
448{
449 struct apm_cmd *apm_cmd;
450 u8 action;
451
452 if (host_control_action == HC_ACTION_NONE)
453 return;
454
455 action = host_control_action;
456 host_control_action = HC_ACTION_NONE;
457
458 if (!smi_data_buf) {
459 dev_dbg(&dcdbas_pdev->dev, "%s: no SMI buffer\n", __func__);
460 return;
461 }
462
463 if (smi_data_buf_size < sizeof(struct apm_cmd)) {
464 dev_dbg(&dcdbas_pdev->dev, "%s: SMI buffer too small\n",
465 __func__);
466 return;
467 }
468
469 apm_cmd = (struct apm_cmd *)smi_data_buf;
470
471 /* power off takes precedence */
472 if (action & HC_ACTION_HOST_CONTROL_POWEROFF) {
473 apm_cmd->command = ESM_APM_POWER_CYCLE;
474 apm_cmd->reserved = 0;
475 *((s16 *)&apm_cmd->parameters.shortreq.parm[0]) = (s16) 0;
476 host_control_smi();
477 } else if (action & HC_ACTION_HOST_CONTROL_POWERCYCLE) {
478 apm_cmd->command = ESM_APM_POWER_CYCLE;
479 apm_cmd->reserved = 0;
480 *((s16 *)&apm_cmd->parameters.shortreq.parm[0]) = (s16) 20;
481 host_control_smi();
482 }
483}
484
485/**
486 * dcdbas_reboot_notify: handle reboot notification for host control
487 */
488static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code,
489 void *unused)
490{
491 switch (code) {
492 case SYS_DOWN:
493 case SYS_HALT:
494 case SYS_POWER_OFF:
495 if (host_control_on_shutdown) {
496 /* firmware is going to perform host control action */
497 printk(KERN_WARNING "Please wait for shutdown "
498 "action to complete...\n");
499 dcdbas_host_control();
500 }
501 break;
502 }
503
504 return NOTIFY_DONE;
505}
506
507static struct notifier_block dcdbas_reboot_nb = {
508 .notifier_call = dcdbas_reboot_notify,
509 .next = NULL,
510 .priority = INT_MIN
511};
512
513static DCDBAS_BIN_ATTR_RW(smi_data);
514
515static struct bin_attribute *dcdbas_bin_attrs[] = {
516 &bin_attr_smi_data,
517 NULL
518};
519
520static DCDBAS_DEV_ATTR_RW(smi_data_buf_size);
521static DCDBAS_DEV_ATTR_RO(smi_data_buf_phys_addr);
522static DCDBAS_DEV_ATTR_WO(smi_request);
523static DCDBAS_DEV_ATTR_RW(host_control_action);
524static DCDBAS_DEV_ATTR_RW(host_control_smi_type);
525static DCDBAS_DEV_ATTR_RW(host_control_on_shutdown);
526
527static struct attribute *dcdbas_dev_attrs[] = {
528 &dev_attr_smi_data_buf_size.attr,
529 &dev_attr_smi_data_buf_phys_addr.attr,
530 &dev_attr_smi_request.attr,
531 &dev_attr_host_control_action.attr,
532 &dev_attr_host_control_smi_type.attr,
533 &dev_attr_host_control_on_shutdown.attr,
534 NULL
535};
536
537static const struct attribute_group dcdbas_attr_group = {
538 .attrs = dcdbas_dev_attrs,
539 .bin_attrs = dcdbas_bin_attrs,
540};
541
542static int dcdbas_probe(struct platform_device *dev)
543{
544 int error;
545
546 host_control_action = HC_ACTION_NONE;
547 host_control_smi_type = HC_SMITYPE_NONE;
548
549 dcdbas_pdev = dev;
550
551 /*
552 * BIOS SMI calls require buffer addresses be in 32-bit address space.
553 * This is done by setting the DMA mask below.
554 */
555 error = dma_set_coherent_mask(&dcdbas_pdev->dev, DMA_BIT_MASK(32));
556 if (error)
557 return error;
558
559 error = sysfs_create_group(&dev->dev.kobj, &dcdbas_attr_group);
560 if (error)
561 return error;
562
563 register_reboot_notifier(&dcdbas_reboot_nb);
564
565 dev_info(&dev->dev, "%s (version %s)\n",
566 DRIVER_DESCRIPTION, DRIVER_VERSION);
567
568 return 0;
569}
570
571static int dcdbas_remove(struct platform_device *dev)
572{
573 unregister_reboot_notifier(&dcdbas_reboot_nb);
574 sysfs_remove_group(&dev->dev.kobj, &dcdbas_attr_group);
575
576 return 0;
577}
578
579static struct platform_driver dcdbas_driver = {
580 .driver = {
581 .name = DRIVER_NAME,
582 },
583 .probe = dcdbas_probe,
584 .remove = dcdbas_remove,
585};
586
587static const struct platform_device_info dcdbas_dev_info __initconst = {
588 .name = DRIVER_NAME,
589 .id = -1,
590 .dma_mask = DMA_BIT_MASK(32),
591};
592
593static struct platform_device *dcdbas_pdev_reg;
594
595/**
596 * dcdbas_init: initialize driver
597 */
598static int __init dcdbas_init(void)
599{
600 int error;
601
602 error = platform_driver_register(&dcdbas_driver);
603 if (error)
604 return error;
605
606 dcdbas_pdev_reg = platform_device_register_full(&dcdbas_dev_info);
607 if (IS_ERR(dcdbas_pdev_reg)) {
608 error = PTR_ERR(dcdbas_pdev_reg);
609 goto err_unregister_driver;
610 }
611
612 return 0;
613
614 err_unregister_driver:
615 platform_driver_unregister(&dcdbas_driver);
616 return error;
617}
618
619/**
620 * dcdbas_exit: perform driver cleanup
621 */
622static void __exit dcdbas_exit(void)
623{
624 /*
625 * make sure functions that use dcdbas_pdev are called
626 * before platform_device_unregister
627 */
628 unregister_reboot_notifier(&dcdbas_reboot_nb);
629
630 /*
631 * We have to free the buffer here instead of dcdbas_remove
632 * because only in module exit function we can be sure that
633 * all sysfs attributes belonging to this module have been
634 * released.
635 */
636 if (dcdbas_pdev)
637 smi_data_buf_free();
638 platform_device_unregister(dcdbas_pdev_reg);
639 platform_driver_unregister(&dcdbas_driver);
640}
641
642subsys_initcall_sync(dcdbas_init);
643module_exit(dcdbas_exit);
644
645MODULE_DESCRIPTION(DRIVER_DESCRIPTION " (version " DRIVER_VERSION ")");
646MODULE_VERSION(DRIVER_VERSION);
647MODULE_AUTHOR("Dell Inc.");
648MODULE_LICENSE("GPL");
649/* Any System or BIOS claiming to be by Dell */
650MODULE_ALIAS("dmi:*:[bs]vnD[Ee][Ll][Ll]*:*");
diff --git a/drivers/firmware/dcdbas.h b/drivers/firmware/dcdbas.h
deleted file mode 100644
index ca3cb0a54ab6..000000000000
--- a/drivers/firmware/dcdbas.h
+++ /dev/null
@@ -1,107 +0,0 @@
1/*
2 * dcdbas.h: Definitions for Dell Systems Management Base driver
3 *
4 * Copyright (C) 1995-2005 Dell Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License v2.0 as published by
8 * the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#ifndef _DCDBAS_H_
17#define _DCDBAS_H_
18
19#include <linux/device.h>
20#include <linux/sysfs.h>
21#include <linux/types.h>
22
23#define MAX_SMI_DATA_BUF_SIZE (256 * 1024)
24
25#define HC_ACTION_NONE (0)
26#define HC_ACTION_HOST_CONTROL_POWEROFF BIT(1)
27#define HC_ACTION_HOST_CONTROL_POWERCYCLE BIT(2)
28
29#define HC_SMITYPE_NONE (0)
30#define HC_SMITYPE_TYPE1 (1)
31#define HC_SMITYPE_TYPE2 (2)
32#define HC_SMITYPE_TYPE3 (3)
33
34#define ESM_APM_CMD (0x0A0)
35#define ESM_APM_POWER_CYCLE (0x10)
36#define ESM_STATUS_CMD_UNSUCCESSFUL (-1)
37
38#define CMOS_BASE_PORT (0x070)
39#define CMOS_PAGE1_INDEX_PORT (0)
40#define CMOS_PAGE1_DATA_PORT (1)
41#define CMOS_PAGE2_INDEX_PORT_PIIX4 (2)
42#define CMOS_PAGE2_DATA_PORT_PIIX4 (3)
43#define PE1400_APM_CONTROL_PORT (0x0B0)
44#define PCAT_APM_CONTROL_PORT (0x0B2)
45#define PCAT_APM_STATUS_PORT (0x0B3)
46#define PE1300_CMOS_CMD_STRUCT_PTR (0x38)
47#define PE1400_CMOS_CMD_STRUCT_PTR (0x70)
48
49#define MAX_SYSMGMT_SHORTCMD_PARMBUF_LEN (14)
50#define MAX_SYSMGMT_LONGCMD_SGENTRY_NUM (16)
51
52#define TIMEOUT_USEC_SHORT_SEMA_BLOCKING (10000)
53#define EXPIRED_TIMER (0)
54
55#define SMI_CMD_MAGIC (0x534D4931)
56
57#define DCDBAS_DEV_ATTR_RW(_name) \
58 DEVICE_ATTR(_name,0600,_name##_show,_name##_store);
59
60#define DCDBAS_DEV_ATTR_RO(_name) \
61 DEVICE_ATTR(_name,0400,_name##_show,NULL);
62
63#define DCDBAS_DEV_ATTR_WO(_name) \
64 DEVICE_ATTR(_name,0200,NULL,_name##_store);
65
66#define DCDBAS_BIN_ATTR_RW(_name) \
67struct bin_attribute bin_attr_##_name = { \
68 .attr = { .name = __stringify(_name), \
69 .mode = 0600 }, \
70 .read = _name##_read, \
71 .write = _name##_write, \
72}
73
74struct smi_cmd {
75 __u32 magic;
76 __u32 ebx;
77 __u32 ecx;
78 __u16 command_address;
79 __u8 command_code;
80 __u8 reserved;
81 __u8 command_buffer[1];
82} __attribute__ ((packed));
83
84struct apm_cmd {
85 __u8 command;
86 __s8 status;
87 __u16 reserved;
88 union {
89 struct {
90 __u8 parm[MAX_SYSMGMT_SHORTCMD_PARMBUF_LEN];
91 } __attribute__ ((packed)) shortreq;
92
93 struct {
94 __u16 num_sg_entries;
95 struct {
96 __u32 size;
97 __u64 addr;
98 } __attribute__ ((packed))
99 sglist[MAX_SYSMGMT_LONGCMD_SGENTRY_NUM];
100 } __attribute__ ((packed)) longreq;
101 } __attribute__ ((packed)) parameters;
102} __attribute__ ((packed));
103
104int dcdbas_smi_request(struct smi_cmd *smi_cmd);
105
106#endif /* _DCDBAS_H_ */
107
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
deleted file mode 100644
index fb8af5cb7c9b..000000000000
--- a/drivers/firmware/dell_rbu.c
+++ /dev/null
@@ -1,745 +0,0 @@
1/*
2 * dell_rbu.c
3 * Bios Update driver for Dell systems
4 * Author: Dell Inc
5 * Abhay Salunke <abhay_salunke@dell.com>
6 *
7 * Copyright (C) 2005 Dell Inc.
8 *
9 * Remote BIOS Update (rbu) driver is used for updating DELL BIOS by
10 * creating entries in the /sys file systems on Linux 2.6 and higher
11 * kernels. The driver supports two mechanism to update the BIOS namely
12 * contiguous and packetized. Both these methods still require having some
13 * application to set the CMOS bit indicating the BIOS to update itself
14 * after a reboot.
15 *
16 * Contiguous method:
17 * This driver writes the incoming data in a monolithic image by allocating
18 * contiguous physical pages large enough to accommodate the incoming BIOS
19 * image size.
20 *
21 * Packetized method:
22 * The driver writes the incoming packet image by allocating a new packet
23 * on every time the packet data is written. This driver requires an
24 * application to break the BIOS image in to fixed sized packet chunks.
25 *
26 * See Documentation/dell_rbu.txt for more info.
27 *
28 * This program is free software; you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License v2.0 as published by
30 * the Free Software Foundation
31 *
32 * This program is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
36 */
37#include <linux/init.h>
38#include <linux/module.h>
39#include <linux/slab.h>
40#include <linux/string.h>
41#include <linux/errno.h>
42#include <linux/blkdev.h>
43#include <linux/platform_device.h>
44#include <linux/spinlock.h>
45#include <linux/moduleparam.h>
46#include <linux/firmware.h>
47#include <linux/dma-mapping.h>
48
49MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
50MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
51MODULE_LICENSE("GPL");
52MODULE_VERSION("3.2");
53
54#define BIOS_SCAN_LIMIT 0xffffffff
55#define MAX_IMAGE_LENGTH 16
56static struct _rbu_data {
57 void *image_update_buffer;
58 unsigned long image_update_buffer_size;
59 unsigned long bios_image_size;
60 int image_update_ordernum;
61 int dma_alloc;
62 spinlock_t lock;
63 unsigned long packet_read_count;
64 unsigned long num_packets;
65 unsigned long packetsize;
66 unsigned long imagesize;
67 int entry_created;
68} rbu_data;
69
70static char image_type[MAX_IMAGE_LENGTH + 1] = "mono";
71module_param_string(image_type, image_type, sizeof (image_type), 0);
72MODULE_PARM_DESC(image_type,
73 "BIOS image type. choose- mono or packet or init");
74
75static unsigned long allocation_floor = 0x100000;
76module_param(allocation_floor, ulong, 0644);
77MODULE_PARM_DESC(allocation_floor,
78 "Minimum address for allocations when using Packet mode");
79
80struct packet_data {
81 struct list_head list;
82 size_t length;
83 void *data;
84 int ordernum;
85};
86
87static struct packet_data packet_data_head;
88
89static struct platform_device *rbu_device;
90static int context;
91static dma_addr_t dell_rbu_dmaaddr;
92
93static void init_packet_head(void)
94{
95 INIT_LIST_HEAD(&packet_data_head.list);
96 rbu_data.packet_read_count = 0;
97 rbu_data.num_packets = 0;
98 rbu_data.packetsize = 0;
99 rbu_data.imagesize = 0;
100}
101
102static int create_packet(void *data, size_t length)
103{
104 struct packet_data *newpacket;
105 int ordernum = 0;
106 int retval = 0;
107 unsigned int packet_array_size = 0;
108 void **invalid_addr_packet_array = NULL;
109 void *packet_data_temp_buf = NULL;
110 unsigned int idx = 0;
111
112 pr_debug("create_packet: entry \n");
113
114 if (!rbu_data.packetsize) {
115 pr_debug("create_packet: packetsize not specified\n");
116 retval = -EINVAL;
117 goto out_noalloc;
118 }
119
120 spin_unlock(&rbu_data.lock);
121
122 newpacket = kzalloc(sizeof (struct packet_data), GFP_KERNEL);
123
124 if (!newpacket) {
125 printk(KERN_WARNING
126 "dell_rbu:%s: failed to allocate new "
127 "packet\n", __func__);
128 retval = -ENOMEM;
129 spin_lock(&rbu_data.lock);
130 goto out_noalloc;
131 }
132
133 ordernum = get_order(length);
134
135 /*
136 * BIOS errata mean we cannot allocate packets below 1MB or they will
137 * be overwritten by BIOS.
138 *
139 * array to temporarily hold packets
140 * that are below the allocation floor
141 *
142 * NOTE: very simplistic because we only need the floor to be at 1MB
143 * due to BIOS errata. This shouldn't be used for higher floors
144 * or you will run out of mem trying to allocate the array.
145 */
146 packet_array_size = max(
147 (unsigned int)(allocation_floor / rbu_data.packetsize),
148 (unsigned int)1);
149 invalid_addr_packet_array = kcalloc(packet_array_size, sizeof(void *),
150 GFP_KERNEL);
151
152 if (!invalid_addr_packet_array) {
153 printk(KERN_WARNING
154 "dell_rbu:%s: failed to allocate "
155 "invalid_addr_packet_array \n",
156 __func__);
157 retval = -ENOMEM;
158 spin_lock(&rbu_data.lock);
159 goto out_alloc_packet;
160 }
161
162 while (!packet_data_temp_buf) {
163 packet_data_temp_buf = (unsigned char *)
164 __get_free_pages(GFP_KERNEL, ordernum);
165 if (!packet_data_temp_buf) {
166 printk(KERN_WARNING
167 "dell_rbu:%s: failed to allocate new "
168 "packet\n", __func__);
169 retval = -ENOMEM;
170 spin_lock(&rbu_data.lock);
171 goto out_alloc_packet_array;
172 }
173
174 if ((unsigned long)virt_to_phys(packet_data_temp_buf)
175 < allocation_floor) {
176 pr_debug("packet 0x%lx below floor at 0x%lx.\n",
177 (unsigned long)virt_to_phys(
178 packet_data_temp_buf),
179 allocation_floor);
180 invalid_addr_packet_array[idx++] = packet_data_temp_buf;
181 packet_data_temp_buf = NULL;
182 }
183 }
184 spin_lock(&rbu_data.lock);
185
186 newpacket->data = packet_data_temp_buf;
187
188 pr_debug("create_packet: newpacket at physical addr %lx\n",
189 (unsigned long)virt_to_phys(newpacket->data));
190
191 /* packets may not have fixed size */
192 newpacket->length = length;
193 newpacket->ordernum = ordernum;
194 ++rbu_data.num_packets;
195
196 /* initialize the newly created packet headers */
197 INIT_LIST_HEAD(&newpacket->list);
198 list_add_tail(&newpacket->list, &packet_data_head.list);
199
200 memcpy(newpacket->data, data, length);
201
202 pr_debug("create_packet: exit \n");
203
204out_alloc_packet_array:
205 /* always free packet array */
206 for (;idx>0;idx--) {
207 pr_debug("freeing unused packet below floor 0x%lx.\n",
208 (unsigned long)virt_to_phys(
209 invalid_addr_packet_array[idx-1]));
210 free_pages((unsigned long)invalid_addr_packet_array[idx-1],
211 ordernum);
212 }
213 kfree(invalid_addr_packet_array);
214
215out_alloc_packet:
216 /* if error, free data */
217 if (retval)
218 kfree(newpacket);
219
220out_noalloc:
221 return retval;
222}
223
224static int packetize_data(const u8 *data, size_t length)
225{
226 int rc = 0;
227 int done = 0;
228 int packet_length;
229 u8 *temp;
230 u8 *end = (u8 *) data + length;
231 pr_debug("packetize_data: data length %zd\n", length);
232 if (!rbu_data.packetsize) {
233 printk(KERN_WARNING
234 "dell_rbu: packetsize not specified\n");
235 return -EIO;
236 }
237
238 temp = (u8 *) data;
239
240 /* packetize the hunk */
241 while (!done) {
242 if ((temp + rbu_data.packetsize) < end)
243 packet_length = rbu_data.packetsize;
244 else {
245 /* this is the last packet */
246 packet_length = end - temp;
247 done = 1;
248 }
249
250 if ((rc = create_packet(temp, packet_length)))
251 return rc;
252
253 pr_debug("%p:%td\n", temp, (end - temp));
254 temp += packet_length;
255 }
256
257 rbu_data.imagesize = length;
258
259 return rc;
260}
261
262static int do_packet_read(char *data, struct list_head *ptemp_list,
263 int length, int bytes_read, int *list_read_count)
264{
265 void *ptemp_buf;
266 struct packet_data *newpacket = NULL;
267 int bytes_copied = 0;
268 int j = 0;
269
270 newpacket = list_entry(ptemp_list, struct packet_data, list);
271 *list_read_count += newpacket->length;
272
273 if (*list_read_count > bytes_read) {
274 /* point to the start of unread data */
275 j = newpacket->length - (*list_read_count - bytes_read);
276 /* point to the offset in the packet buffer */
277 ptemp_buf = (u8 *) newpacket->data + j;
278 /*
279 * check if there is enough room in
280 * * the incoming buffer
281 */
282 if (length > (*list_read_count - bytes_read))
283 /*
284 * copy what ever is there in this
285 * packet and move on
286 */
287 bytes_copied = (*list_read_count - bytes_read);
288 else
289 /* copy the remaining */
290 bytes_copied = length;
291 memcpy(data, ptemp_buf, bytes_copied);
292 }
293 return bytes_copied;
294}
295
296static int packet_read_list(char *data, size_t * pread_length)
297{
298 struct list_head *ptemp_list;
299 int temp_count = 0;
300 int bytes_copied = 0;
301 int bytes_read = 0;
302 int remaining_bytes = 0;
303 char *pdest = data;
304
305 /* check if we have any packets */
306 if (0 == rbu_data.num_packets)
307 return -ENOMEM;
308
309 remaining_bytes = *pread_length;
310 bytes_read = rbu_data.packet_read_count;
311
312 ptemp_list = (&packet_data_head.list)->next;
313 while (!list_empty(ptemp_list)) {
314 bytes_copied = do_packet_read(pdest, ptemp_list,
315 remaining_bytes, bytes_read, &temp_count);
316 remaining_bytes -= bytes_copied;
317 bytes_read += bytes_copied;
318 pdest += bytes_copied;
319 /*
320 * check if we reached end of buffer before reaching the
321 * last packet
322 */
323 if (remaining_bytes == 0)
324 break;
325
326 ptemp_list = ptemp_list->next;
327 }
328 /*finally set the bytes read */
329 *pread_length = bytes_read - rbu_data.packet_read_count;
330 rbu_data.packet_read_count = bytes_read;
331 return 0;
332}
333
334static void packet_empty_list(void)
335{
336 struct list_head *ptemp_list;
337 struct list_head *pnext_list;
338 struct packet_data *newpacket;
339
340 ptemp_list = (&packet_data_head.list)->next;
341 while (!list_empty(ptemp_list)) {
342 newpacket =
343 list_entry(ptemp_list, struct packet_data, list);
344 pnext_list = ptemp_list->next;
345 list_del(ptemp_list);
346 ptemp_list = pnext_list;
347 /*
348 * zero out the RBU packet memory before freeing
349 * to make sure there are no stale RBU packets left in memory
350 */
351 memset(newpacket->data, 0, rbu_data.packetsize);
352 free_pages((unsigned long) newpacket->data,
353 newpacket->ordernum);
354 kfree(newpacket);
355 }
356 rbu_data.packet_read_count = 0;
357 rbu_data.num_packets = 0;
358 rbu_data.imagesize = 0;
359}
360
361/*
362 * img_update_free: Frees the buffer allocated for storing BIOS image
363 * Always called with lock held and returned with lock held
364 */
365static void img_update_free(void)
366{
367 if (!rbu_data.image_update_buffer)
368 return;
369 /*
370 * zero out this buffer before freeing it to get rid of any stale
371 * BIOS image copied in memory.
372 */
373 memset(rbu_data.image_update_buffer, 0,
374 rbu_data.image_update_buffer_size);
375 if (rbu_data.dma_alloc == 1)
376 dma_free_coherent(NULL, rbu_data.bios_image_size,
377 rbu_data.image_update_buffer, dell_rbu_dmaaddr);
378 else
379 free_pages((unsigned long) rbu_data.image_update_buffer,
380 rbu_data.image_update_ordernum);
381
382 /*
383 * Re-initialize the rbu_data variables after a free
384 */
385 rbu_data.image_update_ordernum = -1;
386 rbu_data.image_update_buffer = NULL;
387 rbu_data.image_update_buffer_size = 0;
388 rbu_data.bios_image_size = 0;
389 rbu_data.dma_alloc = 0;
390}
391
392/*
393 * img_update_realloc: This function allocates the contiguous pages to
394 * accommodate the requested size of data. The memory address and size
395 * values are stored globally and on every call to this function the new
396 * size is checked to see if more data is required than the existing size.
397 * If true the previous memory is freed and new allocation is done to
398 * accommodate the new size. If the incoming size is less then than the
399 * already allocated size, then that memory is reused. This function is
400 * called with lock held and returns with lock held.
401 */
402static int img_update_realloc(unsigned long size)
403{
404 unsigned char *image_update_buffer = NULL;
405 unsigned long rc;
406 unsigned long img_buf_phys_addr;
407 int ordernum;
408 int dma_alloc = 0;
409
410 /*
411 * check if the buffer of sufficient size has been
412 * already allocated
413 */
414 if (rbu_data.image_update_buffer_size >= size) {
415 /*
416 * check for corruption
417 */
418 if ((size != 0) && (rbu_data.image_update_buffer == NULL)) {
419 printk(KERN_ERR "dell_rbu:%s: corruption "
420 "check failed\n", __func__);
421 return -EINVAL;
422 }
423 /*
424 * we have a valid pre-allocated buffer with
425 * sufficient size
426 */
427 return 0;
428 }
429
430 /*
431 * free any previously allocated buffer
432 */
433 img_update_free();
434
435 spin_unlock(&rbu_data.lock);
436
437 ordernum = get_order(size);
438 image_update_buffer =
439 (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum);
440
441 img_buf_phys_addr =
442 (unsigned long) virt_to_phys(image_update_buffer);
443
444 if (img_buf_phys_addr > BIOS_SCAN_LIMIT) {
445 free_pages((unsigned long) image_update_buffer, ordernum);
446 ordernum = -1;
447 image_update_buffer = dma_alloc_coherent(NULL, size,
448 &dell_rbu_dmaaddr, GFP_KERNEL);
449 dma_alloc = 1;
450 }
451
452 spin_lock(&rbu_data.lock);
453
454 if (image_update_buffer != NULL) {
455 rbu_data.image_update_buffer = image_update_buffer;
456 rbu_data.image_update_buffer_size = size;
457 rbu_data.bios_image_size =
458 rbu_data.image_update_buffer_size;
459 rbu_data.image_update_ordernum = ordernum;
460 rbu_data.dma_alloc = dma_alloc;
461 rc = 0;
462 } else {
463 pr_debug("Not enough memory for image update:"
464 "size = %ld\n", size);
465 rc = -ENOMEM;
466 }
467
468 return rc;
469}
470
471static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
472{
473 int retval;
474 size_t bytes_left;
475 size_t data_length;
476 char *ptempBuf = buffer;
477
478 /* check to see if we have something to return */
479 if (rbu_data.num_packets == 0) {
480 pr_debug("read_packet_data: no packets written\n");
481 retval = -ENOMEM;
482 goto read_rbu_data_exit;
483 }
484
485 if (pos > rbu_data.imagesize) {
486 retval = 0;
487 printk(KERN_WARNING "dell_rbu:read_packet_data: "
488 "data underrun\n");
489 goto read_rbu_data_exit;
490 }
491
492 bytes_left = rbu_data.imagesize - pos;
493 data_length = min(bytes_left, count);
494
495 if ((retval = packet_read_list(ptempBuf, &data_length)) < 0)
496 goto read_rbu_data_exit;
497
498 if ((pos + count) > rbu_data.imagesize) {
499 rbu_data.packet_read_count = 0;
500 /* this was the last copy */
501 retval = bytes_left;
502 } else
503 retval = count;
504
505 read_rbu_data_exit:
506 return retval;
507}
508
509static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
510{
511 /* check to see if we have something to return */
512 if ((rbu_data.image_update_buffer == NULL) ||
513 (rbu_data.bios_image_size == 0)) {
514 pr_debug("read_rbu_data_mono: image_update_buffer %p ,"
515 "bios_image_size %lu\n",
516 rbu_data.image_update_buffer,
517 rbu_data.bios_image_size);
518 return -ENOMEM;
519 }
520
521 return memory_read_from_buffer(buffer, count, &pos,
522 rbu_data.image_update_buffer, rbu_data.bios_image_size);
523}
524
525static ssize_t read_rbu_data(struct file *filp, struct kobject *kobj,
526 struct bin_attribute *bin_attr,
527 char *buffer, loff_t pos, size_t count)
528{
529 ssize_t ret_count = 0;
530
531 spin_lock(&rbu_data.lock);
532
533 if (!strcmp(image_type, "mono"))
534 ret_count = read_rbu_mono_data(buffer, pos, count);
535 else if (!strcmp(image_type, "packet"))
536 ret_count = read_packet_data(buffer, pos, count);
537 else
538 pr_debug("read_rbu_data: invalid image type specified\n");
539
540 spin_unlock(&rbu_data.lock);
541 return ret_count;
542}
543
544static void callbackfn_rbu(const struct firmware *fw, void *context)
545{
546 rbu_data.entry_created = 0;
547
548 if (!fw)
549 return;
550
551 if (!fw->size)
552 goto out;
553
554 spin_lock(&rbu_data.lock);
555 if (!strcmp(image_type, "mono")) {
556 if (!img_update_realloc(fw->size))
557 memcpy(rbu_data.image_update_buffer,
558 fw->data, fw->size);
559 } else if (!strcmp(image_type, "packet")) {
560 /*
561 * we need to free previous packets if a
562 * new hunk of packets needs to be downloaded
563 */
564 packet_empty_list();
565 if (packetize_data(fw->data, fw->size))
566 /* Incase something goes wrong when we are
567 * in middle of packetizing the data, we
568 * need to free up whatever packets might
569 * have been created before we quit.
570 */
571 packet_empty_list();
572 } else
573 pr_debug("invalid image type specified.\n");
574 spin_unlock(&rbu_data.lock);
575 out:
576 release_firmware(fw);
577}
578
579static ssize_t read_rbu_image_type(struct file *filp, struct kobject *kobj,
580 struct bin_attribute *bin_attr,
581 char *buffer, loff_t pos, size_t count)
582{
583 int size = 0;
584 if (!pos)
585 size = scnprintf(buffer, count, "%s\n", image_type);
586 return size;
587}
588
589static ssize_t write_rbu_image_type(struct file *filp, struct kobject *kobj,
590 struct bin_attribute *bin_attr,
591 char *buffer, loff_t pos, size_t count)
592{
593 int rc = count;
594 int req_firm_rc = 0;
595 int i;
596 spin_lock(&rbu_data.lock);
597 /*
598 * Find the first newline or space
599 */
600 for (i = 0; i < count; ++i)
601 if (buffer[i] == '\n' || buffer[i] == ' ') {
602 buffer[i] = '\0';
603 break;
604 }
605 if (i == count)
606 buffer[count] = '\0';
607
608 if (strstr(buffer, "mono"))
609 strcpy(image_type, "mono");
610 else if (strstr(buffer, "packet"))
611 strcpy(image_type, "packet");
612 else if (strstr(buffer, "init")) {
613 /*
614 * If due to the user error the driver gets in a bad
615 * state where even though it is loaded , the
616 * /sys/class/firmware/dell_rbu entries are missing.
617 * to cover this situation the user can recreate entries
618 * by writing init to image_type.
619 */
620 if (!rbu_data.entry_created) {
621 spin_unlock(&rbu_data.lock);
622 req_firm_rc = request_firmware_nowait(THIS_MODULE,
623 FW_ACTION_NOHOTPLUG, "dell_rbu",
624 &rbu_device->dev, GFP_KERNEL, &context,
625 callbackfn_rbu);
626 if (req_firm_rc) {
627 printk(KERN_ERR
628 "dell_rbu:%s request_firmware_nowait"
629 " failed %d\n", __func__, rc);
630 rc = -EIO;
631 } else
632 rbu_data.entry_created = 1;
633
634 spin_lock(&rbu_data.lock);
635 }
636 } else {
637 printk(KERN_WARNING "dell_rbu: image_type is invalid\n");
638 spin_unlock(&rbu_data.lock);
639 return -EINVAL;
640 }
641
642 /* we must free all previous allocations */
643 packet_empty_list();
644 img_update_free();
645 spin_unlock(&rbu_data.lock);
646
647 return rc;
648}
649
650static ssize_t read_rbu_packet_size(struct file *filp, struct kobject *kobj,
651 struct bin_attribute *bin_attr,
652 char *buffer, loff_t pos, size_t count)
653{
654 int size = 0;
655 if (!pos) {
656 spin_lock(&rbu_data.lock);
657 size = scnprintf(buffer, count, "%lu\n", rbu_data.packetsize);
658 spin_unlock(&rbu_data.lock);
659 }
660 return size;
661}
662
663static ssize_t write_rbu_packet_size(struct file *filp, struct kobject *kobj,
664 struct bin_attribute *bin_attr,
665 char *buffer, loff_t pos, size_t count)
666{
667 unsigned long temp;
668 spin_lock(&rbu_data.lock);
669 packet_empty_list();
670 sscanf(buffer, "%lu", &temp);
671 if (temp < 0xffffffff)
672 rbu_data.packetsize = temp;
673
674 spin_unlock(&rbu_data.lock);
675 return count;
676}
677
678static struct bin_attribute rbu_data_attr = {
679 .attr = {.name = "data", .mode = 0444},
680 .read = read_rbu_data,
681};
682
683static struct bin_attribute rbu_image_type_attr = {
684 .attr = {.name = "image_type", .mode = 0644},
685 .read = read_rbu_image_type,
686 .write = write_rbu_image_type,
687};
688
689static struct bin_attribute rbu_packet_size_attr = {
690 .attr = {.name = "packet_size", .mode = 0644},
691 .read = read_rbu_packet_size,
692 .write = write_rbu_packet_size,
693};
694
695static int __init dcdrbu_init(void)
696{
697 int rc;
698 spin_lock_init(&rbu_data.lock);
699
700 init_packet_head();
701 rbu_device = platform_device_register_simple("dell_rbu", -1, NULL, 0);
702 if (IS_ERR(rbu_device)) {
703 printk(KERN_ERR
704 "dell_rbu:%s:platform_device_register_simple "
705 "failed\n", __func__);
706 return PTR_ERR(rbu_device);
707 }
708
709 rc = sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
710 if (rc)
711 goto out_devreg;
712 rc = sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
713 if (rc)
714 goto out_data;
715 rc = sysfs_create_bin_file(&rbu_device->dev.kobj,
716 &rbu_packet_size_attr);
717 if (rc)
718 goto out_imtype;
719
720 rbu_data.entry_created = 0;
721 return 0;
722
723out_imtype:
724 sysfs_remove_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
725out_data:
726 sysfs_remove_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
727out_devreg:
728 platform_device_unregister(rbu_device);
729 return rc;
730}
731
732static __exit void dcdrbu_exit(void)
733{
734 spin_lock(&rbu_data.lock);
735 packet_empty_list();
736 img_update_free();
737 spin_unlock(&rbu_data.lock);
738 platform_device_unregister(rbu_device);
739}
740
741module_exit(dcdrbu_exit);
742module_init(dcdrbu_init);
743
744/* vim:noet:ts=8:sw=8
745*/