mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-25 06:03:36 -04:00
Merge master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: drivers/macintosh/adbhid.c
This commit is contained in:
commit
b981d8b3f5
7628 changed files with 537060 additions and 239341 deletions
|
|
@ -130,6 +130,7 @@ config ROCKETPORT
|
|||
config CYCLADES
|
||||
tristate "Cyclades async mux support"
|
||||
depends on SERIAL_NONSTANDARD && (PCI || ISA)
|
||||
select FW_LOADER
|
||||
---help---
|
||||
This driver supports Cyclades Z and Y multiserial boards.
|
||||
You would need something like this to connect more than two modems to
|
||||
|
|
@ -185,7 +186,7 @@ config ESPSERIAL
|
|||
|
||||
config MOXA_INTELLIO
|
||||
tristate "Moxa Intellio support"
|
||||
depends on SERIAL_NONSTANDARD
|
||||
depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
|
||||
help
|
||||
Say Y here if you have a Moxa Intellio multiport serial card.
|
||||
|
||||
|
|
@ -241,7 +242,7 @@ config SYNCLINK
|
|||
|
||||
config SYNCLINKMP
|
||||
tristate "SyncLink Multiport support"
|
||||
depends on SERIAL_NONSTANDARD
|
||||
depends on SERIAL_NONSTANDARD && PCI
|
||||
help
|
||||
Enable support for the SyncLink Multiport (2 or 4 ports)
|
||||
serial adapter, running asynchronous and HDLC communications up
|
||||
|
|
@ -372,39 +373,6 @@ config ISTALLION
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called istallion.
|
||||
|
||||
config SERIAL_DEC
|
||||
bool "DECstation serial support"
|
||||
depends on MACH_DECSTATION
|
||||
default y
|
||||
help
|
||||
This selects whether you want to be asked about drivers for
|
||||
DECstation serial ports.
|
||||
|
||||
Note that the answer to this question won't directly affect the
|
||||
kernel: saying N will just cause the configurator to skip all
|
||||
the questions about DECstation serial ports.
|
||||
|
||||
config SERIAL_DEC_CONSOLE
|
||||
bool "Support for console on a DECstation serial port"
|
||||
depends on SERIAL_DEC
|
||||
default y
|
||||
help
|
||||
If you say Y here, it will be possible to use a serial port as the
|
||||
system console (the system console is the device which receives all
|
||||
kernel messages and warnings and which allows logins in single user
|
||||
mode). Note that the firmware uses ttyS0 as the serial console on
|
||||
the Maxine and ttyS2 on the others.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config ZS
|
||||
bool "Z85C30 Serial Support"
|
||||
depends on SERIAL_DEC
|
||||
default y
|
||||
help
|
||||
Documentation on the Zilog 85C350 serial communications controller
|
||||
is downloadable at <http://www.zilog.com/pdfs/serial/z85c30.pdf>
|
||||
|
||||
config A2232
|
||||
tristate "Commodore A2232 serial support (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL && ZORRO && BROKEN_ON_SMP
|
||||
|
|
@ -637,6 +605,14 @@ config HVC_BEAT
|
|||
help
|
||||
Toshiba's Cell Reference Set Beat Console device driver
|
||||
|
||||
config HVC_XEN
|
||||
bool "Xen Hypervisor Console support"
|
||||
depends on XEN
|
||||
select HVC_DRIVER
|
||||
default y
|
||||
help
|
||||
Xen virtual console device driver
|
||||
|
||||
config HVCS
|
||||
tristate "IBM Hypervisor Virtual Console Server support"
|
||||
depends on PPC_PSERIES
|
||||
|
|
@ -751,7 +727,7 @@ config NVRAM
|
|||
|
||||
config RTC
|
||||
tristate "Enhanced Real Time Clock Support"
|
||||
depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM && !SUPERH && !S390
|
||||
depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV && !ARM && !SUPERH && !S390
|
||||
---help---
|
||||
If you say Y here and create a character special file /dev/rtc with
|
||||
major number 10 and minor number 135 using mknod ("man mknod"), you
|
||||
|
|
@ -775,6 +751,28 @@ config RTC
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called rtc.
|
||||
|
||||
config JS_RTC
|
||||
tristate "Enhanced Real Time Clock Support"
|
||||
depends on SPARC32 && PCI
|
||||
---help---
|
||||
If you say Y here and create a character special file /dev/rtc with
|
||||
major number 10 and minor number 135 using mknod ("man mknod"), you
|
||||
will get access to the real time clock (or hardware clock) built
|
||||
into your computer.
|
||||
|
||||
Every PC has such a clock built in. It can be used to generate
|
||||
signals from as low as 1Hz up to 8192Hz, and can also be used
|
||||
as a 24 hour alarm. It reports status information via the file
|
||||
/proc/driver/rtc and its behaviour is set by various ioctls on
|
||||
/dev/rtc.
|
||||
|
||||
If you think you have a use for such a device (such as periodic data
|
||||
sampling), then say Y here, and read <file:Documentation/rtc.txt>
|
||||
for details.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called js-rtc.
|
||||
|
||||
config SGI_DS1286
|
||||
tristate "SGI DS1286 RTC support"
|
||||
depends on SGI_IP22
|
||||
|
|
|
|||
|
|
@ -42,12 +42,14 @@ obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o
|
|||
obj-$(CONFIG_N_HDLC) += n_hdlc.o
|
||||
obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
|
||||
obj-$(CONFIG_SX) += sx.o generic_serial.o
|
||||
obj-$(CONFIG_LGUEST_GUEST) += hvc_lguest.o
|
||||
obj-$(CONFIG_RIO) += rio/ generic_serial.o
|
||||
obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o
|
||||
obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o
|
||||
obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o
|
||||
obj-$(CONFIG_HVC_BEAT) += hvc_beat.o
|
||||
obj-$(CONFIG_HVC_DRIVER) += hvc_console.o
|
||||
obj-$(CONFIG_HVC_XEN) += hvc_xen.o
|
||||
obj-$(CONFIG_RAW_DRIVER) += raw.o
|
||||
obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o
|
||||
obj-$(CONFIG_MSPEC) += mspec.o
|
||||
|
|
@ -95,7 +97,6 @@ obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
|
|||
obj-$(CONFIG_GPIO_TB0219) += tb0219.o
|
||||
obj-$(CONFIG_TELCLOCK) += tlclk.o
|
||||
|
||||
obj-$(CONFIG_WATCHDOG) += watchdog/
|
||||
obj-$(CONFIG_MWAVE) += mwave/
|
||||
obj-$(CONFIG_AGP) += agp/
|
||||
obj-$(CONFIG_DRM) += drm/
|
||||
|
|
@ -105,6 +106,11 @@ obj-$(CONFIG_IPMI_HANDLER) += ipmi/
|
|||
obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
|
||||
obj-$(CONFIG_TCG_TPM) += tpm/
|
||||
|
||||
obj-$(CONFIG_PS3_FLASH) += ps3flash.o
|
||||
|
||||
obj-$(CONFIG_JS_RTC) += js-rtc.o
|
||||
js-rtc-y = rtc.o
|
||||
|
||||
# Files generated that shall be removed upon make clean
|
||||
clean-files := consolemap_deftbl.c defkeymap.c
|
||||
|
||||
|
|
@ -123,7 +129,7 @@ $(obj)/defkeymap.o: $(obj)/defkeymap.c
|
|||
|
||||
ifdef GENERATE_KEYMAP
|
||||
|
||||
$(obj)/defkeymap.c $(obj)/%.c: $(src)/%.map
|
||||
$(obj)/defkeymap.c: $(obj)/%.c: $(src)/%.map
|
||||
loadkeys --mktable $< > $@.tmp
|
||||
sed -e 's/^static *//' $@.tmp > $@
|
||||
rm $@.tmp
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ config AGP_ATI
|
|||
|
||||
config AGP_AMD
|
||||
tristate "AMD Irongate, 761, and 762 chipset support"
|
||||
depends on AGP && X86_32
|
||||
depends on AGP && (X86_32 || ALPHA)
|
||||
help
|
||||
This option gives you AGP support for the GLX component of
|
||||
X on AMD Irongate, 761, and 762 chipsets.
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ struct agp_bridge_data {
|
|||
#define I830_GMCH_MEM_MASK 0x1
|
||||
#define I830_GMCH_MEM_64M 0x1
|
||||
#define I830_GMCH_MEM_128M 0
|
||||
#define I830_GMCH_GMS_MASK 0xF0
|
||||
#define I830_GMCH_GMS_MASK 0x70
|
||||
#define I830_GMCH_GMS_DISABLED 0x00
|
||||
#define I830_GMCH_GMS_LOCAL 0x10
|
||||
#define I830_GMCH_GMS_STOLEN_512 0x20
|
||||
|
|
@ -190,6 +190,7 @@ struct agp_bridge_data {
|
|||
#define INTEL_I830_ERRSTS 0x92
|
||||
|
||||
/* Intel 855GM/852GM registers */
|
||||
#define I855_GMCH_GMS_MASK 0xF0
|
||||
#define I855_GMCH_GMS_STOLEN_0M 0x0
|
||||
#define I855_GMCH_GMS_STOLEN_1M (0x1 << 4)
|
||||
#define I855_GMCH_GMS_STOLEN_4M (0x2 << 4)
|
||||
|
|
|
|||
|
|
@ -223,6 +223,8 @@ static int amd_irongate_configure(void)
|
|||
pci_read_config_dword(agp_bridge->dev, AMD_MMBASE, &temp);
|
||||
temp = (temp & PCI_BASE_ADDRESS_MEM_MASK);
|
||||
amd_irongate_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096);
|
||||
if (!amd_irongate_private.registers)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Write out the address of the gatt table */
|
||||
writel(agp_bridge->gatt_bus_addr, amd_irongate_private.registers+AMD_ATTBASE);
|
||||
|
|
|
|||
|
|
@ -123,21 +123,16 @@ static int ati_create_gatt_pages(int nr_tables)
|
|||
|
||||
for (i = 0; i < nr_tables; i++) {
|
||||
entry = kzalloc(sizeof(struct ati_page_map), GFP_KERNEL);
|
||||
tables[i] = entry;
|
||||
if (entry == NULL) {
|
||||
while (i > 0) {
|
||||
kfree(tables[i-1]);
|
||||
i--;
|
||||
}
|
||||
kfree(tables);
|
||||
retval = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
tables[i] = entry;
|
||||
retval = ati_create_page_map(entry);
|
||||
if (retval != 0)
|
||||
break;
|
||||
}
|
||||
ati_generic_private.num_tables = nr_tables;
|
||||
ati_generic_private.num_tables = i;
|
||||
ati_generic_private.gatt_pages = tables;
|
||||
|
||||
if (retval != 0)
|
||||
|
|
@ -218,6 +213,9 @@ static int ati_configure(void)
|
|||
temp = (temp & 0xfffff000);
|
||||
ati_generic_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096);
|
||||
|
||||
if (!ati_generic_private.registers)
|
||||
return -ENOMEM;
|
||||
|
||||
if (is_r200())
|
||||
pci_write_config_dword(agp_bridge->dev, ATI_RS100_IG_AGPMODE, 0x20000);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/agpgart.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include "agp.h"
|
||||
|
|
|
|||
|
|
@ -375,6 +375,7 @@ static int __devinit agp_efficeon_probe(struct pci_dev *pdev,
|
|||
if (!r->start && r->end) {
|
||||
if (pci_assign_resource(pdev, 0)) {
|
||||
printk(KERN_ERR PFX "could not assign resource 0\n");
|
||||
agp_put_bridge(bridge);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
|
@ -386,6 +387,7 @@ static int __devinit agp_efficeon_probe(struct pci_dev *pdev,
|
|||
*/
|
||||
if (pci_enable_device(pdev)) {
|
||||
printk(KERN_ERR PFX "Unable to Enable PCI device\n");
|
||||
agp_put_bridge(bridge);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include <linux/agpgart.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/sched.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
|
|
|||
|
|
@ -1170,7 +1170,6 @@ void *agp_generic_alloc_page(struct agp_bridge_data *bridge)
|
|||
map_page_into_agp(page);
|
||||
|
||||
get_page(page);
|
||||
SetPageLocked(page);
|
||||
atomic_inc(&agp_bridge->current_memory_agp);
|
||||
return page_address(page);
|
||||
}
|
||||
|
|
@ -1187,7 +1186,6 @@ void agp_generic_destroy_page(void *addr)
|
|||
page = virt_to_page(addr);
|
||||
unmap_page_from_agp(page);
|
||||
put_page(page);
|
||||
unlock_page(page);
|
||||
free_page((unsigned long)addr);
|
||||
atomic_dec(&agp_bridge->current_memory_agp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -221,6 +221,7 @@ hp_zx1_lba_init (u64 hpa)
|
|||
if (cap != PCI_CAP_ID_AGP) {
|
||||
printk(KERN_ERR PFX "Invalid capability ID 0x%02x at 0x%x\n",
|
||||
cap, hp->lba_cap_offset);
|
||||
iounmap(hp->lba_regs);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -249,6 +249,10 @@ static int i460_create_gatt_table (struct agp_bridge_data *bridge)
|
|||
num_entries = A_SIZE_8(temp)->num_entries;
|
||||
|
||||
i460.gatt = ioremap(INTEL_I460_ATTBASE, PAGE_SIZE << page_order);
|
||||
if (!i460.gatt) {
|
||||
printk(KERN_ERR PFX "ioremap failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* These are no good, the should be removed from the agp_bridge strucure... */
|
||||
agp_bridge->gatt_table_real = NULL;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@
|
|||
#define PCI_DEVICE_ID_INTEL_82965G_IG 0x29A2
|
||||
#define PCI_DEVICE_ID_INTEL_82965GM_HB 0x2A00
|
||||
#define PCI_DEVICE_ID_INTEL_82965GM_IG 0x2A02
|
||||
#define PCI_DEVICE_ID_INTEL_82965GME_HB 0x2A10
|
||||
#define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12
|
||||
#define PCI_DEVICE_ID_INTEL_82945GME_HB 0x27AC
|
||||
#define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE
|
||||
#define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0
|
||||
#define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2
|
||||
|
|
@ -33,7 +35,8 @@
|
|||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_1_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB)
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB)
|
||||
|
||||
#define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \
|
||||
|
|
@ -213,7 +216,6 @@ static void *i8xx_alloc_pages(void)
|
|||
}
|
||||
global_flush_tlb();
|
||||
get_page(page);
|
||||
SetPageLocked(page);
|
||||
atomic_inc(&agp_bridge->current_memory_agp);
|
||||
return page_address(page);
|
||||
}
|
||||
|
|
@ -229,7 +231,6 @@ static void i8xx_destroy_pages(void *addr)
|
|||
change_page_attr(page, 4, PAGE_KERNEL);
|
||||
global_flush_tlb();
|
||||
put_page(page);
|
||||
unlock_page(page);
|
||||
__free_pages(page, 2);
|
||||
atomic_dec(&agp_bridge->current_memory_agp);
|
||||
}
|
||||
|
|
@ -505,7 +506,7 @@ static void intel_i830_init_gtt_entries(void)
|
|||
break;
|
||||
}
|
||||
} else {
|
||||
switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
|
||||
switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
|
||||
case I855_GMCH_GMS_STOLEN_1M:
|
||||
gtt_entries = MB(1) - KB(size);
|
||||
break;
|
||||
|
|
@ -527,6 +528,7 @@ static void intel_i830_init_gtt_entries(void)
|
|||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB ||
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GME_HB ||
|
||||
IS_I965 || IS_G33)
|
||||
gtt_entries = MB(48) - KB(size);
|
||||
else
|
||||
|
|
@ -538,6 +540,7 @@ static void intel_i830_init_gtt_entries(void)
|
|||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB ||
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GME_HB ||
|
||||
IS_I965 || IS_G33)
|
||||
gtt_entries = MB(64) - KB(size);
|
||||
else
|
||||
|
|
@ -911,6 +914,7 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
|
|||
struct aper_size_info_fixed *size;
|
||||
int num_entries;
|
||||
u32 temp, temp2;
|
||||
int gtt_map_size = 256 * 1024;
|
||||
|
||||
size = agp_bridge->current_size;
|
||||
page_order = size->page_order;
|
||||
|
|
@ -920,15 +924,19 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
|
|||
pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
|
||||
pci_read_config_dword(intel_private.pcidev, I915_PTEADDR,&temp2);
|
||||
|
||||
intel_private.gtt = ioremap(temp2, 256 * 1024);
|
||||
if (IS_G33)
|
||||
gtt_map_size = 1024 * 1024; /* 1M on G33 */
|
||||
intel_private.gtt = ioremap(temp2, gtt_map_size);
|
||||
if (!intel_private.gtt)
|
||||
return -ENOMEM;
|
||||
|
||||
temp &= 0xfff80000;
|
||||
|
||||
intel_private.registers = ioremap(temp,128 * 4096);
|
||||
if (!intel_private.registers)
|
||||
if (!intel_private.registers) {
|
||||
iounmap(intel_private.gtt);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
|
||||
global_cache_flush(); /* FIXME: ? */
|
||||
|
|
@ -982,13 +990,15 @@ static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
|
|||
temp &= 0xfff00000;
|
||||
intel_private.gtt = ioremap((temp + (512 * 1024)) , 512 * 1024);
|
||||
|
||||
if (!intel_private.gtt)
|
||||
return -ENOMEM;
|
||||
if (!intel_private.gtt)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
intel_private.registers = ioremap(temp,128 * 4096);
|
||||
if (!intel_private.registers)
|
||||
return -ENOMEM;
|
||||
if (!intel_private.registers) {
|
||||
iounmap(intel_private.gtt);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
|
||||
global_cache_flush(); /* FIXME: ? */
|
||||
|
|
@ -1848,9 +1858,9 @@ static const struct intel_driver_description {
|
|||
NULL, &intel_915_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82945G_HB, PCI_DEVICE_ID_INTEL_82945G_IG, 0, "945G",
|
||||
NULL, &intel_915_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GM_IG, 1, "945GM",
|
||||
{ PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GM_IG, 0, "945GM",
|
||||
NULL, &intel_915_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GME_IG, 0, "945GME",
|
||||
{ PCI_DEVICE_ID_INTEL_82945GME_HB, PCI_DEVICE_ID_INTEL_82945GME_IG, 0, "945GME",
|
||||
NULL, &intel_915_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82946GZ_HB, PCI_DEVICE_ID_INTEL_82946GZ_IG, 0, "946GZ",
|
||||
NULL, &intel_i965_driver },
|
||||
|
|
@ -1860,9 +1870,9 @@ static const struct intel_driver_description {
|
|||
NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82965G_HB, PCI_DEVICE_ID_INTEL_82965G_IG, 0, "965G",
|
||||
NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GM_IG, 1, "965GM",
|
||||
{ PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GM_IG, 0, "965GM",
|
||||
NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GME_IG, 0, "965GME/GLE",
|
||||
{ PCI_DEVICE_ID_INTEL_82965GME_HB, PCI_DEVICE_ID_INTEL_82965GME_IG, 0, "965GME/GLE",
|
||||
NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_7505_0, 0, 0, "E7505", &intel_7505_driver, NULL },
|
||||
{ PCI_DEVICE_ID_INTEL_7205_0, 0, 0, "E7205", &intel_7505_driver, NULL },
|
||||
|
|
@ -2051,11 +2061,13 @@ static struct pci_device_id agp_intel_pci_table[] = {
|
|||
ID(PCI_DEVICE_ID_INTEL_82915GM_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_82945G_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_82945GM_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_82945GME_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_82946GZ_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_82965G_1_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_82965Q_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_82965G_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_82965GM_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_82965GME_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_G33_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_Q35_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_Q33_HB),
|
||||
|
|
|
|||
|
|
@ -157,6 +157,9 @@ static int nvidia_configure(void)
|
|||
nvidia_private.aperture =
|
||||
(volatile u32 __iomem *) ioremap(apbase, 33 * PAGE_SIZE);
|
||||
|
||||
if (!nvidia_private.aperture)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ static void *sgi_tioca_alloc_page(struct agp_bridge_data *bridge)
|
|||
return NULL;
|
||||
|
||||
get_page(page);
|
||||
SetPageLocked(page);
|
||||
atomic_inc(&agp_bridge->current_memory_agp);
|
||||
return page_address(page);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -399,6 +399,11 @@ static struct agp_device_ids via_agp_device_ids[] __devinitdata =
|
|||
.device_id = PCI_DEVICE_ID_VIA_P4M890,
|
||||
.chipset_name = "P4M890",
|
||||
},
|
||||
/* P4M900 */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_VT3364,
|
||||
.chipset_name = "P4M900",
|
||||
},
|
||||
{ }, /* dummy final entry, always present */
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1721,12 +1721,11 @@ static int get_async_struct(int line, struct async_struct **ret_info)
|
|||
*ret_info = sstate->info;
|
||||
return 0;
|
||||
}
|
||||
info = kmalloc(sizeof(struct async_struct), GFP_KERNEL);
|
||||
info = kzalloc(sizeof(struct async_struct), GFP_KERNEL);
|
||||
if (!info) {
|
||||
sstate->count--;
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(info, 0, sizeof(struct async_struct));
|
||||
#ifdef DECLARE_WAITQUEUE
|
||||
init_waitqueue_head(&info->open_wait);
|
||||
init_waitqueue_head(&info->close_wait);
|
||||
|
|
|
|||
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* sercons.c
|
||||
* choose the right serial device at boot time
|
||||
*
|
||||
* triemer 6-SEP-1998
|
||||
* sercons.c is designed to allow the three different kinds
|
||||
* of serial devices under the decstation world to co-exist
|
||||
* in the same kernel. The idea here is to abstract
|
||||
* the pieces of the drivers that are common to this file
|
||||
* so that they do not clash at compile time and runtime.
|
||||
*
|
||||
* HK 16-SEP-1998 v0.002
|
||||
* removed the PROM console as this is not a real serial
|
||||
* device. Added support for PROM console in drivers/char/tty_io.c
|
||||
* instead. Although it may work to enable more than one
|
||||
* console device I strongly recommend to use only one.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <asm/dec/machtype.h>
|
||||
|
||||
#ifdef CONFIG_ZS
|
||||
extern int zs_init(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_CONSOLE
|
||||
|
||||
#ifdef CONFIG_ZS
|
||||
extern void zs_serial_console_init(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* rs_init - starts up the serial interface -
|
||||
handle normal case of starting up the serial interface */
|
||||
|
||||
#ifdef CONFIG_SERIAL
|
||||
|
||||
int __init rs_init(void)
|
||||
{
|
||||
#ifdef CONFIG_ZS
|
||||
if (IOASIC)
|
||||
return zs_init();
|
||||
#endif
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
__initcall(rs_init);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_CONSOLE
|
||||
|
||||
/* serial_console_init handles the special case of starting
|
||||
* up the console on the serial port
|
||||
*/
|
||||
static int __init decserial_console_init(void)
|
||||
{
|
||||
#ifdef CONFIG_ZS
|
||||
if (IOASIC)
|
||||
zs_serial_console_init();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
console_initcall(decserial_console_init);
|
||||
|
||||
#endif
|
||||
|
|
@ -177,8 +177,14 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset,
|
|||
MTRR_TYPE_WRCOMB, 1);
|
||||
}
|
||||
}
|
||||
if (map->type == _DRM_REGISTERS)
|
||||
if (map->type == _DRM_REGISTERS) {
|
||||
map->handle = ioremap(map->offset, map->size);
|
||||
if (!map->handle) {
|
||||
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case _DRM_SHM:
|
||||
list = drm_find_matching_map(dev, map);
|
||||
|
|
@ -479,11 +485,6 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!map) {
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Register and framebuffer maps are permanent */
|
||||
if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) {
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
|
|
|||
|
|
@ -184,6 +184,8 @@ static int i915_initialize(struct drm_device * dev,
|
|||
* private backbuffer/depthbuffer usage.
|
||||
*/
|
||||
dev_priv->use_mi_batchbuffer_start = 0;
|
||||
if (IS_I965G(dev)) /* 965 doesn't support older method */
|
||||
dev_priv->use_mi_batchbuffer_start = 1;
|
||||
|
||||
/* Allow hardware batchbuffers unless told otherwise.
|
||||
*/
|
||||
|
|
@ -517,8 +519,13 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
|
|||
|
||||
if (dev_priv->use_mi_batchbuffer_start) {
|
||||
BEGIN_LP_RING(2);
|
||||
OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
|
||||
OUT_RING(batch->start | MI_BATCH_NON_SECURE);
|
||||
if (IS_I965G(dev)) {
|
||||
OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
|
||||
OUT_RING(batch->start);
|
||||
} else {
|
||||
OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
|
||||
OUT_RING(batch->start | MI_BATCH_NON_SECURE);
|
||||
}
|
||||
ADVANCE_LP_RING();
|
||||
} else {
|
||||
BEGIN_LP_RING(4);
|
||||
|
|
@ -735,7 +742,8 @@ static int i915_setparam(DRM_IOCTL_ARGS)
|
|||
|
||||
switch (param.param) {
|
||||
case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
|
||||
dev_priv->use_mi_batchbuffer_start = param.value;
|
||||
if (!IS_I965G(dev))
|
||||
dev_priv->use_mi_batchbuffer_start = param.value;
|
||||
break;
|
||||
case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
|
||||
dev_priv->tex_lru_log_granularity = param.value;
|
||||
|
|
|
|||
|
|
@ -210,6 +210,12 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
|||
#define I915REG_INT_MASK_R 0x020a8
|
||||
#define I915REG_INT_ENABLE_R 0x020a0
|
||||
|
||||
#define I915REG_PIPEASTAT 0x70024
|
||||
#define I915REG_PIPEBSTAT 0x71024
|
||||
|
||||
#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17)
|
||||
#define I915_VBLANK_CLEAR (1UL<<1)
|
||||
|
||||
#define SRX_INDEX 0x3c4
|
||||
#define SRX_DATA 0x3c5
|
||||
#define SR01 1
|
||||
|
|
@ -282,6 +288,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
|||
#define MI_BATCH_BUFFER_START (0x31<<23)
|
||||
#define MI_BATCH_BUFFER_END (0xA<<23)
|
||||
#define MI_BATCH_NON_SECURE (1)
|
||||
#define MI_BATCH_NON_SECURE_I965 (1<<8)
|
||||
|
||||
#define MI_WAIT_FOR_EVENT ((0x3<<23))
|
||||
#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
|
||||
|
|
|
|||
|
|
@ -214,6 +214,10 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
struct drm_device *dev = (struct drm_device *) arg;
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
u16 temp;
|
||||
u32 pipea_stats, pipeb_stats;
|
||||
|
||||
pipea_stats = I915_READ(I915REG_PIPEASTAT);
|
||||
pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
|
||||
|
||||
temp = I915_READ16(I915REG_INT_IDENTITY_R);
|
||||
|
||||
|
|
@ -225,6 +229,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
return IRQ_NONE;
|
||||
|
||||
I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
|
||||
(void) I915_READ16(I915REG_INT_IDENTITY_R);
|
||||
DRM_READMEMORYBARRIER();
|
||||
|
||||
dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
|
||||
|
||||
|
|
@ -252,6 +258,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
|
||||
if (dev_priv->swaps_pending > 0)
|
||||
drm_locked_tasklet(dev, i915_vblank_tasklet);
|
||||
I915_WRITE(I915REG_PIPEASTAT,
|
||||
pipea_stats|I915_VBLANK_INTERRUPT_ENABLE|
|
||||
I915_VBLANK_CLEAR);
|
||||
I915_WRITE(I915REG_PIPEBSTAT,
|
||||
pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE|
|
||||
I915_VBLANK_CLEAR);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
|
|
|||
|
|
@ -273,10 +273,9 @@ via_alloc_desc_pages(drm_via_sg_info_t *vsg)
|
|||
vsg->num_desc_pages = (vsg->num_desc + vsg->descriptors_per_page - 1) /
|
||||
vsg->descriptors_per_page;
|
||||
|
||||
if (NULL == (vsg->desc_pages = kmalloc(sizeof(void *) * vsg->num_desc_pages, GFP_KERNEL)))
|
||||
if (NULL == (vsg->desc_pages = kcalloc(vsg->num_desc_pages, sizeof(void *), GFP_KERNEL)))
|
||||
return DRM_ERR(ENOMEM);
|
||||
|
||||
memset(vsg->desc_pages, 0, sizeof(void *) * vsg->num_desc_pages);
|
||||
vsg->state = dr_via_desc_pages_alloc;
|
||||
for (i=0; i<vsg->num_desc_pages; ++i) {
|
||||
if (NULL == (vsg->desc_pages[i] =
|
||||
|
|
@ -561,7 +560,7 @@ via_init_dmablit(struct drm_device *dev)
|
|||
blitq->head = 0;
|
||||
blitq->cur = 0;
|
||||
blitq->serviced = 0;
|
||||
blitq->num_free = VIA_NUM_BLIT_SLOTS;
|
||||
blitq->num_free = VIA_NUM_BLIT_SLOTS - 1;
|
||||
blitq->num_outstanding = 0;
|
||||
blitq->is_active = 0;
|
||||
blitq->aborting = 0;
|
||||
|
|
|
|||
|
|
@ -513,7 +513,7 @@ static int __init dsp56k_init_driver(void)
|
|||
err = PTR_ERR(dsp56k_class);
|
||||
goto out_chrdev;
|
||||
}
|
||||
class_device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k");
|
||||
device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), "dsp56k");
|
||||
|
||||
printk(banner);
|
||||
goto out;
|
||||
|
|
@ -527,7 +527,7 @@ module_init(dsp56k_init_driver);
|
|||
|
||||
static void __exit dsp56k_cleanup_driver(void)
|
||||
{
|
||||
class_device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0));
|
||||
device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0));
|
||||
class_destroy(dsp56k_class);
|
||||
unregister_chrdev(DSP56K_MAJOR, "dsp56k");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2459,7 +2459,7 @@ static int __init espserial_init(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
info = kmalloc(sizeof(struct esp_struct), GFP_KERNEL);
|
||||
info = kzalloc(sizeof(struct esp_struct), GFP_KERNEL);
|
||||
|
||||
if (!info)
|
||||
{
|
||||
|
|
@ -2469,7 +2469,6 @@ static int __init espserial_init(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
memset((void *)info, 0, sizeof(struct esp_struct));
|
||||
spin_lock_init(&info->lock);
|
||||
/* rx_trigger, tx_trigger are needed by autoconfig */
|
||||
info->config.rx_trigger = rx_trigger;
|
||||
|
|
@ -2527,7 +2526,7 @@ static int __init espserial_init(void)
|
|||
if (!dma)
|
||||
info->stat_flags |= ESP_STAT_NEVER_DMA;
|
||||
|
||||
info = kmalloc(sizeof(struct esp_struct), GFP_KERNEL);
|
||||
info = kzalloc(sizeof(struct esp_struct), GFP_KERNEL);
|
||||
if (!info)
|
||||
{
|
||||
printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n");
|
||||
|
|
@ -2536,7 +2535,6 @@ static int __init espserial_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
memset((void *)info, 0, sizeof(struct esp_struct));
|
||||
/* rx_trigger, tx_trigger are needed by autoconfig */
|
||||
info->config.rx_trigger = rx_trigger;
|
||||
info->config.tx_trigger = tx_trigger;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include <linux/bcd.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/clocksource.h>
|
||||
|
||||
#include <asm/current.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
|
@ -51,8 +52,37 @@
|
|||
|
||||
#define HPET_RANGE_SIZE 1024 /* from HPET spec */
|
||||
|
||||
#if BITS_PER_LONG == 64
|
||||
#define write_counter(V, MC) writeq(V, MC)
|
||||
#define read_counter(MC) readq(MC)
|
||||
#else
|
||||
#define write_counter(V, MC) writel(V, MC)
|
||||
#define read_counter(MC) readl(MC)
|
||||
#endif
|
||||
|
||||
static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ;
|
||||
|
||||
/* This clocksource driver currently only works on ia64 */
|
||||
#ifdef CONFIG_IA64
|
||||
static void __iomem *hpet_mctr;
|
||||
|
||||
static cycle_t read_hpet(void)
|
||||
{
|
||||
return (cycle_t)read_counter((void __iomem *)hpet_mctr);
|
||||
}
|
||||
|
||||
static struct clocksource clocksource_hpet = {
|
||||
.name = "hpet",
|
||||
.rating = 250,
|
||||
.read = read_hpet,
|
||||
.mask = CLOCKSOURCE_MASK(64),
|
||||
.mult = 0, /*to be caluclated*/
|
||||
.shift = 10,
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
};
|
||||
static struct clocksource *hpet_clocksource;
|
||||
#endif
|
||||
|
||||
/* A lock for concurrent access by app and isr hpet activity. */
|
||||
static DEFINE_SPINLOCK(hpet_lock);
|
||||
/* A lock for concurrent intermodule access to hpet and isr hpet activity. */
|
||||
|
|
@ -79,7 +109,7 @@ struct hpets {
|
|||
struct hpets *hp_next;
|
||||
struct hpet __iomem *hp_hpet;
|
||||
unsigned long hp_hpet_phys;
|
||||
struct time_interpolator *hp_interpolator;
|
||||
struct clocksource *hp_clocksource;
|
||||
unsigned long long hp_tick_freq;
|
||||
unsigned long hp_delta;
|
||||
unsigned int hp_ntimer;
|
||||
|
|
@ -94,13 +124,6 @@ static struct hpets *hpets;
|
|||
#define HPET_PERIODIC 0x0004
|
||||
#define HPET_SHARED_IRQ 0x0008
|
||||
|
||||
#if BITS_PER_LONG == 64
|
||||
#define write_counter(V, MC) writeq(V, MC)
|
||||
#define read_counter(MC) readq(MC)
|
||||
#else
|
||||
#define write_counter(V, MC) writel(V, MC)
|
||||
#define read_counter(MC) readl(MC)
|
||||
#endif
|
||||
|
||||
#ifndef readq
|
||||
static inline unsigned long long readq(void __iomem *addr)
|
||||
|
|
@ -737,27 +760,6 @@ static ctl_table dev_root[] = {
|
|||
|
||||
static struct ctl_table_header *sysctl_header;
|
||||
|
||||
static void hpet_register_interpolator(struct hpets *hpetp)
|
||||
{
|
||||
#ifdef CONFIG_TIME_INTERPOLATION
|
||||
struct time_interpolator *ti;
|
||||
|
||||
ti = kzalloc(sizeof(*ti), GFP_KERNEL);
|
||||
if (!ti)
|
||||
return;
|
||||
|
||||
ti->source = TIME_SOURCE_MMIO64;
|
||||
ti->shift = 10;
|
||||
ti->addr = &hpetp->hp_hpet->hpet_mc;
|
||||
ti->frequency = hpetp->hp_tick_freq;
|
||||
ti->drift = HPET_DRIFT;
|
||||
ti->mask = -1;
|
||||
|
||||
hpetp->hp_interpolator = ti;
|
||||
register_time_interpolator(ti);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjustment for when arming the timer with
|
||||
* initial conditions. That is, main counter
|
||||
|
|
@ -909,7 +911,19 @@ int hpet_alloc(struct hpet_data *hdp)
|
|||
}
|
||||
|
||||
hpetp->hp_delta = hpet_calibrate(hpetp);
|
||||
hpet_register_interpolator(hpetp);
|
||||
|
||||
/* This clocksource driver currently only works on ia64 */
|
||||
#ifdef CONFIG_IA64
|
||||
if (!hpet_clocksource) {
|
||||
hpet_mctr = (void __iomem *)&hpetp->hp_hpet->hpet_mc;
|
||||
CLKSRC_FSYS_MMIO_SET(clocksource_hpet.fsys_mmio, hpet_mctr);
|
||||
clocksource_hpet.mult = clocksource_hz2mult(hpetp->hp_tick_freq,
|
||||
clocksource_hpet.shift);
|
||||
clocksource_register(&clocksource_hpet);
|
||||
hpetp->hp_clocksource = &clocksource_hpet;
|
||||
hpet_clocksource = &clocksource_hpet;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -932,14 +946,14 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
|
|||
printk(KERN_DEBUG "%s: 0x%lx is busy\n",
|
||||
__FUNCTION__, hdp->hd_phys_address);
|
||||
iounmap(hdp->hd_address);
|
||||
return -EBUSY;
|
||||
return AE_ALREADY_EXISTS;
|
||||
}
|
||||
} else if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) {
|
||||
struct acpi_resource_fixed_memory32 *fixmem32;
|
||||
|
||||
fixmem32 = &res->data.fixed_memory32;
|
||||
if (!fixmem32)
|
||||
return -EINVAL;
|
||||
return AE_NO_MEMORY;
|
||||
|
||||
hdp->hd_phys_address = fixmem32->address;
|
||||
hdp->hd_address = ioremap(fixmem32->address,
|
||||
|
|
@ -949,7 +963,7 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
|
|||
printk(KERN_DEBUG "%s: 0x%lx is busy\n",
|
||||
__FUNCTION__, hdp->hd_phys_address);
|
||||
iounmap(hdp->hd_address);
|
||||
return -EBUSY;
|
||||
return AE_ALREADY_EXISTS;
|
||||
}
|
||||
} else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
|
||||
struct acpi_resource_extended_irq *irqp;
|
||||
|
|
@ -995,13 +1009,19 @@ static int hpet_acpi_add(struct acpi_device *device)
|
|||
|
||||
static int hpet_acpi_remove(struct acpi_device *device, int type)
|
||||
{
|
||||
/* XXX need to unregister interpolator, dealloc mem, etc */
|
||||
/* XXX need to unregister clocksource, dealloc mem, etc */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct acpi_device_id hpet_device_ids[] = {
|
||||
{"PNP0103", 0},
|
||||
{"", 0},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, hpet_device_ids);
|
||||
|
||||
static struct acpi_driver hpet_acpi_driver = {
|
||||
.name = "hpet",
|
||||
.ids = "PNP0103",
|
||||
.ids = hpet_device_ids,
|
||||
.ops = {
|
||||
.add = hpet_acpi_add,
|
||||
.remove = hpet_acpi_remove,
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ static int hvc_beat_config(char *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int hvc_beat_console_init(void)
|
||||
static int __init hvc_beat_console_init(void)
|
||||
{
|
||||
if (hvc_beat_useit && machine_is_compatible("Beat")) {
|
||||
hvc_instantiate(0, 0, &hvc_beat_get_put_ops);
|
||||
|
|
@ -106,7 +106,7 @@ static int hvc_beat_console_init(void)
|
|||
}
|
||||
|
||||
/* temp */
|
||||
static int hvc_beat_init(void)
|
||||
static int __init hvc_beat_init(void)
|
||||
{
|
||||
struct hvc_struct *hp;
|
||||
|
||||
|
|
|
|||
|
|
@ -472,7 +472,7 @@ static void hvc_handle_event(struct HvLpEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
static int send_open(HvLpIndex remoteLp, void *sem)
|
||||
static int __init send_open(HvLpIndex remoteLp, void *sem)
|
||||
{
|
||||
return HvCallEvent_signalLpEventFast(remoteLp,
|
||||
HvLpEvent_Type_VirtualIo,
|
||||
|
|
@ -484,7 +484,7 @@ static int send_open(HvLpIndex remoteLp, void *sem)
|
|||
0, 0, 0, 0);
|
||||
}
|
||||
|
||||
static int hvc_vio_init(void)
|
||||
static int __init hvc_vio_init(void)
|
||||
{
|
||||
atomic_t wait_flag;
|
||||
int rc;
|
||||
|
|
@ -552,14 +552,14 @@ static int hvc_vio_init(void)
|
|||
}
|
||||
module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */
|
||||
|
||||
static void hvc_vio_exit(void)
|
||||
static void __exit hvc_vio_exit(void)
|
||||
{
|
||||
vio_unregister_driver(&hvc_vio_driver);
|
||||
}
|
||||
module_exit(hvc_vio_exit);
|
||||
|
||||
/* the device tree order defines our numbering */
|
||||
static int hvc_find_vtys(void)
|
||||
static int __init hvc_find_vtys(void)
|
||||
{
|
||||
struct device_node *vty;
|
||||
int num_found = 0;
|
||||
|
|
|
|||
177
drivers/char/hvc_lguest.c
Normal file
177
drivers/char/hvc_lguest.c
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
/*D:300
|
||||
* The Guest console driver
|
||||
*
|
||||
* This is a trivial console driver: we use lguest's DMA mechanism to send
|
||||
* bytes out, and register a DMA buffer to receive bytes in. It is assumed to
|
||||
* be present and available from the very beginning of boot.
|
||||
*
|
||||
* Writing console drivers is one of the few remaining Dark Arts in Linux.
|
||||
* Fortunately for us, the path of virtual consoles has been well-trodden by
|
||||
* the PowerPC folks, who wrote "hvc_console.c" to generically support any
|
||||
* virtual console. We use that infrastructure which only requires us to write
|
||||
* the basic put_chars and get_chars functions and call the right register
|
||||
* functions.
|
||||
:*/
|
||||
|
||||
/*M:002 The console can be flooded: while the Guest is processing input the
|
||||
* Host can send more. Buffering in the Host could alleviate this, but it is a
|
||||
* difficult problem in general. :*/
|
||||
/* Copyright (C) 2006 Rusty Russell, IBM Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/lguest_bus.h>
|
||||
#include <asm/paravirt.h>
|
||||
#include "hvc_console.h"
|
||||
|
||||
/*D:340 This is our single console input buffer, with associated "struct
|
||||
* lguest_dma" referring to it. Note the 0-terminated length array, and the
|
||||
* use of physical address for the buffer itself. */
|
||||
static char inbuf[256];
|
||||
static struct lguest_dma cons_input = { .used_len = 0,
|
||||
.addr[0] = __pa(inbuf),
|
||||
.len[0] = sizeof(inbuf),
|
||||
.len[1] = 0 };
|
||||
|
||||
/*D:310 The put_chars() callback is pretty straightforward.
|
||||
*
|
||||
* First we put the pointer and length in a "struct lguest_dma": we only have
|
||||
* one pointer, so we set the second length to 0. Then we use SEND_DMA to send
|
||||
* the data to (Host) buffers attached to the console key. Usually a device's
|
||||
* key is a physical address within the device's memory, but because the
|
||||
* console device doesn't have any associated physical memory, we use the
|
||||
* LGUEST_CONSOLE_DMA_KEY constant (aka 0). */
|
||||
static int put_chars(u32 vtermno, const char *buf, int count)
|
||||
{
|
||||
struct lguest_dma dma;
|
||||
|
||||
/* FIXME: DMA buffers in a "struct lguest_dma" are not allowed
|
||||
* to go over page boundaries. This never seems to happen,
|
||||
* but if it did we'd need to fix this code. */
|
||||
dma.len[0] = count;
|
||||
dma.len[1] = 0;
|
||||
dma.addr[0] = __pa(buf);
|
||||
|
||||
lguest_send_dma(LGUEST_CONSOLE_DMA_KEY, &dma);
|
||||
/* We're expected to return the amount of data we wrote: all of it. */
|
||||
return count;
|
||||
}
|
||||
|
||||
/*D:350 get_chars() is the callback from the hvc_console infrastructure when
|
||||
* an interrupt is received.
|
||||
*
|
||||
* Firstly we see if our buffer has been filled: if not, we return. The rest
|
||||
* of the code deals with the fact that the hvc_console() infrastructure only
|
||||
* asks us for 16 bytes at a time. We keep a "cons_offset" variable for
|
||||
* partially-read buffers. */
|
||||
static int get_chars(u32 vtermno, char *buf, int count)
|
||||
{
|
||||
static int cons_offset;
|
||||
|
||||
/* Nothing left to see here... */
|
||||
if (!cons_input.used_len)
|
||||
return 0;
|
||||
|
||||
/* You want more than we have to give? Well, try wanting less! */
|
||||
if (cons_input.used_len - cons_offset < count)
|
||||
count = cons_input.used_len - cons_offset;
|
||||
|
||||
/* Copy across to their buffer and increment offset. */
|
||||
memcpy(buf, inbuf + cons_offset, count);
|
||||
cons_offset += count;
|
||||
|
||||
/* Finished? Zero offset, and reset cons_input so Host will use it
|
||||
* again. */
|
||||
if (cons_offset == cons_input.used_len) {
|
||||
cons_offset = 0;
|
||||
cons_input.used_len = 0;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
/*:*/
|
||||
|
||||
static struct hv_ops lguest_cons = {
|
||||
.get_chars = get_chars,
|
||||
.put_chars = put_chars,
|
||||
};
|
||||
|
||||
/*D:320 Console drivers are initialized very early so boot messages can go
|
||||
* out. At this stage, the console is output-only. Our driver checks we're a
|
||||
* Guest, and if so hands hvc_instantiate() the console number (0), priority
|
||||
* (0), and the struct hv_ops containing the put_chars() function. */
|
||||
static int __init cons_init(void)
|
||||
{
|
||||
if (strcmp(paravirt_ops.name, "lguest") != 0)
|
||||
return 0;
|
||||
|
||||
return hvc_instantiate(0, 0, &lguest_cons);
|
||||
}
|
||||
console_initcall(cons_init);
|
||||
|
||||
/*D:370 To set up and manage our virtual console, we call hvc_alloc() and
|
||||
* stash the result in the private pointer of the "struct lguest_device".
|
||||
* Since we never remove the console device we never need this pointer again,
|
||||
* but using ->private is considered good form, and you never know who's going
|
||||
* to copy your driver.
|
||||
*
|
||||
* Once the console is set up, we bind our input buffer ready for input. */
|
||||
static int lguestcons_probe(struct lguest_device *lgdev)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* The first argument of hvc_alloc() is the virtual console number, so
|
||||
* we use zero. The second argument is the interrupt number.
|
||||
*
|
||||
* The third argument is a "struct hv_ops" containing the put_chars()
|
||||
* and get_chars() pointers. The final argument is the output buffer
|
||||
* size: we use 256 and expect the Host to have room for us to send
|
||||
* that much. */
|
||||
lgdev->private = hvc_alloc(0, lgdev_irq(lgdev), &lguest_cons, 256);
|
||||
if (IS_ERR(lgdev->private))
|
||||
return PTR_ERR(lgdev->private);
|
||||
|
||||
/* We bind a single DMA buffer at key LGUEST_CONSOLE_DMA_KEY.
|
||||
* "cons_input" is that statically-initialized global DMA buffer we saw
|
||||
* above, and we also give the interrupt we want. */
|
||||
err = lguest_bind_dma(LGUEST_CONSOLE_DMA_KEY, &cons_input, 1,
|
||||
lgdev_irq(lgdev));
|
||||
if (err)
|
||||
printk("lguest console: failed to bind buffer.\n");
|
||||
return err;
|
||||
}
|
||||
/* Note the use of lgdev_irq() for the interrupt number. We tell hvc_alloc()
|
||||
* to expect input when this interrupt is triggered, and then tell
|
||||
* lguest_bind_dma() that is the interrupt to send us when input comes in. */
|
||||
|
||||
/*D:360 From now on the console driver follows standard Guest driver form:
|
||||
* register_lguest_driver() registers the device type and probe function, and
|
||||
* the probe function sets up the device.
|
||||
*
|
||||
* The standard "struct lguest_driver": */
|
||||
static struct lguest_driver lguestcons_drv = {
|
||||
.name = "lguestcons",
|
||||
.owner = THIS_MODULE,
|
||||
.device_type = LGUEST_DEVICE_T_CONSOLE,
|
||||
.probe = lguestcons_probe,
|
||||
};
|
||||
|
||||
/* The standard init function */
|
||||
static int __init hvc_lguest_init(void)
|
||||
{
|
||||
return register_lguest_driver(&lguestcons_drv);
|
||||
}
|
||||
module_init(hvc_lguest_init);
|
||||
|
|
@ -115,7 +115,7 @@ static void __exit hvc_rtas_exit(void)
|
|||
module_exit(hvc_rtas_exit);
|
||||
|
||||
/* This will happen prior to module init. There is no tty at this time? */
|
||||
static int hvc_rtas_console_init(void)
|
||||
static int __init hvc_rtas_console_init(void)
|
||||
{
|
||||
rtascons_put_char_token = rtas_token("put-term-char");
|
||||
if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
|
||||
|
|
|
|||
159
drivers/char/hvc_xen.c
Normal file
159
drivers/char/hvc_xen.c
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* xen console driver interface to hvc_console.c
|
||||
*
|
||||
* (c) 2007 Gerd Hoffmann <kraxel@suse.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <asm/xen/hypervisor.h>
|
||||
#include <xen/page.h>
|
||||
#include <xen/events.h>
|
||||
#include <xen/interface/io/console.h>
|
||||
#include <xen/hvc-console.h>
|
||||
|
||||
#include "hvc_console.h"
|
||||
|
||||
#define HVC_COOKIE 0x58656e /* "Xen" in hex */
|
||||
|
||||
static struct hvc_struct *hvc;
|
||||
static int xencons_irq;
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static inline struct xencons_interface *xencons_interface(void)
|
||||
{
|
||||
return mfn_to_virt(xen_start_info->console.domU.mfn);
|
||||
}
|
||||
|
||||
static inline void notify_daemon(void)
|
||||
{
|
||||
/* Use evtchn: this is called early, before irq is set up. */
|
||||
notify_remote_via_evtchn(xen_start_info->console.domU.evtchn);
|
||||
}
|
||||
|
||||
static int write_console(uint32_t vtermno, const char *data, int len)
|
||||
{
|
||||
struct xencons_interface *intf = xencons_interface();
|
||||
XENCONS_RING_IDX cons, prod;
|
||||
int sent = 0;
|
||||
|
||||
cons = intf->out_cons;
|
||||
prod = intf->out_prod;
|
||||
mb(); /* update queue values before going on */
|
||||
BUG_ON((prod - cons) > sizeof(intf->out));
|
||||
|
||||
while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
|
||||
intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
|
||||
|
||||
wmb(); /* write ring before updating pointer */
|
||||
intf->out_prod = prod;
|
||||
|
||||
notify_daemon();
|
||||
return sent;
|
||||
}
|
||||
|
||||
static int read_console(uint32_t vtermno, char *buf, int len)
|
||||
{
|
||||
struct xencons_interface *intf = xencons_interface();
|
||||
XENCONS_RING_IDX cons, prod;
|
||||
int recv = 0;
|
||||
|
||||
cons = intf->in_cons;
|
||||
prod = intf->in_prod;
|
||||
mb(); /* get pointers before reading ring */
|
||||
BUG_ON((prod - cons) > sizeof(intf->in));
|
||||
|
||||
while (cons != prod && recv < len)
|
||||
buf[recv++] = intf->in[MASK_XENCONS_IDX(cons++, intf->in)];
|
||||
|
||||
mb(); /* read ring before consuming */
|
||||
intf->in_cons = cons;
|
||||
|
||||
notify_daemon();
|
||||
return recv;
|
||||
}
|
||||
|
||||
static struct hv_ops hvc_ops = {
|
||||
.get_chars = read_console,
|
||||
.put_chars = write_console,
|
||||
};
|
||||
|
||||
static int __init xen_init(void)
|
||||
{
|
||||
struct hvc_struct *hp;
|
||||
|
||||
if (!is_running_on_xen())
|
||||
return 0;
|
||||
|
||||
xencons_irq = bind_evtchn_to_irq(xen_start_info->console.domU.evtchn);
|
||||
if (xencons_irq < 0)
|
||||
xencons_irq = 0 /* NO_IRQ */;
|
||||
hp = hvc_alloc(HVC_COOKIE, xencons_irq, &hvc_ops, 256);
|
||||
if (IS_ERR(hp))
|
||||
return PTR_ERR(hp);
|
||||
|
||||
hvc = hp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit xen_fini(void)
|
||||
{
|
||||
if (hvc)
|
||||
hvc_remove(hvc);
|
||||
}
|
||||
|
||||
static int xen_cons_init(void)
|
||||
{
|
||||
if (!is_running_on_xen())
|
||||
return 0;
|
||||
|
||||
hvc_instantiate(HVC_COOKIE, 0, &hvc_ops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(xen_init);
|
||||
module_exit(xen_fini);
|
||||
console_initcall(xen_cons_init);
|
||||
|
||||
static void xenboot_write_console(struct console *console, const char *string,
|
||||
unsigned len)
|
||||
{
|
||||
unsigned int linelen, off = 0;
|
||||
const char *pos;
|
||||
|
||||
while (off < len && NULL != (pos = strchr(string+off, '\n'))) {
|
||||
linelen = pos-string+off;
|
||||
if (off + linelen > len)
|
||||
break;
|
||||
write_console(0, string+off, linelen);
|
||||
write_console(0, "\r\n", 2);
|
||||
off += linelen + 1;
|
||||
}
|
||||
if (off < len)
|
||||
write_console(0, string+off, len-off);
|
||||
}
|
||||
|
||||
struct console xenboot_console = {
|
||||
.name = "xenboot",
|
||||
.write = xenboot_write_console,
|
||||
.flags = CON_PRINTBUFFER | CON_BOOT,
|
||||
};
|
||||
|
|
@ -210,9 +210,9 @@ static struct ktermios hvcs_tty_termios = {
|
|||
static int hvcs_parm_num_devs = -1;
|
||||
module_param(hvcs_parm_num_devs, int, 0);
|
||||
|
||||
char hvcs_driver_name[] = "hvcs";
|
||||
char hvcs_device_node[] = "hvcs";
|
||||
char hvcs_driver_string[]
|
||||
static const char hvcs_driver_name[] = "hvcs";
|
||||
static const char hvcs_device_node[] = "hvcs";
|
||||
static const char hvcs_driver_string[]
|
||||
= "IBM hvcs (Hypervisor Virtual Console Server) Driver";
|
||||
|
||||
/* Status of partner info rescan triggered via sysfs. */
|
||||
|
|
@ -784,12 +784,10 @@ static int __devinit hvcs_probe(
|
|||
return -EFAULT;
|
||||
}
|
||||
|
||||
hvcsd = kmalloc(sizeof(*hvcsd), GFP_KERNEL);
|
||||
hvcsd = kzalloc(sizeof(*hvcsd), GFP_KERNEL);
|
||||
if (!hvcsd)
|
||||
return -ENODEV;
|
||||
|
||||
/* hvcsd->tty is zeroed out with the memset */
|
||||
memset(hvcsd, 0x00, sizeof(*hvcsd));
|
||||
|
||||
spin_lock_init(&hvcsd->lock);
|
||||
/* Automatically incs the refcount the first time */
|
||||
|
|
@ -1094,7 +1092,7 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,
|
|||
* NOTICE: Do NOT hold either the hvcs_struct.lock or hvcs_structs_lock when
|
||||
* calling this function or you will get deadlock.
|
||||
*/
|
||||
struct hvcs_struct *hvcs_get_by_index(int index)
|
||||
static struct hvcs_struct *hvcs_get_by_index(int index)
|
||||
{
|
||||
struct hvcs_struct *hvcsd = NULL;
|
||||
unsigned long flags;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ config HW_RANDOM_AMD
|
|||
|
||||
config HW_RANDOM_GEODE
|
||||
tristate "AMD Geode HW Random Number Generator support"
|
||||
depends on HW_RANDOM && X86 && PCI
|
||||
depends on HW_RANDOM && X86_32 && PCI
|
||||
default HW_RANDOM
|
||||
---help---
|
||||
This driver provides kernel-side support for the Random Number
|
||||
|
|
|
|||
|
|
@ -98,9 +98,9 @@ struct smm_regs {
|
|||
unsigned int edi __attribute__ ((packed));
|
||||
};
|
||||
|
||||
static inline char *i8k_get_dmi_data(int field)
|
||||
static inline const char *i8k_get_dmi_data(int field)
|
||||
{
|
||||
char *dmi_data = dmi_get_system_info(field);
|
||||
const char *dmi_data = dmi_get_system_info(field);
|
||||
|
||||
return dmi_data && *dmi_data ? dmi_data : "?";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -411,8 +411,8 @@ cleanup_module(void)
|
|||
iiResetDelay( i2BoardPtrTable[i] );
|
||||
/* free io addresses and Tibet */
|
||||
release_region( ip2config.addr[i], 8 );
|
||||
class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i));
|
||||
class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
|
||||
device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i));
|
||||
device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
|
||||
}
|
||||
/* Disable and remove interrupt handler. */
|
||||
if ( (ip2config.irq[i] > 0) && have_requested_irq(ip2config.irq[i]) ) {
|
||||
|
|
@ -425,9 +425,7 @@ cleanup_module(void)
|
|||
printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err);
|
||||
}
|
||||
put_tty_driver(ip2_tty_driver);
|
||||
if ( ( err = unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) ) {
|
||||
printk(KERN_ERR "IP2: failed to unregister IPL driver (%d)\n", err);
|
||||
}
|
||||
unregister_chrdev(IP2_IPL_MAJOR, pcIpl);
|
||||
remove_proc_entry("ip2mem", &proc_root);
|
||||
|
||||
// free memory
|
||||
|
|
@ -502,7 +500,6 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
|
|||
{
|
||||
int i, j, box;
|
||||
int err = 0;
|
||||
int status = 0;
|
||||
static int loaded;
|
||||
i2eBordStrPtr pB = NULL;
|
||||
int rc = -1;
|
||||
|
|
@ -590,6 +587,8 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
|
|||
case PCI:
|
||||
#ifdef CONFIG_PCI
|
||||
{
|
||||
int status;
|
||||
|
||||
pci_dev_i = pci_get_device(PCI_VENDOR_ID_COMPUTONE,
|
||||
PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i);
|
||||
if (pci_dev_i != NULL) {
|
||||
|
|
@ -719,12 +718,12 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
|
|||
}
|
||||
|
||||
if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
|
||||
class_device_create(ip2_class, NULL,
|
||||
device_create(ip2_class, NULL,
|
||||
MKDEV(IP2_IPL_MAJOR, 4 * i),
|
||||
NULL, "ipl%d", i);
|
||||
class_device_create(ip2_class, NULL,
|
||||
"ipl%d", i);
|
||||
device_create(ip2_class, NULL,
|
||||
MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
|
||||
NULL, "stat%d", i);
|
||||
"stat%d", i);
|
||||
|
||||
for ( box = 0; box < ABS_MAX_BOXES; ++box )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -865,7 +865,7 @@ static void ipmi_new_smi(int if_num, struct device *device)
|
|||
entry->dev = dev;
|
||||
|
||||
mutex_lock(®_list_mutex);
|
||||
class_device_create(ipmi_class, NULL, dev, device, "ipmi%d", if_num);
|
||||
device_create(ipmi_class, device, dev, "ipmi%d", if_num);
|
||||
list_add(&entry->link, ®_list);
|
||||
mutex_unlock(®_list_mutex);
|
||||
}
|
||||
|
|
@ -883,7 +883,7 @@ static void ipmi_smi_gone(int if_num)
|
|||
break;
|
||||
}
|
||||
}
|
||||
class_device_destroy(ipmi_class, dev);
|
||||
device_destroy(ipmi_class, dev);
|
||||
mutex_unlock(®_list_mutex);
|
||||
}
|
||||
|
||||
|
|
@ -938,7 +938,7 @@ static __exit void cleanup_ipmi(void)
|
|||
mutex_lock(®_list_mutex);
|
||||
list_for_each_entry_safe(entry, entry2, ®_list, link) {
|
||||
list_del(&entry->link);
|
||||
class_device_destroy(ipmi_class, entry->dev);
|
||||
device_destroy(ipmi_class, entry->dev);
|
||||
kfree(entry);
|
||||
}
|
||||
mutex_unlock(®_list_mutex);
|
||||
|
|
|
|||
|
|
@ -2639,10 +2639,9 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
intf = kmalloc(sizeof(*intf), GFP_KERNEL);
|
||||
intf = kzalloc(sizeof(*intf), GFP_KERNEL);
|
||||
if (!intf)
|
||||
return -ENOMEM;
|
||||
memset(intf, 0, sizeof(*intf));
|
||||
|
||||
intf->ipmi_version_major = ipmi_version_major(device_id);
|
||||
intf->ipmi_version_minor = ipmi_version_minor(device_id);
|
||||
|
|
|
|||
|
|
@ -1965,10 +1965,10 @@ struct dmi_ipmi_data
|
|||
u8 slave_addr;
|
||||
};
|
||||
|
||||
static int __devinit decode_dmi(struct dmi_header *dm,
|
||||
static int __devinit decode_dmi(const struct dmi_header *dm,
|
||||
struct dmi_ipmi_data *dmi)
|
||||
{
|
||||
u8 *data = (u8 *)dm;
|
||||
const u8 *data = (const u8 *)dm;
|
||||
unsigned long base_addr;
|
||||
u8 reg_spacing;
|
||||
u8 len = dm->length;
|
||||
|
|
@ -2050,6 +2050,7 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data)
|
|||
info->si_type = SI_BT;
|
||||
break;
|
||||
default:
|
||||
kfree(info);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2090,13 +2091,14 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data)
|
|||
|
||||
static void __devinit dmi_find_bmc(void)
|
||||
{
|
||||
struct dmi_device *dev = NULL;
|
||||
const struct dmi_device *dev = NULL;
|
||||
struct dmi_ipmi_data data;
|
||||
int rv;
|
||||
|
||||
while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) {
|
||||
memset(&data, 0, sizeof(data));
|
||||
rv = decode_dmi((struct dmi_header *) dev->device_data, &data);
|
||||
rv = decode_dmi((const struct dmi_header *) dev->device_data,
|
||||
&data);
|
||||
if (!rv)
|
||||
try_init_dmi(&data);
|
||||
}
|
||||
|
|
@ -2214,7 +2216,8 @@ static int ipmi_pci_resume(struct pci_dev *pdev)
|
|||
|
||||
static struct pci_device_id ipmi_pci_devices[] = {
|
||||
{ PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) },
|
||||
{ PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) }
|
||||
{ PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) },
|
||||
{ 0, }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, ipmi_pci_devices);
|
||||
|
||||
|
|
@ -2250,19 +2253,19 @@ static int __devinit ipmi_of_probe(struct of_device *dev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
regsize = get_property(np, "reg-size", &proplen);
|
||||
regsize = of_get_property(np, "reg-size", &proplen);
|
||||
if (regsize && proplen != 4) {
|
||||
dev_warn(&dev->dev, PFX "invalid regsize from OF\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
regspacing = get_property(np, "reg-spacing", &proplen);
|
||||
regspacing = of_get_property(np, "reg-spacing", &proplen);
|
||||
if (regspacing && proplen != 4) {
|
||||
dev_warn(&dev->dev, PFX "invalid regspacing from OF\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
regshift = get_property(np, "reg-shift", &proplen);
|
||||
regshift = of_get_property(np, "reg-shift", &proplen);
|
||||
if (regshift && proplen != 4) {
|
||||
dev_warn(&dev->dev, PFX "invalid regshift from OF\n");
|
||||
return -EINVAL;
|
||||
|
|
@ -2291,7 +2294,7 @@ static int __devinit ipmi_of_probe(struct of_device *dev,
|
|||
info->irq = irq_of_parse_and_map(dev->node, 0);
|
||||
info->dev = &dev->dev;
|
||||
|
||||
dev_dbg(&dev->dev, "addr 0x%lx regsize %ld spacing %ld irq %x\n",
|
||||
dev_dbg(&dev->dev, "addr 0x%lx regsize %d spacing %d irq %x\n",
|
||||
info->io.addr_data, info->io.regsize, info->io.regspacing,
|
||||
info->irq);
|
||||
|
||||
|
|
|
|||
|
|
@ -4624,9 +4624,8 @@ static int __init istallion_module_init(void)
|
|||
|
||||
istallion_class = class_create(THIS_MODULE, "staliomem");
|
||||
for (i = 0; i < 4; i++)
|
||||
class_device_create(istallion_class, NULL,
|
||||
MKDEV(STL_SIOMEMMAJOR, i),
|
||||
NULL, "staliomem%d", i);
|
||||
device_create(istallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
|
||||
"staliomem%d", i);
|
||||
|
||||
return 0;
|
||||
err_deinit:
|
||||
|
|
@ -4659,8 +4658,7 @@ static void __exit istallion_module_exit(void)
|
|||
unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
|
||||
|
||||
for (j = 0; j < 4; j++)
|
||||
class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR,
|
||||
j));
|
||||
device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, j));
|
||||
class_destroy(istallion_class);
|
||||
|
||||
pci_unregister_driver(&stli_pcidriver);
|
||||
|
|
|
|||
|
|
@ -1022,10 +1022,6 @@ static const unsigned short x86_keycodes[256] =
|
|||
308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330,
|
||||
332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 };
|
||||
|
||||
#ifdef CONFIG_MAC_EMUMOUSEBTN
|
||||
extern int mac_hid_mouse_emulate_buttons(int, int, int);
|
||||
#endif /* CONFIG_MAC_EMUMOUSEBTN */
|
||||
|
||||
#ifdef CONFIG_SPARC
|
||||
static int sparc_l1_a_state = 0;
|
||||
extern void sun_do_break(void);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#include <asm/io.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/system.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "lcd.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -799,8 +799,7 @@ static int lp_register(int nr, struct parport *port)
|
|||
if (reset)
|
||||
lp_reset(nr);
|
||||
|
||||
class_device_create(lp_class, NULL, MKDEV(LP_MAJOR, nr), port->dev,
|
||||
"lp%d", nr);
|
||||
device_create(lp_class, port->dev, MKDEV(LP_MAJOR, nr), "lp%d", nr);
|
||||
|
||||
printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name,
|
||||
(port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven");
|
||||
|
|
@ -971,7 +970,7 @@ static void lp_cleanup_module (void)
|
|||
if (lp_table[offset].dev == NULL)
|
||||
continue;
|
||||
parport_unregister_device(lp_table[offset].dev);
|
||||
class_device_destroy(lp_class, MKDEV(LP_MAJOR, offset));
|
||||
device_destroy(lp_class, MKDEV(LP_MAJOR, offset));
|
||||
}
|
||||
class_destroy(lp_class);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,14 +39,14 @@
|
|||
#else
|
||||
#define DBG(fmt...)
|
||||
#endif
|
||||
int mbcs_major;
|
||||
static int mbcs_major;
|
||||
|
||||
LIST_HEAD(soft_list);
|
||||
static LIST_HEAD(soft_list);
|
||||
|
||||
/*
|
||||
* file operations
|
||||
*/
|
||||
const struct file_operations mbcs_ops = {
|
||||
static const struct file_operations mbcs_ops = {
|
||||
.open = mbcs_open,
|
||||
.llseek = mbcs_sram_llseek,
|
||||
.read = mbcs_sram_read,
|
||||
|
|
@ -377,7 +377,7 @@ dmaread_exit:
|
|||
return rv;
|
||||
}
|
||||
|
||||
int mbcs_open(struct inode *ip, struct file *fp)
|
||||
static int mbcs_open(struct inode *ip, struct file *fp)
|
||||
{
|
||||
struct mbcs_soft *soft;
|
||||
int minor;
|
||||
|
|
@ -394,7 +394,7 @@ int mbcs_open(struct inode *ip, struct file *fp)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
ssize_t mbcs_sram_read(struct file * fp, char __user *buf, size_t len, loff_t * off)
|
||||
static ssize_t mbcs_sram_read(struct file * fp, char __user *buf, size_t len, loff_t * off)
|
||||
{
|
||||
struct cx_dev *cx_dev = fp->private_data;
|
||||
struct mbcs_soft *soft = cx_dev->soft;
|
||||
|
|
@ -418,7 +418,7 @@ ssize_t mbcs_sram_read(struct file * fp, char __user *buf, size_t len, loff_t *
|
|||
return rv;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
static ssize_t
|
||||
mbcs_sram_write(struct file * fp, const char __user *buf, size_t len, loff_t * off)
|
||||
{
|
||||
struct cx_dev *cx_dev = fp->private_data;
|
||||
|
|
@ -443,7 +443,7 @@ mbcs_sram_write(struct file * fp, const char __user *buf, size_t len, loff_t * o
|
|||
return rv;
|
||||
}
|
||||
|
||||
loff_t mbcs_sram_llseek(struct file * filp, loff_t off, int whence)
|
||||
static loff_t mbcs_sram_llseek(struct file * filp, loff_t off, int whence)
|
||||
{
|
||||
loff_t newpos;
|
||||
|
||||
|
|
@ -491,7 +491,7 @@ static void mbcs_gscr_pioaddr_set(struct mbcs_soft *soft)
|
|||
soft->gscr_addr = mbcs_pioaddr(soft, MBCS_GSCR_START);
|
||||
}
|
||||
|
||||
int mbcs_gscr_mmap(struct file *fp, struct vm_area_struct *vma)
|
||||
static int mbcs_gscr_mmap(struct file *fp, struct vm_area_struct *vma)
|
||||
{
|
||||
struct cx_dev *cx_dev = fp->private_data;
|
||||
struct mbcs_soft *soft = cx_dev->soft;
|
||||
|
|
@ -793,7 +793,7 @@ static int mbcs_remove(struct cx_dev *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const struct cx_device_id __devinitdata mbcs_id_table[] = {
|
||||
static const struct cx_device_id __devinitdata mbcs_id_table[] = {
|
||||
{
|
||||
.part_num = MBCS_PART_NUM,
|
||||
.mfg_num = MBCS_MFG_NUM,
|
||||
|
|
@ -807,7 +807,7 @@ const struct cx_device_id __devinitdata mbcs_id_table[] = {
|
|||
|
||||
MODULE_DEVICE_TABLE(cx, mbcs_id_table);
|
||||
|
||||
struct cx_drv mbcs_driver = {
|
||||
static struct cx_drv mbcs_driver = {
|
||||
.name = DEVICE_NAME,
|
||||
.id_table = mbcs_id_table,
|
||||
.probe = mbcs_probe,
|
||||
|
|
@ -816,12 +816,7 @@ struct cx_drv mbcs_driver = {
|
|||
|
||||
static void __exit mbcs_exit(void)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = unregister_chrdev(mbcs_major, DEVICE_NAME);
|
||||
if (rv < 0)
|
||||
DBG(KERN_ALERT "Error in unregister_chrdev: %d\n", rv);
|
||||
|
||||
unregister_chrdev(mbcs_major, DEVICE_NAME);
|
||||
cx_driver_unregister(&mbcs_driver);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -542,12 +542,12 @@ struct mbcs_soft {
|
|||
struct semaphore algolock;
|
||||
};
|
||||
|
||||
extern int mbcs_open(struct inode *ip, struct file *fp);
|
||||
extern ssize_t mbcs_sram_read(struct file *fp, char __user *buf, size_t len,
|
||||
static int mbcs_open(struct inode *ip, struct file *fp);
|
||||
static ssize_t mbcs_sram_read(struct file *fp, char __user *buf, size_t len,
|
||||
loff_t * off);
|
||||
extern ssize_t mbcs_sram_write(struct file *fp, const char __user *buf, size_t len,
|
||||
static ssize_t mbcs_sram_write(struct file *fp, const char __user *buf, size_t len,
|
||||
loff_t * off);
|
||||
extern loff_t mbcs_sram_llseek(struct file *filp, loff_t off, int whence);
|
||||
extern int mbcs_gscr_mmap(struct file *fp, struct vm_area_struct *vma);
|
||||
static loff_t mbcs_sram_llseek(struct file *filp, loff_t off, int whence);
|
||||
static int mbcs_gscr_mmap(struct file *fp, struct vm_area_struct *vma);
|
||||
|
||||
#endif // __MBCS_H__
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mmtimer.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/posix-timers.h>
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include <linux/miscdevice.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
|
|
@ -66,7 +67,7 @@
|
|||
/*
|
||||
* Page types allocated by the device.
|
||||
*/
|
||||
enum {
|
||||
enum mspec_page_type {
|
||||
MSPEC_FETCHOP = 1,
|
||||
MSPEC_CACHED,
|
||||
MSPEC_UNCACHED
|
||||
|
|
@ -82,15 +83,25 @@ static int is_sn2;
|
|||
* One of these structures is allocated when an mspec region is mmaped. The
|
||||
* structure is pointed to by the vma->vm_private_data field in the vma struct.
|
||||
* This structure is used to record the addresses of the mspec pages.
|
||||
* This structure is shared by all vma's that are split off from the
|
||||
* original vma when split_vma()'s are done.
|
||||
*
|
||||
* The refcnt is incremented atomically because mm->mmap_sem does not
|
||||
* protect in fork case where multiple tasks share the vma_data.
|
||||
*/
|
||||
struct vma_data {
|
||||
atomic_t refcnt; /* Number of vmas sharing the data. */
|
||||
spinlock_t lock; /* Serialize access to the vma. */
|
||||
spinlock_t lock; /* Serialize access to this structure. */
|
||||
int count; /* Number of pages allocated. */
|
||||
int type; /* Type of pages allocated. */
|
||||
enum mspec_page_type type; /* Type of pages allocated. */
|
||||
int flags; /* See VMD_xxx below. */
|
||||
unsigned long vm_start; /* Original (unsplit) base. */
|
||||
unsigned long vm_end; /* Original (unsplit) end. */
|
||||
unsigned long maddr[0]; /* Array of MSPEC addresses. */
|
||||
};
|
||||
|
||||
#define VMD_VMALLOCED 0x1 /* vmalloc'd rather than kmalloc'd */
|
||||
|
||||
/* used on shub2 to clear FOP cache in the HUB */
|
||||
static unsigned long scratch_page[MAX_NUMNODES];
|
||||
#define SH2_AMO_CACHE_ENTRIES 4
|
||||
|
|
@ -128,8 +139,8 @@ mspec_zero_block(unsigned long addr, int len)
|
|||
* mspec_open
|
||||
*
|
||||
* Called when a device mapping is created by a means other than mmap
|
||||
* (via fork, etc.). Increments the reference count on the underlying
|
||||
* mspec data so it is not freed prematurely.
|
||||
* (via fork, munmap, etc.). Increments the reference count on the
|
||||
* underlying mspec data so it is not freed prematurely.
|
||||
*/
|
||||
static void
|
||||
mspec_open(struct vm_area_struct *vma)
|
||||
|
|
@ -144,43 +155,43 @@ mspec_open(struct vm_area_struct *vma)
|
|||
* mspec_close
|
||||
*
|
||||
* Called when unmapping a device mapping. Frees all mspec pages
|
||||
* belonging to the vma.
|
||||
* belonging to all the vma's sharing this vma_data structure.
|
||||
*/
|
||||
static void
|
||||
mspec_close(struct vm_area_struct *vma)
|
||||
{
|
||||
struct vma_data *vdata;
|
||||
int i, pages, result, vdata_size;
|
||||
int index, last_index;
|
||||
unsigned long my_page;
|
||||
|
||||
vdata = vma->vm_private_data;
|
||||
|
||||
if (!atomic_dec_and_test(&vdata->refcnt))
|
||||
return;
|
||||
|
||||
pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
|
||||
vdata_size = sizeof(struct vma_data) + pages * sizeof(long);
|
||||
for (i = 0; i < pages; i++) {
|
||||
if (vdata->maddr[i] == 0)
|
||||
last_index = (vdata->vm_end - vdata->vm_start) >> PAGE_SHIFT;
|
||||
for (index = 0; index < last_index; index++) {
|
||||
if (vdata->maddr[index] == 0)
|
||||
continue;
|
||||
/*
|
||||
* Clear the page before sticking it back
|
||||
* into the pool.
|
||||
*/
|
||||
result = mspec_zero_block(vdata->maddr[i], PAGE_SIZE);
|
||||
if (!result)
|
||||
uncached_free_page(vdata->maddr[i]);
|
||||
my_page = vdata->maddr[index];
|
||||
vdata->maddr[index] = 0;
|
||||
if (!mspec_zero_block(my_page, PAGE_SIZE))
|
||||
uncached_free_page(my_page);
|
||||
else
|
||||
printk(KERN_WARNING "mspec_close(): "
|
||||
"failed to zero page %i\n",
|
||||
result);
|
||||
"failed to zero page %ld\n", my_page);
|
||||
}
|
||||
|
||||
if (vdata_size <= PAGE_SIZE)
|
||||
kfree(vdata);
|
||||
else
|
||||
if (vdata->flags & VMD_VMALLOCED)
|
||||
vfree(vdata);
|
||||
else
|
||||
kfree(vdata);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* mspec_nopfn
|
||||
*
|
||||
|
|
@ -194,7 +205,8 @@ mspec_nopfn(struct vm_area_struct *vma, unsigned long address)
|
|||
int index;
|
||||
struct vma_data *vdata = vma->vm_private_data;
|
||||
|
||||
index = (address - vma->vm_start) >> PAGE_SHIFT;
|
||||
BUG_ON(address < vdata->vm_start || address >= vdata->vm_end);
|
||||
index = (address - vdata->vm_start) >> PAGE_SHIFT;
|
||||
maddr = (volatile unsigned long) vdata->maddr[index];
|
||||
if (maddr == 0) {
|
||||
maddr = uncached_alloc_page(numa_node_id());
|
||||
|
|
@ -236,10 +248,11 @@ static struct vm_operations_struct mspec_vm_ops = {
|
|||
* underlying pages.
|
||||
*/
|
||||
static int
|
||||
mspec_mmap(struct file *file, struct vm_area_struct *vma, int type)
|
||||
mspec_mmap(struct file *file, struct vm_area_struct *vma,
|
||||
enum mspec_page_type type)
|
||||
{
|
||||
struct vma_data *vdata;
|
||||
int pages, vdata_size;
|
||||
int pages, vdata_size, flags = 0;
|
||||
|
||||
if (vma->vm_pgoff != 0)
|
||||
return -EINVAL;
|
||||
|
|
@ -254,12 +267,17 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma, int type)
|
|||
vdata_size = sizeof(struct vma_data) + pages * sizeof(long);
|
||||
if (vdata_size <= PAGE_SIZE)
|
||||
vdata = kmalloc(vdata_size, GFP_KERNEL);
|
||||
else
|
||||
else {
|
||||
vdata = vmalloc(vdata_size);
|
||||
flags = VMD_VMALLOCED;
|
||||
}
|
||||
if (!vdata)
|
||||
return -ENOMEM;
|
||||
memset(vdata, 0, vdata_size);
|
||||
|
||||
vdata->vm_start = vma->vm_start;
|
||||
vdata->vm_end = vma->vm_end;
|
||||
vdata->flags = flags;
|
||||
vdata->type = type;
|
||||
spin_lock_init(&vdata->lock);
|
||||
vdata->refcnt = ATOMIC_INIT(1);
|
||||
|
|
|
|||
|
|
@ -1629,7 +1629,7 @@ static int cmm_open(struct inode *inode, struct file *filp)
|
|||
{
|
||||
struct cm4000_dev *dev;
|
||||
struct pcmcia_device *link;
|
||||
int rc, minor = iminor(inode);
|
||||
int minor = iminor(inode);
|
||||
|
||||
if (minor >= CM4000_MAX_DEV)
|
||||
return -ENODEV;
|
||||
|
|
@ -1668,7 +1668,6 @@ static int cmm_open(struct inode *inode, struct file *filp)
|
|||
start_monitor(dev);
|
||||
|
||||
link->open = 1; /* only one open per device */
|
||||
rc = 0;
|
||||
|
||||
DEBUGP(2, dev, "<- cmm_open\n");
|
||||
return nonseekable_open(inode, filp);
|
||||
|
|
@ -1824,7 +1823,7 @@ static int cm4000_resume(struct pcmcia_device *link)
|
|||
|
||||
static void cm4000_release(struct pcmcia_device *link)
|
||||
{
|
||||
cmm_cm4000_release(link->priv); /* delay release until device closed */
|
||||
cmm_cm4000_release(link); /* delay release until device closed */
|
||||
pcmcia_disable_device(link);
|
||||
}
|
||||
|
||||
|
|
@ -1864,8 +1863,7 @@ static int cm4000_probe(struct pcmcia_device *link)
|
|||
return ret;
|
||||
}
|
||||
|
||||
class_device_create(cmm_class, NULL, MKDEV(major, i), NULL,
|
||||
"cmm%d", i);
|
||||
device_create(cmm_class, NULL, MKDEV(major, i), "cmm%d", i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1889,7 +1887,7 @@ static void cm4000_detach(struct pcmcia_device *link)
|
|||
dev_table[devno] = NULL;
|
||||
kfree(dev);
|
||||
|
||||
class_device_destroy(cmm_class, MKDEV(major, devno));
|
||||
device_destroy(cmm_class, MKDEV(major, devno));
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -599,7 +599,7 @@ cs_release:
|
|||
|
||||
static void reader_release(struct pcmcia_device *link)
|
||||
{
|
||||
cm4040_reader_release(link->priv);
|
||||
cm4040_reader_release(link);
|
||||
pcmcia_disable_device(link);
|
||||
}
|
||||
|
||||
|
|
@ -642,8 +642,7 @@ static int reader_probe(struct pcmcia_device *link)
|
|||
return ret;
|
||||
}
|
||||
|
||||
class_device_create(cmx_class, NULL, MKDEV(major, i), NULL,
|
||||
"cmx%d", i);
|
||||
device_create(cmx_class, NULL, MKDEV(major, i), "cmx%d", i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -666,7 +665,7 @@ static void reader_detach(struct pcmcia_device *link)
|
|||
dev_table[devno] = NULL;
|
||||
kfree(dev);
|
||||
|
||||
class_device_destroy(cmx_class, MKDEV(major, devno));
|
||||
device_destroy(cmx_class, MKDEV(major, devno));
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -540,13 +540,12 @@ static int mgslpc_probe(struct pcmcia_device *link)
|
|||
if (debug_level >= DEBUG_LEVEL_INFO)
|
||||
printk("mgslpc_attach\n");
|
||||
|
||||
info = kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL);
|
||||
info = kzalloc(sizeof(MGSLPC_INFO), GFP_KERNEL);
|
||||
if (!info) {
|
||||
printk("Error can't allocate device instance data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(info, 0, sizeof(MGSLPC_INFO));
|
||||
info->magic = MGSLPC_MAGIC;
|
||||
INIT_WORK(&info->task, bh_handler);
|
||||
info->max_frame_size = 4096;
|
||||
|
|
|
|||
440
drivers/char/ps3flash.c
Normal file
440
drivers/char/ps3flash.c
Normal file
|
|
@ -0,0 +1,440 @@
|
|||
/*
|
||||
* PS3 FLASH ROM Storage Driver
|
||||
*
|
||||
* Copyright (C) 2007 Sony Computer Entertainment Inc.
|
||||
* Copyright 2007 Sony Corp.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <asm/lv1call.h>
|
||||
#include <asm/ps3stor.h>
|
||||
|
||||
|
||||
#define DEVICE_NAME "ps3flash"
|
||||
|
||||
#define FLASH_BLOCK_SIZE (256*1024)
|
||||
|
||||
|
||||
struct ps3flash_private {
|
||||
struct mutex mutex; /* Bounce buffer mutex */
|
||||
};
|
||||
|
||||
static struct ps3_storage_device *ps3flash_dev;
|
||||
|
||||
static ssize_t ps3flash_read_write_sectors(struct ps3_storage_device *dev,
|
||||
u64 lpar, u64 start_sector,
|
||||
u64 sectors, int write)
|
||||
{
|
||||
u64 res = ps3stor_read_write_sectors(dev, lpar, start_sector, sectors,
|
||||
write);
|
||||
if (res) {
|
||||
dev_err(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__,
|
||||
__LINE__, write ? "write" : "read", res);
|
||||
return -EIO;
|
||||
}
|
||||
return sectors;
|
||||
}
|
||||
|
||||
static ssize_t ps3flash_read_sectors(struct ps3_storage_device *dev,
|
||||
u64 start_sector, u64 sectors,
|
||||
unsigned int sector_offset)
|
||||
{
|
||||
u64 max_sectors, lpar;
|
||||
|
||||
max_sectors = dev->bounce_size / dev->blk_size;
|
||||
if (sectors > max_sectors) {
|
||||
dev_dbg(&dev->sbd.core, "%s:%u Limiting sectors to %lu\n",
|
||||
__func__, __LINE__, max_sectors);
|
||||
sectors = max_sectors;
|
||||
}
|
||||
|
||||
lpar = dev->bounce_lpar + sector_offset * dev->blk_size;
|
||||
return ps3flash_read_write_sectors(dev, lpar, start_sector, sectors,
|
||||
0);
|
||||
}
|
||||
|
||||
static ssize_t ps3flash_write_chunk(struct ps3_storage_device *dev,
|
||||
u64 start_sector)
|
||||
{
|
||||
u64 sectors = dev->bounce_size / dev->blk_size;
|
||||
return ps3flash_read_write_sectors(dev, dev->bounce_lpar, start_sector,
|
||||
sectors, 1);
|
||||
}
|
||||
|
||||
static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin)
|
||||
{
|
||||
struct ps3_storage_device *dev = ps3flash_dev;
|
||||
loff_t res;
|
||||
|
||||
mutex_lock(&file->f_mapping->host->i_mutex);
|
||||
switch (origin) {
|
||||
case 1:
|
||||
offset += file->f_pos;
|
||||
break;
|
||||
case 2:
|
||||
offset += dev->regions[dev->region_idx].size*dev->blk_size;
|
||||
break;
|
||||
}
|
||||
if (offset < 0) {
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
file->f_pos = offset;
|
||||
res = file->f_pos;
|
||||
|
||||
out:
|
||||
mutex_unlock(&file->f_mapping->host->i_mutex);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t ps3flash_read(struct file *file, char __user *buf, size_t count,
|
||||
loff_t *pos)
|
||||
{
|
||||
struct ps3_storage_device *dev = ps3flash_dev;
|
||||
struct ps3flash_private *priv = dev->sbd.core.driver_data;
|
||||
u64 size, start_sector, end_sector, offset;
|
||||
ssize_t sectors_read;
|
||||
size_t remaining, n;
|
||||
|
||||
dev_dbg(&dev->sbd.core,
|
||||
"%s:%u: Reading %zu bytes at position %lld to user 0x%p\n",
|
||||
__func__, __LINE__, count, *pos, buf);
|
||||
|
||||
size = dev->regions[dev->region_idx].size*dev->blk_size;
|
||||
if (*pos >= size || !count)
|
||||
return 0;
|
||||
|
||||
if (*pos + count > size) {
|
||||
dev_dbg(&dev->sbd.core,
|
||||
"%s:%u Truncating count from %zu to %llu\n", __func__,
|
||||
__LINE__, count, size - *pos);
|
||||
count = size - *pos;
|
||||
}
|
||||
|
||||
start_sector = *pos / dev->blk_size;
|
||||
offset = *pos % dev->blk_size;
|
||||
end_sector = DIV_ROUND_UP(*pos + count, dev->blk_size);
|
||||
|
||||
remaining = count;
|
||||
do {
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
sectors_read = ps3flash_read_sectors(dev, start_sector,
|
||||
end_sector-start_sector,
|
||||
0);
|
||||
if (sectors_read < 0) {
|
||||
mutex_unlock(&priv->mutex);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
n = min(remaining, sectors_read*dev->blk_size-offset);
|
||||
dev_dbg(&dev->sbd.core,
|
||||
"%s:%u: copy %lu bytes from 0x%p to user 0x%p\n",
|
||||
__func__, __LINE__, n, dev->bounce_buf+offset, buf);
|
||||
if (copy_to_user(buf, dev->bounce_buf+offset, n)) {
|
||||
mutex_unlock(&priv->mutex);
|
||||
sectors_read = -EFAULT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
*pos += n;
|
||||
buf += n;
|
||||
remaining -= n;
|
||||
start_sector += sectors_read;
|
||||
offset = 0;
|
||||
} while (remaining > 0);
|
||||
|
||||
return count;
|
||||
|
||||
fail:
|
||||
return sectors_read;
|
||||
}
|
||||
|
||||
static ssize_t ps3flash_write(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
struct ps3_storage_device *dev = ps3flash_dev;
|
||||
struct ps3flash_private *priv = dev->sbd.core.driver_data;
|
||||
u64 size, chunk_sectors, start_write_sector, end_write_sector,
|
||||
end_read_sector, start_read_sector, head, tail, offset;
|
||||
ssize_t res;
|
||||
size_t remaining, n;
|
||||
unsigned int sec_off;
|
||||
|
||||
dev_dbg(&dev->sbd.core,
|
||||
"%s:%u: Writing %zu bytes at position %lld from user 0x%p\n",
|
||||
__func__, __LINE__, count, *pos, buf);
|
||||
|
||||
size = dev->regions[dev->region_idx].size*dev->blk_size;
|
||||
if (*pos >= size || !count)
|
||||
return 0;
|
||||
|
||||
if (*pos + count > size) {
|
||||
dev_dbg(&dev->sbd.core,
|
||||
"%s:%u Truncating count from %zu to %llu\n", __func__,
|
||||
__LINE__, count, size - *pos);
|
||||
count = size - *pos;
|
||||
}
|
||||
|
||||
chunk_sectors = dev->bounce_size / dev->blk_size;
|
||||
|
||||
start_write_sector = *pos / dev->bounce_size * chunk_sectors;
|
||||
offset = *pos % dev->bounce_size;
|
||||
end_write_sector = DIV_ROUND_UP(*pos + count, dev->bounce_size) *
|
||||
chunk_sectors;
|
||||
|
||||
end_read_sector = DIV_ROUND_UP(*pos, dev->blk_size);
|
||||
start_read_sector = (*pos + count) / dev->blk_size;
|
||||
|
||||
/*
|
||||
* As we have to write in 256 KiB chunks, while we can read in blk_size
|
||||
* (usually 512 bytes) chunks, we perform the following steps:
|
||||
* 1. Read from start_write_sector to end_read_sector ("head")
|
||||
* 2. Read from start_read_sector to end_write_sector ("tail")
|
||||
* 3. Copy data to buffer
|
||||
* 4. Write from start_write_sector to end_write_sector
|
||||
* All of this is complicated by using only one 256 KiB bounce buffer.
|
||||
*/
|
||||
|
||||
head = end_read_sector - start_write_sector;
|
||||
tail = end_write_sector - start_read_sector;
|
||||
|
||||
remaining = count;
|
||||
do {
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (end_read_sector >= start_read_sector) {
|
||||
/* Merge head and tail */
|
||||
dev_dbg(&dev->sbd.core,
|
||||
"Merged head and tail: %lu sectors at %lu\n",
|
||||
chunk_sectors, start_write_sector);
|
||||
res = ps3flash_read_sectors(dev, start_write_sector,
|
||||
chunk_sectors, 0);
|
||||
if (res < 0)
|
||||
goto fail;
|
||||
} else {
|
||||
if (head) {
|
||||
/* Read head */
|
||||
dev_dbg(&dev->sbd.core,
|
||||
"head: %lu sectors at %lu\n", head,
|
||||
start_write_sector);
|
||||
res = ps3flash_read_sectors(dev,
|
||||
start_write_sector,
|
||||
head, 0);
|
||||
if (res < 0)
|
||||
goto fail;
|
||||
}
|
||||
if (start_read_sector <
|
||||
start_write_sector+chunk_sectors) {
|
||||
/* Read tail */
|
||||
dev_dbg(&dev->sbd.core,
|
||||
"tail: %lu sectors at %lu\n", tail,
|
||||
start_read_sector);
|
||||
sec_off = start_read_sector-start_write_sector;
|
||||
res = ps3flash_read_sectors(dev,
|
||||
start_read_sector,
|
||||
tail, sec_off);
|
||||
if (res < 0)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
n = min(remaining, dev->bounce_size-offset);
|
||||
dev_dbg(&dev->sbd.core,
|
||||
"%s:%u: copy %lu bytes from user 0x%p to 0x%p\n",
|
||||
__func__, __LINE__, n, buf, dev->bounce_buf+offset);
|
||||
if (copy_from_user(dev->bounce_buf+offset, buf, n)) {
|
||||
res = -EFAULT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
res = ps3flash_write_chunk(dev, start_write_sector);
|
||||
if (res < 0)
|
||||
goto fail;
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
*pos += n;
|
||||
buf += n;
|
||||
remaining -= n;
|
||||
start_write_sector += chunk_sectors;
|
||||
head = 0;
|
||||
offset = 0;
|
||||
} while (remaining > 0);
|
||||
|
||||
return count;
|
||||
|
||||
fail:
|
||||
mutex_unlock(&priv->mutex);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static irqreturn_t ps3flash_interrupt(int irq, void *data)
|
||||
{
|
||||
struct ps3_storage_device *dev = data;
|
||||
int res;
|
||||
u64 tag, status;
|
||||
|
||||
res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
|
||||
|
||||
if (tag != dev->tag)
|
||||
dev_err(&dev->sbd.core,
|
||||
"%s:%u: tag mismatch, got %lx, expected %lx\n",
|
||||
__func__, __LINE__, tag, dev->tag);
|
||||
|
||||
if (res) {
|
||||
dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%lx\n",
|
||||
__func__, __LINE__, res, status);
|
||||
} else {
|
||||
dev->lv1_status = status;
|
||||
complete(&dev->done);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
static const struct file_operations ps3flash_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = ps3flash_llseek,
|
||||
.read = ps3flash_read,
|
||||
.write = ps3flash_write,
|
||||
};
|
||||
|
||||
static struct miscdevice ps3flash_misc = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = DEVICE_NAME,
|
||||
.fops = &ps3flash_fops,
|
||||
};
|
||||
|
||||
static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev)
|
||||
{
|
||||
struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
|
||||
struct ps3flash_private *priv;
|
||||
int error;
|
||||
unsigned long tmp;
|
||||
|
||||
tmp = dev->regions[dev->region_idx].start*dev->blk_size;
|
||||
if (tmp % FLASH_BLOCK_SIZE) {
|
||||
dev_err(&dev->sbd.core,
|
||||
"%s:%u region start %lu is not aligned\n", __func__,
|
||||
__LINE__, tmp);
|
||||
return -EINVAL;
|
||||
}
|
||||
tmp = dev->regions[dev->region_idx].size*dev->blk_size;
|
||||
if (tmp % FLASH_BLOCK_SIZE) {
|
||||
dev_err(&dev->sbd.core,
|
||||
"%s:%u region size %lu is not aligned\n", __func__,
|
||||
__LINE__, tmp);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* use static buffer, kmalloc cannot allocate 256 KiB */
|
||||
if (!ps3flash_bounce_buffer.address)
|
||||
return -ENODEV;
|
||||
|
||||
if (ps3flash_dev) {
|
||||
dev_err(&dev->sbd.core,
|
||||
"Only one FLASH device is supported\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
ps3flash_dev = dev;
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv) {
|
||||
error = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dev->sbd.core.driver_data = priv;
|
||||
mutex_init(&priv->mutex);
|
||||
|
||||
dev->bounce_size = ps3flash_bounce_buffer.size;
|
||||
dev->bounce_buf = ps3flash_bounce_buffer.address;
|
||||
|
||||
error = ps3stor_setup(dev, ps3flash_interrupt);
|
||||
if (error)
|
||||
goto fail_free_priv;
|
||||
|
||||
ps3flash_misc.parent = &dev->sbd.core;
|
||||
error = misc_register(&ps3flash_misc);
|
||||
if (error) {
|
||||
dev_err(&dev->sbd.core, "%s:%u: misc_register failed %d\n",
|
||||
__func__, __LINE__, error);
|
||||
goto fail_teardown;
|
||||
}
|
||||
|
||||
dev_info(&dev->sbd.core, "%s:%u: registered misc device %d\n",
|
||||
__func__, __LINE__, ps3flash_misc.minor);
|
||||
return 0;
|
||||
|
||||
fail_teardown:
|
||||
ps3stor_teardown(dev);
|
||||
fail_free_priv:
|
||||
kfree(priv);
|
||||
dev->sbd.core.driver_data = NULL;
|
||||
fail:
|
||||
ps3flash_dev = NULL;
|
||||
return error;
|
||||
}
|
||||
|
||||
static int ps3flash_remove(struct ps3_system_bus_device *_dev)
|
||||
{
|
||||
struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
|
||||
|
||||
misc_deregister(&ps3flash_misc);
|
||||
ps3stor_teardown(dev);
|
||||
kfree(dev->sbd.core.driver_data);
|
||||
dev->sbd.core.driver_data = NULL;
|
||||
ps3flash_dev = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct ps3_system_bus_driver ps3flash = {
|
||||
.match_id = PS3_MATCH_ID_STOR_FLASH,
|
||||
.core.name = DEVICE_NAME,
|
||||
.core.owner = THIS_MODULE,
|
||||
.probe = ps3flash_probe,
|
||||
.remove = ps3flash_remove,
|
||||
.shutdown = ps3flash_remove,
|
||||
};
|
||||
|
||||
|
||||
static int __init ps3flash_init(void)
|
||||
{
|
||||
return ps3_system_bus_driver_register(&ps3flash);
|
||||
}
|
||||
|
||||
static void __exit ps3flash_exit(void)
|
||||
{
|
||||
ps3_system_bus_driver_unregister(&ps3flash);
|
||||
}
|
||||
|
||||
module_init(ps3flash_init);
|
||||
module_exit(ps3flash_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("PS3 FLASH ROM Storage Driver");
|
||||
MODULE_AUTHOR("Sony Corporation");
|
||||
MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_FLASH);
|
||||
|
|
@ -248,14 +248,19 @@ static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file,
|
|||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
||||
static int legacy_count = CONFIG_LEGACY_PTY_COUNT;
|
||||
module_param(legacy_count, int, 0);
|
||||
|
||||
static void __init legacy_pty_init(void)
|
||||
{
|
||||
if (legacy_count <= 0)
|
||||
return;
|
||||
|
||||
pty_driver = alloc_tty_driver(NR_PTYS);
|
||||
pty_driver = alloc_tty_driver(legacy_count);
|
||||
if (!pty_driver)
|
||||
panic("Couldn't allocate pty driver");
|
||||
|
||||
pty_slave_driver = alloc_tty_driver(NR_PTYS);
|
||||
pty_slave_driver = alloc_tty_driver(legacy_count);
|
||||
if (!pty_slave_driver)
|
||||
panic("Couldn't allocate pty slave driver");
|
||||
|
||||
|
|
|
|||
|
|
@ -693,9 +693,14 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
|
|||
|
||||
if (r->pull && r->entropy_count < nbytes * 8 &&
|
||||
r->entropy_count < r->poolinfo->POOLBITS) {
|
||||
int bytes = max_t(int, random_read_wakeup_thresh / 8,
|
||||
min_t(int, nbytes, sizeof(tmp)));
|
||||
/* If we're limited, always leave two wakeup worth's BITS */
|
||||
int rsvd = r->limit ? 0 : random_read_wakeup_thresh/4;
|
||||
int bytes = nbytes;
|
||||
|
||||
/* pull at least as many as BYTES as wakeup BITS */
|
||||
bytes = max_t(int, bytes, random_read_wakeup_thresh / 8);
|
||||
/* but never more than the buffer size */
|
||||
bytes = min_t(int, bytes, sizeof(tmp));
|
||||
|
||||
DEBUG_ENT("going to reseed %s with %d bits "
|
||||
"(%d of %d requested)\n",
|
||||
|
|
@ -1545,11 +1550,13 @@ __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
|
|||
* As close as possible to RFC 793, which
|
||||
* suggests using a 250 kHz clock.
|
||||
* Further reading shows this assumes 2 Mb/s networks.
|
||||
* For 10 Gb/s Ethernet, a 1 GHz clock is appropriate.
|
||||
* That's funny, Linux has one built in! Use it!
|
||||
* (Networks are faster now - should this be increased?)
|
||||
* For 10 Mb/s Ethernet, a 1 MHz clock is appropriate.
|
||||
* For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but
|
||||
* we also need to limit the resolution so that the u32 seq
|
||||
* overlaps less than one time per MSL (2 minutes).
|
||||
* Choosing a clock of 64 ns period is OK. (period of 274 s)
|
||||
*/
|
||||
seq += ktime_get_real().tv64;
|
||||
seq += ktime_get_real().tv64 >> 6;
|
||||
#if 0
|
||||
printk("init_seq(%lx, %lx, %d, %d) = %d\n",
|
||||
saddr, daddr, sport, dport, seq);
|
||||
|
|
|
|||
|
|
@ -255,10 +255,7 @@ static const struct file_operations raw_ctl_fops = {
|
|||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static struct cdev raw_cdev = {
|
||||
.kobj = {.name = "raw", },
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
static struct cdev raw_cdev;
|
||||
|
||||
static int __init raw_init(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -803,9 +803,7 @@ static void *ckmalloc(int size)
|
|||
{
|
||||
void *p;
|
||||
|
||||
p = kmalloc(size, GFP_KERNEL);
|
||||
if (p)
|
||||
memset(p, 0, size);
|
||||
p = kzalloc(size, GFP_KERNEL);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -556,9 +556,7 @@ struct CmdBlk *RIOGetCmdBlk(void)
|
|||
{
|
||||
struct CmdBlk *CmdBlkP;
|
||||
|
||||
CmdBlkP = kmalloc(sizeof(struct CmdBlk), GFP_ATOMIC);
|
||||
if (CmdBlkP)
|
||||
memset(CmdBlkP, 0, sizeof(struct CmdBlk));
|
||||
CmdBlkP = kzalloc(sizeof(struct CmdBlk), GFP_ATOMIC);
|
||||
return CmdBlkP;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -863,8 +863,7 @@ int RIOReMapPorts(struct rio_info *p, struct Host *HostP, struct Map *HostMapP)
|
|||
if (PortP->TxRingBuffer)
|
||||
memset(PortP->TxRingBuffer, 0, p->RIOBufferSize);
|
||||
else if (p->RIOBufferSize) {
|
||||
PortP->TxRingBuffer = kmalloc(p->RIOBufferSize, GFP_KERNEL);
|
||||
memset(PortP->TxRingBuffer, 0, p->RIOBufferSize);
|
||||
PortP->TxRingBuffer = kzalloc(p->RIOBufferSize, GFP_KERNEL);
|
||||
}
|
||||
PortP->TxBufferOut = 0;
|
||||
PortP->TxBufferIn = 0;
|
||||
|
|
|
|||
|
|
@ -635,12 +635,11 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
|
|||
ctlp = sCtlNumToCtlPtr(board);
|
||||
|
||||
/* Get a r_port struct for the port, fill it in and save it globally, indexed by line number */
|
||||
info = kmalloc(sizeof (struct r_port), GFP_KERNEL);
|
||||
info = kzalloc(sizeof (struct r_port), GFP_KERNEL);
|
||||
if (!info) {
|
||||
printk(KERN_INFO "Couldn't allocate info struct for line #%d\n", line);
|
||||
return;
|
||||
}
|
||||
memset(info, 0, sizeof (struct r_port));
|
||||
|
||||
info->magic = RPORT_MAGIC;
|
||||
info->line = line;
|
||||
|
|
|
|||
|
|
@ -82,16 +82,13 @@
|
|||
#include <asm/uaccess.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
#if defined(__i386__)
|
||||
#ifdef CONFIG_X86
|
||||
#include <asm/hpet.h>
|
||||
#endif
|
||||
|
||||
#ifdef __sparc__
|
||||
#ifdef CONFIG_SPARC32
|
||||
#include <linux/pci.h>
|
||||
#include <asm/ebus.h>
|
||||
#ifdef __sparc_v9__
|
||||
#include <asm/isa.h>
|
||||
#endif
|
||||
|
||||
static unsigned long rtc_port;
|
||||
static int rtc_irq = PCI_IRQ_NONE;
|
||||
|
|
@ -930,13 +927,9 @@ static int __init rtc_init(void)
|
|||
unsigned int year, ctrl;
|
||||
char *guess = NULL;
|
||||
#endif
|
||||
#ifdef __sparc__
|
||||
#ifdef CONFIG_SPARC32
|
||||
struct linux_ebus *ebus;
|
||||
struct linux_ebus_device *edev;
|
||||
#ifdef __sparc_v9__
|
||||
struct sparc_isa_bridge *isa_br;
|
||||
struct sparc_isa_device *isa_dev;
|
||||
#endif
|
||||
#else
|
||||
void *r;
|
||||
#ifdef RTC_IRQ
|
||||
|
|
@ -944,7 +937,7 @@ static int __init rtc_init(void)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __sparc__
|
||||
#ifdef CONFIG_SPARC32
|
||||
for_each_ebus(ebus) {
|
||||
for_each_ebusdev(edev, ebus) {
|
||||
if(strcmp(edev->prom_node->name, "rtc") == 0) {
|
||||
|
|
@ -954,17 +947,6 @@ static int __init rtc_init(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
#ifdef __sparc_v9__
|
||||
for_each_isa(isa_br) {
|
||||
for_each_isadev(isa_dev, isa_br) {
|
||||
if (strcmp(isa_dev->prom_node->name, "rtc") == 0) {
|
||||
rtc_port = isa_dev->resource.start;
|
||||
rtc_irq = isa_dev->irq;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
rtc_has_irq = 0;
|
||||
printk(KERN_ERR "rtc_init: no PC rtc found\n");
|
||||
return -EIO;
|
||||
|
|
@ -1020,7 +1002,7 @@ no_irq:
|
|||
|
||||
#endif
|
||||
|
||||
#endif /* __sparc__ vs. others */
|
||||
#endif /* CONFIG_SPARC32 vs. others */
|
||||
|
||||
if (misc_register(&rtc_dev)) {
|
||||
#ifdef RTC_IRQ
|
||||
|
|
@ -1105,7 +1087,7 @@ static void __exit rtc_exit (void)
|
|||
remove_proc_entry ("driver/rtc", NULL);
|
||||
misc_deregister(&rtc_dev);
|
||||
|
||||
#ifdef __sparc__
|
||||
#ifdef CONFIG_SPARC32
|
||||
if (rtc_has_irq)
|
||||
free_irq (rtc_irq, &rtc_port);
|
||||
#else
|
||||
|
|
@ -1117,7 +1099,7 @@ static void __exit rtc_exit (void)
|
|||
if (rtc_has_irq)
|
||||
free_irq (RTC_IRQ, NULL);
|
||||
#endif
|
||||
#endif /* __sparc__ */
|
||||
#endif /* CONFIG_SPARC32 */
|
||||
}
|
||||
|
||||
module_init(rtc_init);
|
||||
|
|
|
|||
|
|
@ -2573,16 +2573,10 @@ static struct tty_driver *serial167_console_device(struct console *c,
|
|||
return cy_serial_driver;
|
||||
}
|
||||
|
||||
static int __init serial167_console_setup(struct console *co, char *options)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct console sercons = {
|
||||
.name = "ttyS",
|
||||
.write = serial167_console_write,
|
||||
.device = serial167_console_device,
|
||||
.setup = serial167_console_setup,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -441,8 +441,7 @@ scdrv_init(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
class_device_create(snsc_class, NULL, dev, NULL,
|
||||
"%s", devname);
|
||||
device_create(snsc_class, NULL, dev, "%s", devname);
|
||||
|
||||
ia64_sn_irtr_intr_enable(scd->scd_nasid,
|
||||
0 /*ignored */ ,
|
||||
|
|
|
|||
|
|
@ -875,7 +875,7 @@ found:
|
|||
|
||||
#ifdef CONFIG_ACPI
|
||||
if (sonypi_acpi_device)
|
||||
acpi_bus_generate_event(sonypi_acpi_device, 1, event);
|
||||
acpi_bus_generate_proc_event(sonypi_acpi_device, 1, event);
|
||||
#endif
|
||||
|
||||
kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event));
|
||||
|
|
@ -1147,10 +1147,15 @@ static int sonypi_acpi_remove(struct acpi_device *device, int type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const static struct acpi_device_id sonypi_device_ids[] = {
|
||||
{"SNY6001", 0},
|
||||
{"", 0},
|
||||
};
|
||||
|
||||
static struct acpi_driver sonypi_acpi_driver = {
|
||||
.name = "sonypi",
|
||||
.class = "hkey",
|
||||
.ids = "SNY6001",
|
||||
.ids = sonypi_device_ids,
|
||||
.ops = {
|
||||
.add = sonypi_acpi_add,
|
||||
.remove = sonypi_acpi_remove,
|
||||
|
|
|
|||
|
|
@ -4778,9 +4778,8 @@ static int __init stallion_module_init(void)
|
|||
if (IS_ERR(stallion_class))
|
||||
printk("STALLION: failed to create class\n");
|
||||
for (i = 0; i < 4; i++)
|
||||
class_device_create(stallion_class, NULL,
|
||||
MKDEV(STL_SIOMEMMAJOR, i), NULL,
|
||||
"staliomem%d", i);
|
||||
device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
|
||||
"staliomem%d", i);
|
||||
|
||||
return 0;
|
||||
err_unrtty:
|
||||
|
|
@ -4795,7 +4794,6 @@ static void __exit stallion_module_exit(void)
|
|||
{
|
||||
struct stlbrd *brdp;
|
||||
unsigned int i, j;
|
||||
int retval;
|
||||
|
||||
pr_debug("cleanup_module()\n");
|
||||
|
||||
|
|
@ -4817,10 +4815,8 @@ static void __exit stallion_module_exit(void)
|
|||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
|
||||
if ((retval = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
|
||||
printk("STALLION: failed to un-register serial memory device, "
|
||||
"errno=%d\n", -retval);
|
||||
device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
|
||||
unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
|
||||
class_destroy(stallion_class);
|
||||
|
||||
pci_unregister_driver(&stl_pcidriver);
|
||||
|
|
|
|||
|
|
@ -4324,13 +4324,12 @@ static struct mgsl_struct* mgsl_allocate_device(void)
|
|||
{
|
||||
struct mgsl_struct *info;
|
||||
|
||||
info = kmalloc(sizeof(struct mgsl_struct),
|
||||
info = kzalloc(sizeof(struct mgsl_struct),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!info) {
|
||||
printk("Error can't allocate device instance data\n");
|
||||
} else {
|
||||
memset(info, 0, sizeof(struct mgsl_struct));
|
||||
info->magic = MGSL_MAGIC;
|
||||
INIT_WORK(&info->task, mgsl_bh_handler);
|
||||
info->max_frame_size = 4096;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* $Id: synclink_gt.c,v 4.36 2006/08/28 20:47:14 paulkf Exp $
|
||||
* $Id: synclink_gt.c,v 4.50 2007/07/25 19:29:25 paulkf Exp $
|
||||
*
|
||||
* Device driver for Microgate SyncLink GT serial adapters.
|
||||
*
|
||||
|
|
@ -93,7 +93,7 @@
|
|||
* module identification
|
||||
*/
|
||||
static char *driver_name = "SyncLink GT";
|
||||
static char *driver_version = "$Revision: 4.36 $";
|
||||
static char *driver_version = "$Revision: 4.50 $";
|
||||
static char *tty_driver_name = "synclink_gt";
|
||||
static char *tty_dev_prefix = "ttySLG";
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -477,6 +477,7 @@ static void tx_set_idle(struct slgt_info *info);
|
|||
static unsigned int free_tbuf_count(struct slgt_info *info);
|
||||
static void reset_tbufs(struct slgt_info *info);
|
||||
static void tdma_reset(struct slgt_info *info);
|
||||
static void tdma_start(struct slgt_info *info);
|
||||
static void tx_load(struct slgt_info *info, const char *buf, unsigned int count);
|
||||
|
||||
static void get_signals(struct slgt_info *info);
|
||||
|
|
@ -904,6 +905,8 @@ start:
|
|||
spin_lock_irqsave(&info->lock,flags);
|
||||
if (!info->tx_active)
|
||||
tx_start(info);
|
||||
else
|
||||
tdma_start(info);
|
||||
spin_unlock_irqrestore(&info->lock,flags);
|
||||
}
|
||||
|
||||
|
|
@ -1562,6 +1565,9 @@ static int hdlcdev_open(struct net_device *dev)
|
|||
int rc;
|
||||
unsigned long flags;
|
||||
|
||||
if (!try_module_get(THIS_MODULE))
|
||||
return -EBUSY;
|
||||
|
||||
DBGINFO(("%s hdlcdev_open\n", dev->name));
|
||||
|
||||
/* generic HDLC layer open processing */
|
||||
|
|
@ -1631,6 +1637,7 @@ static int hdlcdev_close(struct net_device *dev)
|
|||
info->netcount=0;
|
||||
spin_unlock_irqrestore(&info->netlock, flags);
|
||||
|
||||
module_put(THIS_MODULE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3414,13 +3421,12 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev
|
|||
{
|
||||
struct slgt_info *info;
|
||||
|
||||
info = kmalloc(sizeof(struct slgt_info), GFP_KERNEL);
|
||||
info = kzalloc(sizeof(struct slgt_info), GFP_KERNEL);
|
||||
|
||||
if (!info) {
|
||||
DBGERR(("%s device alloc failed adapter=%d port=%d\n",
|
||||
driver_name, adapter_num, port_num));
|
||||
} else {
|
||||
memset(info, 0, sizeof(struct slgt_info));
|
||||
info->magic = MGSL_MAGIC;
|
||||
INIT_WORK(&info->task, bh_handler);
|
||||
info->max_frame_size = 4096;
|
||||
|
|
@ -3872,44 +3878,58 @@ static void tx_start(struct slgt_info *info)
|
|||
slgt_irq_on(info, IRQ_TXUNDER + IRQ_TXIDLE);
|
||||
/* clear tx idle and underrun status bits */
|
||||
wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER));
|
||||
|
||||
if (!(rd_reg32(info, TDCSR) & BIT0)) {
|
||||
/* tx DMA stopped, restart tx DMA */
|
||||
tdma_reset(info);
|
||||
/* set 1st descriptor address */
|
||||
wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc);
|
||||
switch(info->params.mode) {
|
||||
case MGSL_MODE_RAW:
|
||||
case MGSL_MODE_MONOSYNC:
|
||||
case MGSL_MODE_BISYNC:
|
||||
wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */
|
||||
break;
|
||||
default:
|
||||
wr_reg32(info, TDCSR, BIT0); /* DMA enable */
|
||||
}
|
||||
}
|
||||
|
||||
if (info->params.mode == MGSL_MODE_HDLC)
|
||||
mod_timer(&info->tx_timer, jiffies +
|
||||
msecs_to_jiffies(5000));
|
||||
} else {
|
||||
tdma_reset(info);
|
||||
/* set 1st descriptor address */
|
||||
wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc);
|
||||
|
||||
slgt_irq_off(info, IRQ_TXDATA);
|
||||
slgt_irq_on(info, IRQ_TXIDLE);
|
||||
/* clear tx idle status bit */
|
||||
wr_reg16(info, SSR, IRQ_TXIDLE);
|
||||
|
||||
/* enable tx DMA */
|
||||
wr_reg32(info, TDCSR, BIT0);
|
||||
}
|
||||
|
||||
tdma_start(info);
|
||||
info->tx_active = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* start transmit DMA if inactive and there are unsent buffers
|
||||
*/
|
||||
static void tdma_start(struct slgt_info *info)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (rd_reg32(info, TDCSR) & BIT0)
|
||||
return;
|
||||
|
||||
/* transmit DMA inactive, check for unsent buffers */
|
||||
i = info->tbuf_start;
|
||||
while (!desc_count(info->tbufs[i])) {
|
||||
if (++i == info->tbuf_count)
|
||||
i = 0;
|
||||
if (i == info->tbuf_current)
|
||||
return;
|
||||
}
|
||||
info->tbuf_start = i;
|
||||
|
||||
/* there are unsent buffers, start transmit DMA */
|
||||
|
||||
/* reset needed if previous error condition */
|
||||
tdma_reset(info);
|
||||
|
||||
/* set 1st descriptor address */
|
||||
wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc);
|
||||
switch(info->params.mode) {
|
||||
case MGSL_MODE_RAW:
|
||||
case MGSL_MODE_MONOSYNC:
|
||||
case MGSL_MODE_BISYNC:
|
||||
wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */
|
||||
break;
|
||||
default:
|
||||
wr_reg32(info, TDCSR, BIT0); /* DMA enable */
|
||||
}
|
||||
}
|
||||
|
||||
static void tx_stop(struct slgt_info *info)
|
||||
{
|
||||
unsigned short val;
|
||||
|
|
@ -4643,8 +4663,8 @@ static unsigned int free_tbuf_count(struct slgt_info *info)
|
|||
i=0;
|
||||
} while (i != info->tbuf_current);
|
||||
|
||||
/* last buffer with zero count may be in use, assume it is */
|
||||
if (count)
|
||||
/* if tx DMA active, last zero count buffer is in use */
|
||||
if (count && (rd_reg32(info, TDCSR) & BIT0))
|
||||
--count;
|
||||
|
||||
return count;
|
||||
|
|
|
|||
|
|
@ -3786,14 +3786,13 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev)
|
|||
{
|
||||
SLMP_INFO *info;
|
||||
|
||||
info = kmalloc(sizeof(SLMP_INFO),
|
||||
info = kzalloc(sizeof(SLMP_INFO),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!info) {
|
||||
printk("%s(%d) Error can't allocate device instance data for adapter %d, port %d\n",
|
||||
__FILE__,__LINE__, adapter_num, port_num);
|
||||
} else {
|
||||
memset(info, 0, sizeof(SLMP_INFO));
|
||||
info->magic = MGSL_MAGIC;
|
||||
INIT_WORK(&info->task, bh_handler);
|
||||
info->max_frame_size = 4096;
|
||||
|
|
|
|||
|
|
@ -441,8 +441,8 @@ tipar_register(int nr, struct parport *port)
|
|||
goto out;
|
||||
}
|
||||
|
||||
class_device_create(tipar_class, NULL, MKDEV(TIPAR_MAJOR,
|
||||
TIPAR_MINOR + nr), port->dev, "par%d", nr);
|
||||
device_create(tipar_class, port->dev, MKDEV(TIPAR_MAJOR,
|
||||
TIPAR_MINOR + nr), "par%d", nr);
|
||||
|
||||
/* Display informations */
|
||||
pr_info("tipar%d: using %s (%s)\n", nr, port->name, (port->irq ==
|
||||
|
|
@ -534,7 +534,7 @@ tipar_cleanup_module(void)
|
|||
if (table[i].dev == NULL)
|
||||
continue;
|
||||
parport_unregister_device(table[i].dev);
|
||||
class_device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, i));
|
||||
device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, i));
|
||||
}
|
||||
class_destroy(tipar_class);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
* Kylene Hall <kjhall@us.ibm.com>
|
||||
*
|
||||
* Maintained by: <tpmdd_devel@lists.sourceforge.net>
|
||||
* Maintained by: <tpmdd-devel@lists.sourceforge.net>
|
||||
*
|
||||
* Device driver for TCG/TCPA TPM (trusted platform module).
|
||||
* Specifications at www.trustedcomputinggroup.org
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
* Kylene Hall <kjhall@us.ibm.com>
|
||||
*
|
||||
* Maintained by: <tpmdd_devel@lists.sourceforge.net>
|
||||
* Maintained by: <tpmdd-devel@lists.sourceforge.net>
|
||||
*
|
||||
* Device driver for TCG/TCPA TPM (trusted platform module).
|
||||
* Specifications at www.trustedcomputinggroup.org
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
* Kylene Hall <kjhall@us.ibm.com>
|
||||
*
|
||||
* Maintained by: <tpmdd_devel@lists.sourceforge.net>
|
||||
* Maintained by: <tpmdd-devel@lists.sourceforge.net>
|
||||
*
|
||||
* Device driver for TCG/TCPA TPM (trusted platform module).
|
||||
* Specifications at www.trustedcomputinggroup.org
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
* Authors:
|
||||
* Kylene Hall <kjhall@us.ibm.com>
|
||||
*
|
||||
* Maintained by: <tpmdd_devel@lists.sourceforge.net>
|
||||
* Maintained by: <tpmdd-devel@lists.sourceforge.net>
|
||||
*
|
||||
* Device driver for TCG/TCPA TPM (trusted platform module).
|
||||
* Specifications at www.trustedcomputinggroup.org
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
* Kylene Hall <kjhall@us.ibm.com>
|
||||
*
|
||||
* Maintained by: <tpmdd-devel@lists.sourceforge.net>
|
||||
*
|
||||
* Access to the eventlog extended by the TCG BIOS of PC platform
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
|
@ -427,7 +429,7 @@ static int tpm_ascii_bios_measurements_open(struct inode *inode,
|
|||
return -ENOMEM;
|
||||
|
||||
if ((err = read_log(log)))
|
||||
return err;
|
||||
goto out_free;
|
||||
|
||||
/* now register seq file */
|
||||
err = seq_open(file, &tpm_ascii_b_measurments_seqops);
|
||||
|
|
@ -435,10 +437,15 @@ static int tpm_ascii_bios_measurements_open(struct inode *inode,
|
|||
seq = file->private_data;
|
||||
seq->private = log;
|
||||
} else {
|
||||
kfree(log->bios_event_log);
|
||||
kfree(log);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
out:
|
||||
return err;
|
||||
out_free:
|
||||
kfree(log->bios_event_log);
|
||||
kfree(log);
|
||||
goto out;
|
||||
}
|
||||
|
||||
const struct file_operations tpm_ascii_bios_measurements_ops = {
|
||||
|
|
@ -460,7 +467,7 @@ static int tpm_binary_bios_measurements_open(struct inode *inode,
|
|||
return -ENOMEM;
|
||||
|
||||
if ((err = read_log(log)))
|
||||
return err;
|
||||
goto out_free;
|
||||
|
||||
/* now register seq file */
|
||||
err = seq_open(file, &tpm_binary_b_measurments_seqops);
|
||||
|
|
@ -468,10 +475,15 @@ static int tpm_binary_bios_measurements_open(struct inode *inode,
|
|||
seq = file->private_data;
|
||||
seq->private = log;
|
||||
} else {
|
||||
kfree(log->bios_event_log);
|
||||
kfree(log);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
out:
|
||||
return err;
|
||||
out_free:
|
||||
kfree(log->bios_event_log);
|
||||
kfree(log);
|
||||
goto out;
|
||||
}
|
||||
|
||||
const struct file_operations tpm_binary_bios_measurements_ops = {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
* Kylene Hall <kjhall@us.ibm.com>
|
||||
*
|
||||
* Maintained by: <tpmdd_devel@lists.sourceforge.net>
|
||||
* Maintained by: <tpmdd-devel@lists.sourceforge.net>
|
||||
*
|
||||
* Device driver for TCG/TCPA TPM (trusted platform module).
|
||||
* Specifications at www.trustedcomputinggroup.org
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
* Leendert van Doorn <leendert@watson.ibm.com>
|
||||
* Kylene Hall <kjhall@us.ibm.com>
|
||||
*
|
||||
* Maintained by: <tpmdd-devel@lists.sourceforge.net>
|
||||
*
|
||||
* Device driver for TCG/TCPA TPM (trusted platform module).
|
||||
* Specifications at www.trustedcomputinggroup.org
|
||||
*
|
||||
|
|
|
|||
|
|
@ -368,26 +368,55 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* __tty_buffer_flush - flush full tty buffers
|
||||
* @tty: tty to flush
|
||||
*
|
||||
* flush all the buffers containing receive data. Caller must
|
||||
* hold the buffer lock and must have ensured no parallel flush to
|
||||
* ldisc is running.
|
||||
*
|
||||
* Locking: Caller must hold tty->buf.lock
|
||||
*/
|
||||
|
||||
static void __tty_buffer_flush(struct tty_struct *tty)
|
||||
{
|
||||
struct tty_buffer *thead;
|
||||
|
||||
while((thead = tty->buf.head) != NULL) {
|
||||
tty->buf.head = thead->next;
|
||||
tty_buffer_free(tty, thead);
|
||||
}
|
||||
tty->buf.tail = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* tty_buffer_flush - flush full tty buffers
|
||||
* @tty: tty to flush
|
||||
*
|
||||
* flush all the buffers containing receive data
|
||||
* flush all the buffers containing receive data. If the buffer is
|
||||
* being processed by flush_to_ldisc then we defer the processing
|
||||
* to that function
|
||||
*
|
||||
* Locking: none
|
||||
*/
|
||||
|
||||
static void tty_buffer_flush(struct tty_struct *tty)
|
||||
{
|
||||
struct tty_buffer *thead;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tty->buf.lock, flags);
|
||||
while((thead = tty->buf.head) != NULL) {
|
||||
tty->buf.head = thead->next;
|
||||
tty_buffer_free(tty, thead);
|
||||
}
|
||||
tty->buf.tail = NULL;
|
||||
|
||||
/* If the data is being pushed to the tty layer then we can't
|
||||
process it here. Instead set a flag and the flush_to_ldisc
|
||||
path will process the flush request before it exits */
|
||||
if (test_bit(TTY_FLUSHING, &tty->flags)) {
|
||||
set_bit(TTY_FLUSHPENDING, &tty->flags);
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
wait_event(tty->read_wait,
|
||||
test_bit(TTY_FLUSHPENDING, &tty->flags) == 0);
|
||||
return;
|
||||
} else
|
||||
__tty_buffer_flush(tty);
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
}
|
||||
|
||||
|
|
@ -2034,8 +2063,7 @@ static int init_dev(struct tty_driver *driver, int idx,
|
|||
}
|
||||
|
||||
if (!*tp_loc) {
|
||||
tp = (struct ktermios *) kmalloc(sizeof(struct ktermios),
|
||||
GFP_KERNEL);
|
||||
tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL);
|
||||
if (!tp)
|
||||
goto free_mem_out;
|
||||
*tp = driver->init_termios;
|
||||
|
|
@ -2065,8 +2093,7 @@ static int init_dev(struct tty_driver *driver, int idx,
|
|||
}
|
||||
|
||||
if (!*o_tp_loc) {
|
||||
o_tp = (struct ktermios *)
|
||||
kmalloc(sizeof(struct ktermios), GFP_KERNEL);
|
||||
o_tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL);
|
||||
if (!o_tp)
|
||||
goto free_mem_out;
|
||||
*o_tp = driver->other->init_termios;
|
||||
|
|
@ -3594,6 +3621,7 @@ static void flush_to_ldisc(struct work_struct *work)
|
|||
return;
|
||||
|
||||
spin_lock_irqsave(&tty->buf.lock, flags);
|
||||
set_bit(TTY_FLUSHING, &tty->flags); /* So we know a flush is running */
|
||||
head = tty->buf.head;
|
||||
if (head != NULL) {
|
||||
tty->buf.head = NULL;
|
||||
|
|
@ -3607,6 +3635,11 @@ static void flush_to_ldisc(struct work_struct *work)
|
|||
tty_buffer_free(tty, tbuf);
|
||||
continue;
|
||||
}
|
||||
/* Ldisc or user is trying to flush the buffers
|
||||
we are feeding to the ldisc, stop feeding the
|
||||
line discipline as we want to empty the queue */
|
||||
if (test_bit(TTY_FLUSHPENDING, &tty->flags))
|
||||
break;
|
||||
if (!tty->receive_room) {
|
||||
schedule_delayed_work(&tty->buf.work, 1);
|
||||
break;
|
||||
|
|
@ -3620,8 +3653,17 @@ static void flush_to_ldisc(struct work_struct *work)
|
|||
disc->receive_buf(tty, char_buf, flag_buf, count);
|
||||
spin_lock_irqsave(&tty->buf.lock, flags);
|
||||
}
|
||||
/* Restore the queue head */
|
||||
tty->buf.head = head;
|
||||
}
|
||||
/* We may have a deferred request to flush the input buffer,
|
||||
if so pull the chain under the lock and empty the queue */
|
||||
if (test_bit(TTY_FLUSHPENDING, &tty->flags)) {
|
||||
__tty_buffer_flush(tty);
|
||||
clear_bit(TTY_FLUSHPENDING, &tty->flags);
|
||||
wake_up(&tty->read_wait);
|
||||
}
|
||||
clear_bit(TTY_FLUSHING, &tty->flags);
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
|
||||
tty_ldisc_deref(disc);
|
||||
|
|
|
|||
|
|
@ -795,6 +795,7 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
|
|||
if (L_ICANON(tty))
|
||||
retval = inq_canon(tty);
|
||||
return put_user(retval, (unsigned int __user *) arg);
|
||||
#ifndef TCGETS2
|
||||
case TIOCGLCKTRMIOS:
|
||||
if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
|
||||
return -EFAULT;
|
||||
|
|
@ -806,6 +807,19 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
|
|||
if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
#else
|
||||
case TIOCGLCKTRMIOS:
|
||||
if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
case TIOCSLCKTRMIOS:
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
case TIOCPKT:
|
||||
{
|
||||
|
|
|
|||
|
|
@ -92,47 +92,6 @@ struct viot_devinfo_struct {
|
|||
#define VIOTAPOP_SETPART 14
|
||||
#define VIOTAPOP_UNLOAD 15
|
||||
|
||||
struct viotapelpevent {
|
||||
struct HvLpEvent event;
|
||||
u32 reserved;
|
||||
u16 version;
|
||||
u16 sub_type_result;
|
||||
u16 tape;
|
||||
u16 flags;
|
||||
u32 token;
|
||||
u64 len;
|
||||
union {
|
||||
struct {
|
||||
u32 tape_op;
|
||||
u32 count;
|
||||
} op;
|
||||
struct {
|
||||
u32 type;
|
||||
u32 resid;
|
||||
u32 dsreg;
|
||||
u32 gstat;
|
||||
u32 erreg;
|
||||
u32 file_no;
|
||||
u32 block_no;
|
||||
} get_status;
|
||||
struct {
|
||||
u32 block_no;
|
||||
} get_pos;
|
||||
} u;
|
||||
};
|
||||
|
||||
enum viotapesubtype {
|
||||
viotapeopen = 0x0001,
|
||||
viotapeclose = 0x0002,
|
||||
viotaperead = 0x0003,
|
||||
viotapewrite = 0x0004,
|
||||
viotapegetinfo = 0x0005,
|
||||
viotapeop = 0x0006,
|
||||
viotapegetpos = 0x0007,
|
||||
viotapesetpos = 0x0008,
|
||||
viotapegetstatus = 0x0009
|
||||
};
|
||||
|
||||
enum viotaperc {
|
||||
viotape_InvalidRange = 0x0601,
|
||||
viotape_InvalidToken = 0x0602,
|
||||
|
|
@ -223,14 +182,11 @@ static const struct vio_error_entry viotape_err_table[] = {
|
|||
#define VIOT_WRITING 2
|
||||
|
||||
/* Our info on the tapes */
|
||||
struct tape_descr {
|
||||
char rsrcname[10];
|
||||
char type[4];
|
||||
char model[3];
|
||||
};
|
||||
|
||||
static struct tape_descr *viotape_unitinfo;
|
||||
static dma_addr_t viotape_unitinfo_token;
|
||||
static struct {
|
||||
const char *rsrcname;
|
||||
const char *type;
|
||||
const char *model;
|
||||
} viotape_unitinfo[VIOTAPE_MAX_TAPE];
|
||||
|
||||
static struct mtget viomtget[VIOTAPE_MAX_TAPE];
|
||||
|
||||
|
|
@ -381,53 +337,6 @@ int tape_rc_to_errno(int tape_rc, char *operation, int tapeno)
|
|||
return -err->errno;
|
||||
}
|
||||
|
||||
/* Get info on all tapes from OS/400 */
|
||||
static int get_viotape_info(void)
|
||||
{
|
||||
HvLpEvent_Rc hvrc;
|
||||
int i;
|
||||
size_t len = sizeof(*viotape_unitinfo) * VIOTAPE_MAX_TAPE;
|
||||
struct op_struct *op = get_op_struct();
|
||||
|
||||
if (op == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
viotape_unitinfo = dma_alloc_coherent(iSeries_vio_dev, len,
|
||||
&viotape_unitinfo_token, GFP_ATOMIC);
|
||||
if (viotape_unitinfo == NULL) {
|
||||
free_op_struct(op);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(viotape_unitinfo, 0, len);
|
||||
|
||||
hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
|
||||
HvLpEvent_Type_VirtualIo,
|
||||
viomajorsubtype_tape | viotapegetinfo,
|
||||
HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
|
||||
viopath_sourceinst(viopath_hostLp),
|
||||
viopath_targetinst(viopath_hostLp),
|
||||
(u64) (unsigned long) op, VIOVERSION << 16,
|
||||
viotape_unitinfo_token, len, 0, 0);
|
||||
if (hvrc != HvLpEvent_Rc_Good) {
|
||||
printk(VIOTAPE_KERN_WARN "hv error on op %d\n",
|
||||
(int)hvrc);
|
||||
free_op_struct(op);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
wait_for_completion(&op->com);
|
||||
|
||||
free_op_struct(op);
|
||||
|
||||
for (i = 0;
|
||||
((i < VIOTAPE_MAX_TAPE) && (viotape_unitinfo[i].rsrcname[0]));
|
||||
i++)
|
||||
viotape_numdev++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Write */
|
||||
static ssize_t viotap_write(struct file *file, const char *buf,
|
||||
size_t count, loff_t * ppos)
|
||||
|
|
@ -899,7 +808,6 @@ static void vioHandleTapeEvent(struct HvLpEvent *event)
|
|||
tapeminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK;
|
||||
op = (struct op_struct *)event->xCorrelationToken;
|
||||
switch (tapeminor) {
|
||||
case viotapegetinfo:
|
||||
case viotapeopen:
|
||||
case viotapeclose:
|
||||
op->rc = tevent->sub_type_result;
|
||||
|
|
@ -942,19 +850,31 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
|
|||
{
|
||||
int i = vdev->unit_address;
|
||||
int j;
|
||||
struct device_node *node = vdev->dev.archdata.of_node;
|
||||
|
||||
if (i >= viotape_numdev)
|
||||
if (i > VIOTAPE_MAX_TAPE)
|
||||
return -ENODEV;
|
||||
if (!node)
|
||||
return -ENODEV;
|
||||
|
||||
if (i >= viotape_numdev)
|
||||
viotape_numdev = i + 1;
|
||||
|
||||
tape_device[i] = &vdev->dev;
|
||||
viotape_unitinfo[i].rsrcname = of_get_property(node,
|
||||
"linux,vio_rsrcname", NULL);
|
||||
viotape_unitinfo[i].type = of_get_property(node, "linux,vio_type",
|
||||
NULL);
|
||||
viotape_unitinfo[i].model = of_get_property(node, "linux,vio_model",
|
||||
NULL);
|
||||
|
||||
state[i].cur_part = 0;
|
||||
for (j = 0; j < MAX_PARTITIONS; ++j)
|
||||
state[i].part_stat_rwi[j] = VIOT_IDLE;
|
||||
class_device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), NULL,
|
||||
device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i),
|
||||
"iseries!vt%d", i);
|
||||
class_device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80),
|
||||
NULL, "iseries!nvt%d", i);
|
||||
device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80),
|
||||
"iseries!nvt%d", i);
|
||||
printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries "
|
||||
"resource %10.10s type %4.4s, model %3.3s\n",
|
||||
i, viotape_unitinfo[i].rsrcname,
|
||||
|
|
@ -966,8 +886,8 @@ static int viotape_remove(struct vio_dev *vdev)
|
|||
{
|
||||
int i = vdev->unit_address;
|
||||
|
||||
class_device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80));
|
||||
class_device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i));
|
||||
device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80));
|
||||
device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1044,11 +964,6 @@ int __init viotap_init(void)
|
|||
goto unreg_chrdev;
|
||||
}
|
||||
|
||||
if ((ret = get_viotape_info()) < 0) {
|
||||
printk(VIOTAPE_KERN_WARN "Unable to obtain virtual device information");
|
||||
goto unreg_class;
|
||||
}
|
||||
|
||||
ret = vio_register_driver(&viotape_driver);
|
||||
if (ret)
|
||||
goto unreg_class;
|
||||
|
|
@ -1098,19 +1013,10 @@ static int chg_state(int index, unsigned char new_state, struct file *file)
|
|||
/* Cleanup */
|
||||
static void __exit viotap_exit(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
remove_proc_entry("iSeries/viotape", NULL);
|
||||
vio_unregister_driver(&viotape_driver);
|
||||
class_destroy(tape_class);
|
||||
ret = unregister_chrdev(VIOTAPE_MAJOR, "viotape");
|
||||
if (ret < 0)
|
||||
printk(VIOTAPE_KERN_WARN "Error unregistering device: %d\n",
|
||||
ret);
|
||||
if (viotape_unitinfo)
|
||||
dma_free_coherent(iSeries_vio_dev,
|
||||
sizeof(viotape_unitinfo[0]) * VIOTAPE_MAX_TAPE,
|
||||
viotape_unitinfo, viotape_unitinfo_token);
|
||||
unregister_chrdev(VIOTAPE_MAJOR, "viotape");
|
||||
viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2);
|
||||
vio_clearHandler(viomajorsubtype_tape);
|
||||
clear_op_struct_pool();
|
||||
|
|
|
|||
|
|
@ -1013,18 +1013,10 @@ static struct tty_driver *scc_console_device(struct console *c, int *index)
|
|||
return scc_driver;
|
||||
}
|
||||
|
||||
|
||||
static int __init scc_console_setup(struct console *co, char *options)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct console sercons = {
|
||||
.name = "ttyS",
|
||||
.write = scc_console_write,
|
||||
.device = scc_console_device,
|
||||
.setup = scc_console_setup,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -770,6 +770,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
|
|||
/*
|
||||
* Switching-from response
|
||||
*/
|
||||
acquire_console_sem();
|
||||
if (vc->vt_newvt >= 0) {
|
||||
if (arg == 0)
|
||||
/*
|
||||
|
|
@ -784,7 +785,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
|
|||
* complete the switch.
|
||||
*/
|
||||
int newvt;
|
||||
acquire_console_sem();
|
||||
newvt = vc->vt_newvt;
|
||||
vc->vt_newvt = -1;
|
||||
i = vc_allocate(newvt);
|
||||
|
|
@ -798,7 +798,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
|
|||
* other console switches..
|
||||
*/
|
||||
complete_change_console(vc_cons[newvt].d);
|
||||
release_console_sem();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -810,9 +809,12 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
|
|||
/*
|
||||
* If it's just an ACK, ignore it
|
||||
*/
|
||||
if (arg != VT_ACKACQ)
|
||||
if (arg != VT_ACKACQ) {
|
||||
release_console_sem();
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
release_console_sem();
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
@ -1030,7 +1032,7 @@ static DECLARE_WAIT_QUEUE_HEAD(vt_activate_queue);
|
|||
|
||||
/*
|
||||
* Sleeps until a vt is activated, or the task is interrupted. Returns
|
||||
* 0 if activation, -EINTR if interrupted.
|
||||
* 0 if activation, -EINTR if interrupted by a signal handler.
|
||||
*/
|
||||
int vt_waitactive(int vt)
|
||||
{
|
||||
|
|
@ -1055,7 +1057,7 @@ int vt_waitactive(int vt)
|
|||
break;
|
||||
}
|
||||
release_console_sem();
|
||||
retval = -EINTR;
|
||||
retval = -ERESTARTNOHAND;
|
||||
if (signal_pending(current))
|
||||
break;
|
||||
schedule();
|
||||
|
|
@ -1208,15 +1210,18 @@ void change_console(struct vc_data *new_vc)
|
|||
/*
|
||||
* Send the signal as privileged - kill_pid() will
|
||||
* tell us if the process has gone or something else
|
||||
* is awry
|
||||
* is awry.
|
||||
*
|
||||
* We need to set vt_newvt *before* sending the signal or we
|
||||
* have a race.
|
||||
*/
|
||||
vc->vt_newvt = new_vc->vc_num;
|
||||
if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) {
|
||||
/*
|
||||
* It worked. Mark the vt to switch to and
|
||||
* return. The process needs to send us a
|
||||
* VT_RELDISP ioctl to complete the switch.
|
||||
*/
|
||||
vc->vt_newvt = new_vc->vc_num;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ config SOFT_WATCHDOG
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called softdog.
|
||||
|
||||
# ALPHA Architecture
|
||||
|
||||
# ARM Architecture
|
||||
|
||||
config AT91RM9200_WATCHDOG
|
||||
|
|
@ -187,15 +189,64 @@ config PNX4008_WATCHDOG
|
|||
|
||||
Say N if you are unsure.
|
||||
|
||||
config IOP_WATCHDOG
|
||||
tristate "IOP Watchdog"
|
||||
depends on PLAT_IOP
|
||||
select WATCHDOG_NOWAYOUT if (ARCH_IOP32X || ARCH_IOP33X)
|
||||
help
|
||||
Say Y here if to include support for the watchdog timer
|
||||
in the Intel IOP3XX & IOP13XX I/O Processors. This driver can
|
||||
be built as a module by choosing M. The module will
|
||||
be called iop_wdt.
|
||||
|
||||
Note: The IOP13XX watchdog does an Internal Bus Reset which will
|
||||
affect both cores and the peripherals of the IOP. The ATU-X
|
||||
and/or ATUe configuration registers will remain intact, but if
|
||||
operating as an Root Complex and/or Central Resource, the PCI-X
|
||||
and/or PCIe busses will also be reset. THIS IS A VERY BIG HAMMER.
|
||||
|
||||
config DAVINCI_WATCHDOG
|
||||
tristate "DaVinci watchdog"
|
||||
depends on ARCH_DAVINCI
|
||||
help
|
||||
Say Y here if to include support for the watchdog timer
|
||||
in the DaVinci DM644x/DM646x processors.
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called davinci_wdt.
|
||||
|
||||
NOTE: once enabled, this timer cannot be disabled.
|
||||
Say N if you are unsure.
|
||||
|
||||
# ARM26 Architecture
|
||||
|
||||
# AVR32 Architecture
|
||||
|
||||
config AT32AP700X_WDT
|
||||
tristate "AT32AP700x watchdog"
|
||||
depends on WATCHDOG && CPU_AT32AP7000
|
||||
depends on CPU_AT32AP7000
|
||||
help
|
||||
Watchdog timer embedded into AT32AP700x devices. This will reboot
|
||||
your system when the timeout is reached.
|
||||
|
||||
# BLACKFIN Architecture
|
||||
|
||||
config BFIN_WDT
|
||||
tristate "Blackfin On-Chip Watchdog Timer"
|
||||
depends on BLACKFIN
|
||||
---help---
|
||||
If you say yes here you will get support for the Blackfin On-Chip
|
||||
Watchdog Timer. If you have one of these processors and wish to
|
||||
have watchdog support enabled, say Y, otherwise say N.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called bfin_wdt.
|
||||
|
||||
# CRIS Architecture
|
||||
|
||||
# FRV Architecture
|
||||
|
||||
# H8300 Architecture
|
||||
|
||||
# X86 (i386 + ia64 + x86_64) Architecture
|
||||
|
||||
config ACQUIRE_WDT
|
||||
|
|
@ -524,7 +575,47 @@ config SBC_EPX_C3_WATCHDOG
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called sbc_epx_c3.
|
||||
|
||||
# PowerPC Architecture
|
||||
# M32R Architecture
|
||||
|
||||
# M68K Architecture
|
||||
|
||||
# M68KNOMMU Architecture
|
||||
|
||||
# MIPS Architecture
|
||||
|
||||
config INDYDOG
|
||||
tristate "Indy/I2 Hardware Watchdog"
|
||||
depends on SGI_IP22
|
||||
help
|
||||
Hardware driver for the Indy's/I2's watchdog. This is a
|
||||
watchdog timer that will reboot the machine after a 60 second
|
||||
timer expired and no process has written to /dev/watchdog during
|
||||
that time.
|
||||
|
||||
config WDT_MTX1
|
||||
tristate "MTX-1 Hardware Watchdog"
|
||||
depends on MIPS_MTX1
|
||||
help
|
||||
Hardware driver for the MTX-1 boards. This is a watchdog timer that
|
||||
will reboot the machine after a 100 seconds timer expired.
|
||||
|
||||
config WDT_RM9K_GPI
|
||||
tristate "RM9000/GPI hardware watchdog"
|
||||
depends on CPU_RM9000
|
||||
help
|
||||
Watchdog implementation using the GPI hardware found on
|
||||
PMC-Sierra RM9xxx CPUs.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called rm9k_wdt.
|
||||
|
||||
# PARISC Architecture
|
||||
|
||||
# POWERPC Architecture
|
||||
|
||||
config MPC5200_WDT
|
||||
tristate "MPC5200 Watchdog Timer"
|
||||
depends on PPC_MPC52xx
|
||||
|
||||
config 8xx_WDT
|
||||
tristate "MPC8xx Watchdog Timer"
|
||||
|
|
@ -556,34 +647,6 @@ config WATCHDOG_RTAS
|
|||
To compile this driver as a module, choose M here. The module
|
||||
will be called wdrtas.
|
||||
|
||||
# MIPS Architecture
|
||||
|
||||
config INDYDOG
|
||||
tristate "Indy/I2 Hardware Watchdog"
|
||||
depends on SGI_IP22
|
||||
help
|
||||
Hardware driver for the Indy's/I2's watchdog. This is a
|
||||
watchdog timer that will reboot the machine after a 60 second
|
||||
timer expired and no process has written to /dev/watchdog during
|
||||
that time.
|
||||
|
||||
config WDT_MTX1
|
||||
tristate "MTX-1 Hardware Watchdog"
|
||||
depends on MIPS_MTX1
|
||||
help
|
||||
Hardware driver for the MTX-1 boards. This is a watchdog timer that
|
||||
will reboot the machine after a 100 seconds timer expired.
|
||||
|
||||
config WDT_RM9K_GPI
|
||||
tristate "RM9000/GPI hardware watchdog"
|
||||
depends on CPU_RM9000
|
||||
help
|
||||
Watchdog implementation using the GPI hardware found on
|
||||
PMC-Sierra RM9xxx CPUs.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called rm9k_wdt.
|
||||
|
||||
# S390 Architecture
|
||||
|
||||
config ZVM_WATCHDOG
|
||||
|
|
@ -598,11 +661,11 @@ config ZVM_WATCHDOG
|
|||
To compile this driver as a module, choose M here. The module
|
||||
will be called vmwatchdog.
|
||||
|
||||
# SUPERH Architecture
|
||||
# SUPERH (sh + sh64) Architecture
|
||||
|
||||
config SH_WDT
|
||||
tristate "SuperH Watchdog"
|
||||
depends on SUPERH
|
||||
depends on SUPERH && (CPU_SH3 || CPU_SH4)
|
||||
help
|
||||
This driver adds watchdog support for the integrated watchdog in the
|
||||
SuperH processors. If you have one of these processors and wish
|
||||
|
|
@ -625,6 +688,8 @@ config SH_WDT_MMAP
|
|||
If you say Y here, user applications will be able to mmap the
|
||||
WDT/CPG registers.
|
||||
|
||||
# SPARC Architecture
|
||||
|
||||
# SPARC64 Architecture
|
||||
|
||||
config WATCHDOG_CP1XXX
|
||||
|
|
@ -649,6 +714,10 @@ config WATCHDOG_RIO
|
|||
machines. The watchdog timeout period is normally one minute but
|
||||
can be changed with a boot-time parameter.
|
||||
|
||||
# V850 Architecture
|
||||
|
||||
# XTENSA Architecture
|
||||
|
||||
#
|
||||
# ISA-based Watchdog Cards
|
||||
#
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ obj-$(CONFIG_WDTPCI) += wdt_pci.o
|
|||
# USB-based Watchdog Cards
|
||||
obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
|
||||
|
||||
# ALPHA Architecture
|
||||
|
||||
# ARM Architecture
|
||||
obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o
|
||||
obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
|
||||
|
|
@ -35,10 +37,23 @@ obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
|
|||
obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
|
||||
obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o
|
||||
obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o
|
||||
obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o
|
||||
obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o
|
||||
|
||||
# ARM26 Architecture
|
||||
|
||||
# AVR32 Architecture
|
||||
obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
|
||||
|
||||
# BLACKFIN Architecture
|
||||
obj-$(CONFIG_BFIN_WDT) += bfin_wdt.o
|
||||
|
||||
# CRIS Architecture
|
||||
|
||||
# FRV Architecture
|
||||
|
||||
# H8300 Architecture
|
||||
|
||||
# X86 (i386 + ia64 + x86_64) Architecture
|
||||
obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
|
||||
obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
|
||||
|
|
@ -65,8 +80,22 @@ obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
|
|||
obj-$(CONFIG_MACHZ_WDT) += machzwd.o
|
||||
obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
|
||||
|
||||
# PowerPC Architecture
|
||||
# M32R Architecture
|
||||
|
||||
# M68K Architecture
|
||||
|
||||
# M68KNOMMU Architecture
|
||||
|
||||
# MIPS Architecture
|
||||
obj-$(CONFIG_INDYDOG) += indydog.o
|
||||
obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
|
||||
obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
|
||||
|
||||
# PARISC Architecture
|
||||
|
||||
# POWERPC Architecture
|
||||
obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
|
||||
obj-$(CONFIG_MPC5200_WDT) += mpc5200_wdt.o
|
||||
obj-$(CONFIG_83xx_WDT) += mpc83xx_wdt.o
|
||||
obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o
|
||||
obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
|
||||
|
|
@ -74,17 +103,18 @@ obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
|
|||
# PPC64 Architecture
|
||||
obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o
|
||||
|
||||
# MIPS Architecture
|
||||
obj-$(CONFIG_INDYDOG) += indydog.o
|
||||
obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
|
||||
obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
|
||||
|
||||
# S390 Architecture
|
||||
|
||||
# SUPERH Architecture
|
||||
# SUPERH (sh + sh64) Architecture
|
||||
obj-$(CONFIG_SH_WDT) += shwdt.o
|
||||
|
||||
# SPARC Architecture
|
||||
|
||||
# SPARC64 Architecture
|
||||
|
||||
# V850 Architecture
|
||||
|
||||
# XTENSA Architecture
|
||||
|
||||
# Architecture Independant
|
||||
obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
|
||||
|
|
|
|||
|
|
@ -312,6 +312,7 @@ static int ali_notify_sys(struct notifier_block *this, unsigned long code, void
|
|||
*/
|
||||
|
||||
static struct pci_device_id ali_pci_tbl[] = {
|
||||
{ PCI_VENDOR_ID_AL, 0x1533, PCI_ANY_ID, PCI_ANY_ID,},
|
||||
{ PCI_VENDOR_ID_AL, 0x1535, PCI_ANY_ID, PCI_ANY_ID,},
|
||||
{ 0, },
|
||||
};
|
||||
|
|
@ -329,9 +330,11 @@ static int __init ali_find_watchdog(void)
|
|||
struct pci_dev *pdev;
|
||||
u32 wdog;
|
||||
|
||||
/* Check for a 1535 series bridge */
|
||||
/* Check for a 1533/1535 series bridge */
|
||||
pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x1535, NULL);
|
||||
if(pdev == NULL)
|
||||
if (pdev == NULL)
|
||||
pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x1533, NULL);
|
||||
if (pdev == NULL)
|
||||
return -ENODEV;
|
||||
pci_dev_put(pdev);
|
||||
|
||||
|
|
|
|||
490
drivers/char/watchdog/bfin_wdt.c
Normal file
490
drivers/char/watchdog/bfin_wdt.c
Normal file
|
|
@ -0,0 +1,490 @@
|
|||
/*
|
||||
* Blackfin On-Chip Watchdog Driver
|
||||
* Supports BF53[123]/BF53[467]/BF54[2489]/BF561
|
||||
*
|
||||
* Originally based on softdog.c
|
||||
* Copyright 2006-2007 Analog Devices Inc.
|
||||
* Copyright 2006-2007 Michele d'Amico
|
||||
* Copyright 1996 Alan Cox <alan@redhat.com>
|
||||
*
|
||||
* Enter bugs at http://blackfin.uclinux.org/
|
||||
*
|
||||
* Licensed under the GPL-2 or later.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/watchdog.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <asm/blackfin.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
|
||||
#define stampit() stamp("here i am")
|
||||
|
||||
#define WATCHDOG_NAME "bfin-wdt"
|
||||
#define PFX WATCHDOG_NAME ": "
|
||||
|
||||
/* The BF561 has two watchdogs (one per core), but since Linux
|
||||
* only runs on core A, we'll just work with that one.
|
||||
*/
|
||||
#ifdef BF561_FAMILY
|
||||
# define bfin_read_WDOG_CTL() bfin_read_WDOGA_CTL()
|
||||
# define bfin_read_WDOG_CNT() bfin_read_WDOGA_CNT()
|
||||
# define bfin_read_WDOG_STAT() bfin_read_WDOGA_STAT()
|
||||
# define bfin_write_WDOG_CTL(x) bfin_write_WDOGA_CTL(x)
|
||||
# define bfin_write_WDOG_CNT(x) bfin_write_WDOGA_CNT(x)
|
||||
# define bfin_write_WDOG_STAT(x) bfin_write_WDOGA_STAT(x)
|
||||
#endif
|
||||
|
||||
/* Bit in SWRST that indicates boot caused by watchdog */
|
||||
#define SWRST_RESET_WDOG 0x4000
|
||||
|
||||
/* Bit in WDOG_CTL that indicates watchdog has expired (WDR0) */
|
||||
#define WDOG_EXPIRED 0x8000
|
||||
|
||||
/* Masks for WDEV field in WDOG_CTL register */
|
||||
#define ICTL_RESET 0x0
|
||||
#define ICTL_NMI 0x2
|
||||
#define ICTL_GPI 0x4
|
||||
#define ICTL_NONE 0x6
|
||||
#define ICTL_MASK 0x6
|
||||
|
||||
/* Masks for WDEN field in WDOG_CTL register */
|
||||
#define WDEN_MASK 0x0FF0
|
||||
#define WDEN_ENABLE 0x0000
|
||||
#define WDEN_DISABLE 0x0AD0
|
||||
|
||||
/* some defaults */
|
||||
#define WATCHDOG_TIMEOUT 20
|
||||
|
||||
static unsigned int timeout = WATCHDOG_TIMEOUT;
|
||||
static int nowayout = WATCHDOG_NOWAYOUT;
|
||||
static struct watchdog_info bfin_wdt_info;
|
||||
static unsigned long open_check;
|
||||
static char expect_close;
|
||||
static spinlock_t bfin_wdt_spinlock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
/**
|
||||
* bfin_wdt_keepalive - Keep the Userspace Watchdog Alive
|
||||
*
|
||||
* The Userspace watchdog got a KeepAlive: schedule the next timeout.
|
||||
*/
|
||||
static int bfin_wdt_keepalive(void)
|
||||
{
|
||||
stampit();
|
||||
bfin_write_WDOG_STAT(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* bfin_wdt_stop - Stop the Watchdog
|
||||
*
|
||||
* Stops the on-chip watchdog.
|
||||
*/
|
||||
static int bfin_wdt_stop(void)
|
||||
{
|
||||
stampit();
|
||||
bfin_write_WDOG_CTL(WDEN_DISABLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* bfin_wdt_start - Start the Watchdog
|
||||
*
|
||||
* Starts the on-chip watchdog. Automatically loads WDOG_CNT
|
||||
* into WDOG_STAT for us.
|
||||
*/
|
||||
static int bfin_wdt_start(void)
|
||||
{
|
||||
stampit();
|
||||
bfin_write_WDOG_CTL(WDEN_ENABLE | ICTL_RESET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* bfin_wdt_running - Check Watchdog status
|
||||
*
|
||||
* See if the watchdog is running.
|
||||
*/
|
||||
static int bfin_wdt_running(void)
|
||||
{
|
||||
stampit();
|
||||
return ((bfin_read_WDOG_CTL() & WDEN_MASK) != WDEN_DISABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* bfin_wdt_set_timeout - Set the Userspace Watchdog timeout
|
||||
* @t: new timeout value (in seconds)
|
||||
*
|
||||
* Translate the specified timeout in seconds into System Clock
|
||||
* terms which is what the on-chip Watchdog requires.
|
||||
*/
|
||||
static int bfin_wdt_set_timeout(unsigned long t)
|
||||
{
|
||||
u32 cnt;
|
||||
unsigned long flags;
|
||||
|
||||
stampit();
|
||||
|
||||
cnt = t * get_sclk();
|
||||
if (cnt < get_sclk()) {
|
||||
printk(KERN_WARNING PFX "timeout value is too large\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&bfin_wdt_spinlock, flags);
|
||||
{
|
||||
int run = bfin_wdt_running();
|
||||
bfin_wdt_stop();
|
||||
bfin_write_WDOG_CNT(cnt);
|
||||
if (run) bfin_wdt_start();
|
||||
}
|
||||
spin_unlock_irqrestore(&bfin_wdt_spinlock, flags);
|
||||
|
||||
timeout = t;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* bfin_wdt_open - Open the Device
|
||||
* @inode: inode of device
|
||||
* @file: file handle of device
|
||||
*
|
||||
* Watchdog device is opened and started.
|
||||
*/
|
||||
static int bfin_wdt_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
stampit();
|
||||
|
||||
if (test_and_set_bit(0, &open_check))
|
||||
return -EBUSY;
|
||||
|
||||
if (nowayout)
|
||||
__module_get(THIS_MODULE);
|
||||
|
||||
bfin_wdt_keepalive();
|
||||
bfin_wdt_start();
|
||||
|
||||
return nonseekable_open(inode, file);
|
||||
}
|
||||
|
||||
/**
|
||||
* bfin_wdt_close - Close the Device
|
||||
* @inode: inode of device
|
||||
* @file: file handle of device
|
||||
*
|
||||
* Watchdog device is closed and stopped.
|
||||
*/
|
||||
static int bfin_wdt_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
stampit();
|
||||
|
||||
if (expect_close == 42) {
|
||||
bfin_wdt_stop();
|
||||
} else {
|
||||
printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
|
||||
bfin_wdt_keepalive();
|
||||
}
|
||||
|
||||
expect_close = 0;
|
||||
clear_bit(0, &open_check);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* bfin_wdt_write - Write to Device
|
||||
* @file: file handle of device
|
||||
* @buf: buffer to write
|
||||
* @count: length of buffer
|
||||
* @ppos: offset
|
||||
*
|
||||
* Pings the watchdog on write.
|
||||
*/
|
||||
static ssize_t bfin_wdt_write(struct file *file, const char __user *data,
|
||||
size_t len, loff_t *ppos)
|
||||
{
|
||||
stampit();
|
||||
|
||||
if (len) {
|
||||
if (!nowayout) {
|
||||
size_t i;
|
||||
|
||||
/* In case it was set long ago */
|
||||
expect_close = 0;
|
||||
|
||||
for (i = 0; i != len; i++) {
|
||||
char c;
|
||||
if (get_user(c, data + i))
|
||||
return -EFAULT;
|
||||
if (c == 'V')
|
||||
expect_close = 42;
|
||||
}
|
||||
}
|
||||
bfin_wdt_keepalive();
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* bfin_wdt_ioctl - Query Device
|
||||
* @inode: inode of device
|
||||
* @file: file handle of device
|
||||
* @cmd: watchdog command
|
||||
* @arg: argument
|
||||
*
|
||||
* Query basic information from the device or ping it, as outlined by the
|
||||
* watchdog API.
|
||||
*/
|
||||
static int bfin_wdt_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
void __user *argp = (void __user *)arg;
|
||||
int __user *p = argp;
|
||||
|
||||
stampit();
|
||||
|
||||
switch (cmd) {
|
||||
default:
|
||||
return -ENOTTY;
|
||||
|
||||
case WDIOC_GETSUPPORT:
|
||||
if (copy_to_user(argp, &bfin_wdt_info, sizeof(bfin_wdt_info)))
|
||||
return -EFAULT;
|
||||
else
|
||||
return 0;
|
||||
|
||||
case WDIOC_GETSTATUS:
|
||||
case WDIOC_GETBOOTSTATUS:
|
||||
return put_user(!!(_bfin_swrst & SWRST_RESET_WDOG), p);
|
||||
|
||||
case WDIOC_KEEPALIVE:
|
||||
bfin_wdt_keepalive();
|
||||
return 0;
|
||||
|
||||
case WDIOC_SETTIMEOUT: {
|
||||
int new_timeout;
|
||||
|
||||
if (get_user(new_timeout, p))
|
||||
return -EFAULT;
|
||||
|
||||
if (bfin_wdt_set_timeout(new_timeout))
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Fall */
|
||||
case WDIOC_GETTIMEOUT:
|
||||
return put_user(timeout, p);
|
||||
|
||||
case WDIOC_SETOPTIONS: {
|
||||
unsigned long flags;
|
||||
int options, ret = -EINVAL;
|
||||
|
||||
if (get_user(options, p))
|
||||
return -EFAULT;
|
||||
|
||||
spin_lock_irqsave(&bfin_wdt_spinlock, flags);
|
||||
|
||||
if (options & WDIOS_DISABLECARD) {
|
||||
bfin_wdt_stop();
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (options & WDIOS_ENABLECARD) {
|
||||
bfin_wdt_start();
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&bfin_wdt_spinlock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* bfin_wdt_notify_sys - Notifier Handler
|
||||
* @this: notifier block
|
||||
* @code: notifier event
|
||||
* @unused: unused
|
||||
*
|
||||
* Handles specific events, such as turning off the watchdog during a
|
||||
* shutdown event.
|
||||
*/
|
||||
static int bfin_wdt_notify_sys(struct notifier_block *this, unsigned long code,
|
||||
void *unused)
|
||||
{
|
||||
stampit();
|
||||
|
||||
if (code == SYS_DOWN || code == SYS_HALT)
|
||||
bfin_wdt_stop();
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int state_before_suspend;
|
||||
|
||||
/**
|
||||
* bfin_wdt_suspend - suspend the watchdog
|
||||
* @pdev: device being suspended
|
||||
* @state: requested suspend state
|
||||
*
|
||||
* Remember if the watchdog was running and stop it.
|
||||
* TODO: is this even right? Doesn't seem to be any
|
||||
* standard in the watchdog world ...
|
||||
*/
|
||||
static int bfin_wdt_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
stampit();
|
||||
|
||||
state_before_suspend = bfin_wdt_running();
|
||||
bfin_wdt_stop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* bfin_wdt_resume - resume the watchdog
|
||||
* @pdev: device being resumed
|
||||
*
|
||||
* If the watchdog was running, turn it back on.
|
||||
*/
|
||||
static int bfin_wdt_resume(struct platform_device *pdev)
|
||||
{
|
||||
stampit();
|
||||
|
||||
if (state_before_suspend) {
|
||||
bfin_wdt_set_timeout(timeout);
|
||||
bfin_wdt_start();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
# define bfin_wdt_suspend NULL
|
||||
# define bfin_wdt_resume NULL
|
||||
#endif
|
||||
|
||||
static struct platform_device bfin_wdt_device = {
|
||||
.name = WATCHDOG_NAME,
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static struct platform_driver bfin_wdt_driver = {
|
||||
.driver = {
|
||||
.name = WATCHDOG_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.suspend = bfin_wdt_suspend,
|
||||
.resume = bfin_wdt_resume,
|
||||
};
|
||||
|
||||
static struct file_operations bfin_wdt_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.write = bfin_wdt_write,
|
||||
.ioctl = bfin_wdt_ioctl,
|
||||
.open = bfin_wdt_open,
|
||||
.release = bfin_wdt_release,
|
||||
};
|
||||
|
||||
static struct miscdevice bfin_wdt_miscdev = {
|
||||
.minor = WATCHDOG_MINOR,
|
||||
.name = "watchdog",
|
||||
.fops = &bfin_wdt_fops,
|
||||
};
|
||||
|
||||
static struct watchdog_info bfin_wdt_info = {
|
||||
.identity = "Blackfin Watchdog",
|
||||
.options = WDIOF_SETTIMEOUT |
|
||||
WDIOF_KEEPALIVEPING |
|
||||
WDIOF_MAGICCLOSE,
|
||||
};
|
||||
|
||||
static struct notifier_block bfin_wdt_notifier = {
|
||||
.notifier_call = bfin_wdt_notify_sys,
|
||||
};
|
||||
|
||||
/**
|
||||
* bfin_wdt_init - Initialize module
|
||||
*
|
||||
* Registers the device and notifier handler. Actual device
|
||||
* initialization is handled by bfin_wdt_open().
|
||||
*/
|
||||
static int __init bfin_wdt_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
stampit();
|
||||
|
||||
/* Check that the timeout value is within range */
|
||||
if (bfin_wdt_set_timeout(timeout))
|
||||
return -EINVAL;
|
||||
|
||||
/* Since this is an on-chip device and needs no board-specific
|
||||
* resources, we'll handle all the platform device stuff here.
|
||||
*/
|
||||
ret = platform_device_register(&bfin_wdt_device);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = platform_driver_probe(&bfin_wdt_driver, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = register_reboot_notifier(&bfin_wdt_notifier);
|
||||
if (ret) {
|
||||
printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = misc_register(&bfin_wdt_miscdev);
|
||||
if (ret) {
|
||||
printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
|
||||
WATCHDOG_MINOR, ret);
|
||||
unregister_reboot_notifier(&bfin_wdt_notifier);
|
||||
return ret;
|
||||
}
|
||||
|
||||
printk(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n",
|
||||
timeout, nowayout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* bfin_wdt_exit - Deinitialize module
|
||||
*
|
||||
* Unregisters the device and notifier handler. Actual device
|
||||
* deinitialization is handled by bfin_wdt_close().
|
||||
*/
|
||||
static void __exit bfin_wdt_exit(void)
|
||||
{
|
||||
misc_deregister(&bfin_wdt_miscdev);
|
||||
unregister_reboot_notifier(&bfin_wdt_notifier);
|
||||
}
|
||||
|
||||
module_init(bfin_wdt_init);
|
||||
module_exit(bfin_wdt_exit);
|
||||
|
||||
MODULE_AUTHOR("Michele d'Amico, Mike Frysinger <vapier@gentoo.org>");
|
||||
MODULE_DESCRIPTION("Blackfin Watchdog Device Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
|
||||
|
||||
module_param(timeout, uint, 0);
|
||||
MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
|
||||
|
||||
module_param(nowayout, int, 0);
|
||||
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
|
||||
|
|
@ -144,7 +144,7 @@ static int booke_wdt_open (struct inode *inode, struct file *file)
|
|||
booke_wdt_period);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return nonseekable_open(inode, file);
|
||||
}
|
||||
|
||||
static const struct file_operations booke_wdt_fops = {
|
||||
|
|
|
|||
|
|
@ -162,6 +162,10 @@ static int cpu5wdt_ioctl(struct inode *inode, struct file *file, unsigned int cm
|
|||
if ( copy_to_user(argp, &value, sizeof(int)) )
|
||||
return -EFAULT;
|
||||
break;
|
||||
case WDIOC_GETBOOTSTATUS:
|
||||
if ( copy_to_user(argp, &value, sizeof(int)) )
|
||||
return -EFAULT;
|
||||
break;
|
||||
case WDIOC_GETSUPPORT:
|
||||
if ( copy_to_user(argp, &ident, sizeof(ident)) )
|
||||
return -EFAULT;
|
||||
|
|
|
|||
281
drivers/char/watchdog/davinci_wdt.c
Normal file
281
drivers/char/watchdog/davinci_wdt.c
Normal file
|
|
@ -0,0 +1,281 @@
|
|||
/*
|
||||
* drivers/char/watchdog/davinci_wdt.c
|
||||
*
|
||||
* Watchdog driver for DaVinci DM644x/DM646x processors
|
||||
*
|
||||
* Copyright (C) 2006 Texas Instruments.
|
||||
*
|
||||
* 2007 (c) MontaVista Software, Inc. This file is licensed under
|
||||
* the terms of the GNU General Public License version 2. This program
|
||||
* is licensed "as is" without any warranty of any kind, whether express
|
||||
* or implied.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/watchdog.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define MODULE_NAME "DAVINCI-WDT: "
|
||||
|
||||
#define DEFAULT_HEARTBEAT 60
|
||||
#define MAX_HEARTBEAT 600 /* really the max margin is 264/27MHz*/
|
||||
|
||||
/* Timer register set definition */
|
||||
#define PID12 (0x0)
|
||||
#define EMUMGT (0x4)
|
||||
#define TIM12 (0x10)
|
||||
#define TIM34 (0x14)
|
||||
#define PRD12 (0x18)
|
||||
#define PRD34 (0x1C)
|
||||
#define TCR (0x20)
|
||||
#define TGCR (0x24)
|
||||
#define WDTCR (0x28)
|
||||
|
||||
/* TCR bit definitions */
|
||||
#define ENAMODE12_DISABLED (0 << 6)
|
||||
#define ENAMODE12_ONESHOT (1 << 6)
|
||||
#define ENAMODE12_PERIODIC (2 << 6)
|
||||
|
||||
/* TGCR bit definitions */
|
||||
#define TIM12RS_UNRESET (1 << 0)
|
||||
#define TIM34RS_UNRESET (1 << 1)
|
||||
#define TIMMODE_64BIT_WDOG (2 << 2)
|
||||
|
||||
/* WDTCR bit definitions */
|
||||
#define WDEN (1 << 14)
|
||||
#define WDFLAG (1 << 15)
|
||||
#define WDKEY_SEQ0 (0xa5c6 << 16)
|
||||
#define WDKEY_SEQ1 (0xda7e << 16)
|
||||
|
||||
static int heartbeat = DEFAULT_HEARTBEAT;
|
||||
|
||||
static spinlock_t io_lock;
|
||||
static unsigned long wdt_status;
|
||||
#define WDT_IN_USE 0
|
||||
#define WDT_OK_TO_CLOSE 1
|
||||
#define WDT_REGION_INITED 2
|
||||
#define WDT_DEVICE_INITED 3
|
||||
|
||||
static struct resource *wdt_mem;
|
||||
static void __iomem *wdt_base;
|
||||
|
||||
static void wdt_service(void)
|
||||
{
|
||||
spin_lock(&io_lock);
|
||||
|
||||
/* put watchdog in service state */
|
||||
davinci_writel(WDKEY_SEQ0, wdt_base + WDTCR);
|
||||
/* put watchdog in active state */
|
||||
davinci_writel(WDKEY_SEQ1, wdt_base + WDTCR);
|
||||
|
||||
spin_unlock(&io_lock);
|
||||
}
|
||||
|
||||
static void wdt_enable(void)
|
||||
{
|
||||
u32 tgcr;
|
||||
u32 timer_margin;
|
||||
|
||||
spin_lock(&io_lock);
|
||||
|
||||
/* disable, internal clock source */
|
||||
davinci_writel(0, wdt_base + TCR);
|
||||
/* reset timer, set mode to 64-bit watchdog, and unreset */
|
||||
davinci_writel(0, wdt_base + TGCR);
|
||||
tgcr = TIMMODE_64BIT_WDOG | TIM12RS_UNRESET | TIM34RS_UNRESET;
|
||||
davinci_writel(tgcr, wdt_base + TGCR);
|
||||
/* clear counter regs */
|
||||
davinci_writel(0, wdt_base + TIM12);
|
||||
davinci_writel(0, wdt_base + TIM34);
|
||||
/* set timeout period */
|
||||
timer_margin = (((u64)heartbeat * CLOCK_TICK_RATE) & 0xffffffff);
|
||||
davinci_writel(timer_margin, wdt_base + PRD12);
|
||||
timer_margin = (((u64)heartbeat * CLOCK_TICK_RATE) >> 32);
|
||||
davinci_writel(timer_margin, wdt_base + PRD34);
|
||||
/* enable run continuously */
|
||||
davinci_writel(ENAMODE12_PERIODIC, wdt_base + TCR);
|
||||
/* Once the WDT is in pre-active state write to
|
||||
* TIM12, TIM34, PRD12, PRD34, TCR, TGCR, WDTCR are
|
||||
* write protected (except for the WDKEY field)
|
||||
*/
|
||||
/* put watchdog in pre-active state */
|
||||
davinci_writel(WDKEY_SEQ0 | WDEN, wdt_base + WDTCR);
|
||||
/* put watchdog in active state */
|
||||
davinci_writel(WDKEY_SEQ1 | WDEN, wdt_base + WDTCR);
|
||||
|
||||
spin_unlock(&io_lock);
|
||||
}
|
||||
|
||||
static int davinci_wdt_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
if (test_and_set_bit(WDT_IN_USE, &wdt_status))
|
||||
return -EBUSY;
|
||||
|
||||
wdt_enable();
|
||||
|
||||
return nonseekable_open(inode, file);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
davinci_wdt_write(struct file *file, const char *data, size_t len,
|
||||
loff_t *ppos)
|
||||
{
|
||||
if (len)
|
||||
wdt_service();
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static struct watchdog_info ident = {
|
||||
.options = WDIOF_KEEPALIVEPING,
|
||||
.identity = "DaVinci Watchdog",
|
||||
};
|
||||
|
||||
static int
|
||||
davinci_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
int ret = -ENOTTY;
|
||||
|
||||
switch (cmd) {
|
||||
case WDIOC_GETSUPPORT:
|
||||
ret = copy_to_user((struct watchdog_info *)arg, &ident,
|
||||
sizeof(ident)) ? -EFAULT : 0;
|
||||
break;
|
||||
|
||||
case WDIOC_GETSTATUS:
|
||||
case WDIOC_GETBOOTSTATUS:
|
||||
ret = put_user(0, (int *)arg);
|
||||
break;
|
||||
|
||||
case WDIOC_GETTIMEOUT:
|
||||
ret = put_user(heartbeat, (int *)arg);
|
||||
break;
|
||||
|
||||
case WDIOC_KEEPALIVE:
|
||||
wdt_service();
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int davinci_wdt_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
wdt_service();
|
||||
clear_bit(WDT_IN_USE, &wdt_status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations davinci_wdt_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.write = davinci_wdt_write,
|
||||
.ioctl = davinci_wdt_ioctl,
|
||||
.open = davinci_wdt_open,
|
||||
.release = davinci_wdt_release,
|
||||
};
|
||||
|
||||
static struct miscdevice davinci_wdt_miscdev = {
|
||||
.minor = WATCHDOG_MINOR,
|
||||
.name = "watchdog",
|
||||
.fops = &davinci_wdt_fops,
|
||||
};
|
||||
|
||||
static int davinci_wdt_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0, size;
|
||||
struct resource *res;
|
||||
|
||||
spin_lock_init(&io_lock);
|
||||
|
||||
if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
|
||||
heartbeat = DEFAULT_HEARTBEAT;
|
||||
|
||||
printk(KERN_INFO MODULE_NAME
|
||||
"DaVinci Watchdog Timer: heartbeat %d sec\n", heartbeat);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (res == NULL) {
|
||||
printk(KERN_INFO MODULE_NAME
|
||||
"failed to get memory region resource\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
size = res->end - res->start + 1;
|
||||
wdt_mem = request_mem_region(res->start, size, pdev->name);
|
||||
|
||||
if (wdt_mem == NULL) {
|
||||
printk(KERN_INFO MODULE_NAME "failed to get memory region\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
wdt_base = (void __iomem *)(res->start);
|
||||
|
||||
ret = misc_register(&davinci_wdt_miscdev);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR MODULE_NAME "cannot register misc device\n");
|
||||
release_resource(wdt_mem);
|
||||
kfree(wdt_mem);
|
||||
} else {
|
||||
set_bit(WDT_DEVICE_INITED, &wdt_status);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int davinci_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
misc_deregister(&davinci_wdt_miscdev);
|
||||
if (wdt_mem) {
|
||||
release_resource(wdt_mem);
|
||||
kfree(wdt_mem);
|
||||
wdt_mem = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver platform_wdt_driver = {
|
||||
.driver = {
|
||||
.name = "watchdog",
|
||||
},
|
||||
.probe = davinci_wdt_probe,
|
||||
.remove = davinci_wdt_remove,
|
||||
};
|
||||
|
||||
static int __init davinci_wdt_init(void)
|
||||
{
|
||||
return platform_driver_register(&platform_wdt_driver);
|
||||
}
|
||||
|
||||
static void __exit davinci_wdt_exit(void)
|
||||
{
|
||||
return platform_driver_unregister(&platform_wdt_driver);
|
||||
}
|
||||
|
||||
module_init(davinci_wdt_init);
|
||||
module_exit(davinci_wdt_exit);
|
||||
|
||||
MODULE_AUTHOR("Texas Instruments");
|
||||
MODULE_DESCRIPTION("DaVinci Watchdog Driver");
|
||||
|
||||
module_param(heartbeat, int, 0);
|
||||
MODULE_PARM_DESC(heartbeat,
|
||||
"Watchdog heartbeat period in seconds from 1 to "
|
||||
__MODULE_STRING(MAX_HEARTBEAT) ", default "
|
||||
__MODULE_STRING(DEFAULT_HEARTBEAT));
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Eurotech CPU-1220/1410 on board WDT driver
|
||||
* Eurotech CPU-1220/1410/1420 on board WDT driver
|
||||
*
|
||||
* (c) Copyright 2001 Ascensit <support@ascensit.com>
|
||||
* (c) Copyright 2001 Rodolfo Giometti <giometti@ascensit.com>
|
||||
|
|
@ -24,6 +24,9 @@
|
|||
*/
|
||||
|
||||
/* Changelog:
|
||||
*
|
||||
* 2001 - Rodolfo Giometti
|
||||
* Initial release
|
||||
*
|
||||
* 2002/04/25 - Rob Radez
|
||||
* clean up #includes
|
||||
|
|
@ -33,13 +36,15 @@
|
|||
* add WDIOC_GETSTATUS and WDIOC_SETOPTIONS ioctls
|
||||
* add expect_close support
|
||||
*
|
||||
* 2001 - Rodolfo Giometti
|
||||
* Initial release
|
||||
*
|
||||
* 2002.05.30 - Joel Becker <joel.becker@oracle.com>
|
||||
* Added Matt Domsch's nowayout module option.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The eurotech CPU-1220/1410/1420's watchdog is a part
|
||||
* of the on-board SUPER I/O device SMSC FDC 37B782.
|
||||
*/
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
|
|
|||
|
|
@ -39,7 +39,12 @@
|
|||
* 82801HR (ICH8R) : document number 313056-002, 313057-004,
|
||||
* 82801HH (ICH8DH) : document number 313056-002, 313057-004,
|
||||
* 82801HO (ICH8DO) : document number 313056-002, 313057-004,
|
||||
* 6300ESB (6300ESB) : document number 300641-003
|
||||
* 82801IB (ICH9) : document number 316972-001, 316973-001,
|
||||
* 82801IR (ICH9R) : document number 316972-001, 316973-001,
|
||||
* 82801IH (ICH9DH) : document number 316972-001, 316973-001,
|
||||
* 6300ESB (6300ESB) : document number 300641-003, 300884-010,
|
||||
* 631xESB (631xESB) : document number 313082-001, 313075-005,
|
||||
* 632xESB (632xESB) : document number 313082-001, 313075-005
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
@ -48,8 +53,8 @@
|
|||
|
||||
/* Module and version information */
|
||||
#define DRV_NAME "iTCO_wdt"
|
||||
#define DRV_VERSION "1.01"
|
||||
#define DRV_RELDATE "21-Jan-2007"
|
||||
#define DRV_VERSION "1.02"
|
||||
#define DRV_RELDATE "26-Jul-2007"
|
||||
#define PFX DRV_NAME ": "
|
||||
|
||||
/* Includes */
|
||||
|
|
@ -92,6 +97,10 @@ enum iTCO_chipsets {
|
|||
TCO_ICH8, /* ICH8 & ICH8R */
|
||||
TCO_ICH8DH, /* ICH8DH */
|
||||
TCO_ICH8DO, /* ICH8DO */
|
||||
TCO_ICH9, /* ICH9 */
|
||||
TCO_ICH9R, /* ICH9R */
|
||||
TCO_ICH9DH, /* ICH9DH */
|
||||
TCO_631XESB, /* 631xESB/632xESB */
|
||||
};
|
||||
|
||||
static struct {
|
||||
|
|
@ -118,6 +127,10 @@ static struct {
|
|||
{"ICH8 or ICH8R", 2},
|
||||
{"ICH8DH", 2},
|
||||
{"ICH8DO", 2},
|
||||
{"ICH9", 2},
|
||||
{"ICH9R", 2},
|
||||
{"ICH9DH", 2},
|
||||
{"631xESB/632xESB", 2},
|
||||
{NULL,0}
|
||||
};
|
||||
|
||||
|
|
@ -148,6 +161,25 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = {
|
|||
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8 },
|
||||
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DH },
|
||||
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DO },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x2918, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9 },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x2916, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9R },
|
||||
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9DH },
|
||||
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x2671, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x2672, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x2673, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x2674, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x2675, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x2676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x2677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x2678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x2679, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x267a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x267b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x267c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x267d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x267e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x267f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
|
||||
{ 0, }, /* End of list */
|
||||
};
|
||||
MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl);
|
||||
|
|
|
|||
262
drivers/char/watchdog/iop_wdt.c
Normal file
262
drivers/char/watchdog/iop_wdt.c
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* drivers/char/watchdog/iop_wdt.c
|
||||
*
|
||||
* WDT driver for Intel I/O Processors
|
||||
* Copyright (C) 2005, Intel Corporation.
|
||||
*
|
||||
* Based on ixp4xx driver, Copyright 2004 (c) MontaVista, Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place - Suite 330, Boston, MA 02111-1307 USA.
|
||||
*
|
||||
* Curt E Bruns <curt.e.bruns@intel.com>
|
||||
* Peter Milne <peter.milne@d-tacq.com>
|
||||
* Dan Williams <dan.j.williams@intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/watchdog.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/hardware.h>
|
||||
|
||||
static int nowayout = WATCHDOG_NOWAYOUT;
|
||||
static unsigned long wdt_status;
|
||||
static unsigned long boot_status;
|
||||
|
||||
#define WDT_IN_USE 0
|
||||
#define WDT_OK_TO_CLOSE 1
|
||||
#define WDT_ENABLED 2
|
||||
|
||||
static unsigned long iop_watchdog_timeout(void)
|
||||
{
|
||||
return (0xffffffffUL / get_iop_tick_rate());
|
||||
}
|
||||
|
||||
/**
|
||||
* wdt_supports_disable - determine if we are accessing a iop13xx watchdog
|
||||
* or iop3xx by whether it has a disable command
|
||||
*/
|
||||
static int wdt_supports_disable(void)
|
||||
{
|
||||
int can_disable;
|
||||
|
||||
if (IOP_WDTCR_EN_ARM != IOP_WDTCR_DIS_ARM)
|
||||
can_disable = 1;
|
||||
else
|
||||
can_disable = 0;
|
||||
|
||||
return can_disable;
|
||||
}
|
||||
|
||||
static void wdt_enable(void)
|
||||
{
|
||||
/* Arm and enable the Timer to starting counting down from 0xFFFF.FFFF
|
||||
* Takes approx. 10.7s to timeout
|
||||
*/
|
||||
write_wdtcr(IOP_WDTCR_EN_ARM);
|
||||
write_wdtcr(IOP_WDTCR_EN);
|
||||
}
|
||||
|
||||
/* returns 0 if the timer was successfully disabled */
|
||||
static int wdt_disable(void)
|
||||
{
|
||||
/* Stop Counting */
|
||||
if (wdt_supports_disable()) {
|
||||
write_wdtcr(IOP_WDTCR_DIS_ARM);
|
||||
write_wdtcr(IOP_WDTCR_DIS);
|
||||
clear_bit(WDT_ENABLED, &wdt_status);
|
||||
printk(KERN_INFO "WATCHDOG: Disabled\n");
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int iop_wdt_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
if (test_and_set_bit(WDT_IN_USE, &wdt_status))
|
||||
return -EBUSY;
|
||||
|
||||
clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
|
||||
|
||||
wdt_enable();
|
||||
|
||||
set_bit(WDT_ENABLED, &wdt_status);
|
||||
|
||||
return nonseekable_open(inode, file);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
iop_wdt_write(struct file *file, const char *data, size_t len,
|
||||
loff_t *ppos)
|
||||
{
|
||||
if (len) {
|
||||
if (!nowayout) {
|
||||
size_t i;
|
||||
|
||||
clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
|
||||
|
||||
for (i = 0; i != len; i++) {
|
||||
char c;
|
||||
|
||||
if (get_user(c, data + i))
|
||||
return -EFAULT;
|
||||
if (c == 'V')
|
||||
set_bit(WDT_OK_TO_CLOSE, &wdt_status);
|
||||
}
|
||||
}
|
||||
wdt_enable();
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static struct watchdog_info ident = {
|
||||
.options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
|
||||
.identity = "iop watchdog",
|
||||
};
|
||||
|
||||
static int
|
||||
iop_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
int options;
|
||||
int ret = -ENOTTY;
|
||||
|
||||
switch (cmd) {
|
||||
case WDIOC_GETSUPPORT:
|
||||
if (copy_to_user
|
||||
((struct watchdog_info *)arg, &ident, sizeof ident))
|
||||
ret = -EFAULT;
|
||||
else
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case WDIOC_GETSTATUS:
|
||||
ret = put_user(0, (int *)arg);
|
||||
break;
|
||||
|
||||
case WDIOC_GETBOOTSTATUS:
|
||||
ret = put_user(boot_status, (int *)arg);
|
||||
break;
|
||||
|
||||
case WDIOC_GETTIMEOUT:
|
||||
ret = put_user(iop_watchdog_timeout(), (int *)arg);
|
||||
break;
|
||||
|
||||
case WDIOC_KEEPALIVE:
|
||||
wdt_enable();
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case WDIOC_SETOPTIONS:
|
||||
if (get_user(options, (int *)arg))
|
||||
return -EFAULT;
|
||||
|
||||
if (options & WDIOS_DISABLECARD) {
|
||||
if (!nowayout) {
|
||||
if (wdt_disable() == 0) {
|
||||
set_bit(WDT_OK_TO_CLOSE, &wdt_status);
|
||||
ret = 0;
|
||||
} else
|
||||
ret = -ENXIO;
|
||||
} else
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (options & WDIOS_ENABLECARD) {
|
||||
wdt_enable();
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iop_wdt_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
int state = 1;
|
||||
if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
|
||||
if (test_bit(WDT_ENABLED, &wdt_status))
|
||||
state = wdt_disable();
|
||||
|
||||
/* if the timer is not disbaled reload and notify that we are still
|
||||
* going down
|
||||
*/
|
||||
if (state != 0) {
|
||||
wdt_enable();
|
||||
printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
|
||||
"reset in %lu seconds\n", iop_watchdog_timeout());
|
||||
}
|
||||
|
||||
clear_bit(WDT_IN_USE, &wdt_status);
|
||||
clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations iop_wdt_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.write = iop_wdt_write,
|
||||
.ioctl = iop_wdt_ioctl,
|
||||
.open = iop_wdt_open,
|
||||
.release = iop_wdt_release,
|
||||
};
|
||||
|
||||
static struct miscdevice iop_wdt_miscdev = {
|
||||
.minor = WATCHDOG_MINOR,
|
||||
.name = "watchdog",
|
||||
.fops = &iop_wdt_fops,
|
||||
};
|
||||
|
||||
static int __init iop_wdt_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = misc_register(&iop_wdt_miscdev);
|
||||
if (ret == 0)
|
||||
printk("iop watchdog timer: timeout %lu sec\n",
|
||||
iop_watchdog_timeout());
|
||||
|
||||
/* check if the reset was caused by the watchdog timer */
|
||||
boot_status = (read_rcsr() & IOP_RCSR_WDT) ? WDIOF_CARDRESET : 0;
|
||||
|
||||
/* Configure Watchdog Timeout to cause an Internal Bus (IB) Reset
|
||||
* NOTE: An IB Reset will Reset both cores in the IOP342
|
||||
*/
|
||||
write_wdtsr(IOP13XX_WDTCR_IB_RESET);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit iop_wdt_exit(void)
|
||||
{
|
||||
misc_deregister(&iop_wdt_miscdev);
|
||||
}
|
||||
|
||||
module_init(iop_wdt_init);
|
||||
module_exit(iop_wdt_exit);
|
||||
|
||||
module_param(nowayout, int, 0);
|
||||
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
|
||||
|
||||
MODULE_AUTHOR("Curt E Bruns <curt.e.bruns@intel.com>");
|
||||
MODULE_DESCRIPTION("iop watchdog timer driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
|
||||
|
|
@ -321,6 +321,7 @@ static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
|
|||
break;
|
||||
|
||||
case WDIOC_GETSTATUS:
|
||||
case WDIOC_GETBOOTSTATUS:
|
||||
return put_user(0, p);
|
||||
|
||||
case WDIOC_KEEPALIVE:
|
||||
|
|
|
|||
|
|
@ -215,6 +215,11 @@ static int mixcomwd_ioctl(struct inode *inode, struct file *file,
|
|||
return -EFAULT;
|
||||
}
|
||||
break;
|
||||
case WDIOC_GETBOOTSTATUS:
|
||||
if (copy_to_user(p, &status, sizeof(int))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
break;
|
||||
case WDIOC_GETSUPPORT:
|
||||
if (copy_to_user(argp, &ident, sizeof(ident))) {
|
||||
return -EFAULT;
|
||||
|
|
|
|||
286
drivers/char/watchdog/mpc5200_wdt.c
Normal file
286
drivers/char/watchdog/mpc5200_wdt.c
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/watchdog.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/of_platform.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/mpc52xx.h>
|
||||
|
||||
|
||||
#define GPT_MODE_WDT (1<<15)
|
||||
#define GPT_MODE_CE (1<<12)
|
||||
#define GPT_MODE_MS_TIMER (0x4)
|
||||
|
||||
|
||||
struct mpc5200_wdt {
|
||||
unsigned count; /* timer ticks before watchdog kicks in */
|
||||
long ipb_freq;
|
||||
struct miscdevice miscdev;
|
||||
struct resource mem;
|
||||
struct mpc52xx_gpt __iomem *regs;
|
||||
spinlock_t io_lock;
|
||||
};
|
||||
|
||||
/* is_active stores wether or not the /dev/watchdog device is opened */
|
||||
static unsigned long is_active;
|
||||
|
||||
/* misc devices don't provide a way, to get back to 'dev' or 'miscdev' from
|
||||
* file operations, which sucks. But there can be max 1 watchdog anyway, so...
|
||||
*/
|
||||
static struct mpc5200_wdt *wdt_global;
|
||||
|
||||
|
||||
/* helper to calculate timeout in timer counts */
|
||||
static void mpc5200_wdt_set_timeout(struct mpc5200_wdt *wdt, int timeout)
|
||||
{
|
||||
/* use biggest prescaler of 64k */
|
||||
wdt->count = (wdt->ipb_freq + 0xffff) / 0x10000 * timeout;
|
||||
|
||||
if (wdt->count > 0xffff)
|
||||
wdt->count = 0xffff;
|
||||
}
|
||||
/* return timeout in seconds (calculated from timer count) */
|
||||
static int mpc5200_wdt_get_timeout(struct mpc5200_wdt *wdt)
|
||||
{
|
||||
return wdt->count * 0x10000 / wdt->ipb_freq;
|
||||
}
|
||||
|
||||
|
||||
/* watchdog operations */
|
||||
static int mpc5200_wdt_start(struct mpc5200_wdt *wdt)
|
||||
{
|
||||
spin_lock(&wdt->io_lock);
|
||||
/* disable */
|
||||
out_be32(&wdt->regs->mode, 0);
|
||||
/* set timeout, with maximum prescaler */
|
||||
out_be32(&wdt->regs->count, 0x0 | wdt->count);
|
||||
/* enable watchdog */
|
||||
out_be32(&wdt->regs->mode, GPT_MODE_CE | GPT_MODE_WDT | GPT_MODE_MS_TIMER);
|
||||
spin_unlock(&wdt->io_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int mpc5200_wdt_ping(struct mpc5200_wdt *wdt)
|
||||
{
|
||||
spin_lock(&wdt->io_lock);
|
||||
/* writing A5 to OCPW resets the watchdog */
|
||||
out_be32(&wdt->regs->mode, 0xA5000000 | (0xffffff & in_be32(&wdt->regs->mode)));
|
||||
spin_unlock(&wdt->io_lock);
|
||||
return 0;
|
||||
}
|
||||
static int mpc5200_wdt_stop(struct mpc5200_wdt *wdt)
|
||||
{
|
||||
spin_lock(&wdt->io_lock);
|
||||
/* disable */
|
||||
out_be32(&wdt->regs->mode, 0);
|
||||
spin_unlock(&wdt->io_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* file operations */
|
||||
static ssize_t mpc5200_wdt_write(struct file *file, const char *data,
|
||||
size_t len, loff_t *ppos)
|
||||
{
|
||||
struct mpc5200_wdt *wdt = file->private_data;
|
||||
mpc5200_wdt_ping(wdt);
|
||||
return 0;
|
||||
}
|
||||
static struct watchdog_info mpc5200_wdt_info = {
|
||||
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
|
||||
.identity = "mpc5200 watchdog on GPT0",
|
||||
};
|
||||
static int mpc5200_wdt_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct mpc5200_wdt *wdt = file->private_data;
|
||||
int __user *data = (int __user *)arg;
|
||||
int timeout;
|
||||
int ret = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case WDIOC_GETSUPPORT:
|
||||
ret = copy_to_user(data, &mpc5200_wdt_info,
|
||||
sizeof(mpc5200_wdt_info));
|
||||
if (ret)
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
|
||||
case WDIOC_GETSTATUS:
|
||||
case WDIOC_GETBOOTSTATUS:
|
||||
ret = put_user(0, data);
|
||||
break;
|
||||
|
||||
case WDIOC_KEEPALIVE:
|
||||
mpc5200_wdt_ping(wdt);
|
||||
break;
|
||||
|
||||
case WDIOC_SETTIMEOUT:
|
||||
ret = get_user(timeout, data);
|
||||
if (ret)
|
||||
break;
|
||||
mpc5200_wdt_set_timeout(wdt, timeout);
|
||||
mpc5200_wdt_start(wdt);
|
||||
/* fall through and return the timeout */
|
||||
|
||||
case WDIOC_GETTIMEOUT:
|
||||
timeout = mpc5200_wdt_get_timeout(wdt);
|
||||
ret = put_user(timeout, data);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -ENOTTY;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static int mpc5200_wdt_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
/* /dev/watchdog can only be opened once */
|
||||
if (test_and_set_bit(0, &is_active))
|
||||
return -EBUSY;
|
||||
|
||||
/* Set and activate the watchdog */
|
||||
mpc5200_wdt_set_timeout(wdt_global, 30);
|
||||
mpc5200_wdt_start(wdt_global);
|
||||
file->private_data = wdt_global;
|
||||
return nonseekable_open(inode, file);
|
||||
}
|
||||
static int mpc5200_wdt_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
#if WATCHDOG_NOWAYOUT == 0
|
||||
struct mpc5200_wdt *wdt = file->private_data;
|
||||
mpc5200_wdt_stop(wdt);
|
||||
wdt->count = 0; /* == disabled */
|
||||
#endif
|
||||
clear_bit(0, &is_active);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct file_operations mpc5200_wdt_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.write = mpc5200_wdt_write,
|
||||
.ioctl = mpc5200_wdt_ioctl,
|
||||
.open = mpc5200_wdt_open,
|
||||
.release = mpc5200_wdt_release,
|
||||
};
|
||||
|
||||
/* module operations */
|
||||
static int mpc5200_wdt_probe(struct of_device *op, const struct of_device_id *match)
|
||||
{
|
||||
struct mpc5200_wdt *wdt;
|
||||
int err;
|
||||
const void *has_wdt;
|
||||
int size;
|
||||
|
||||
has_wdt = of_get_property(op->node, "has-wdt", NULL);
|
||||
if (!has_wdt)
|
||||
return -ENODEV;
|
||||
|
||||
wdt = kzalloc(sizeof(*wdt), GFP_KERNEL);
|
||||
if (!wdt)
|
||||
return -ENOMEM;
|
||||
|
||||
wdt->ipb_freq = mpc52xx_find_ipb_freq(op->node);
|
||||
|
||||
err = of_address_to_resource(op->node, 0, &wdt->mem);
|
||||
if (err)
|
||||
goto out_free;
|
||||
size = wdt->mem.end - wdt->mem.start + 1;
|
||||
if (!request_mem_region(wdt->mem.start, size, "mpc5200_wdt")) {
|
||||
err = -ENODEV;
|
||||
goto out_free;
|
||||
}
|
||||
wdt->regs = ioremap(wdt->mem.start, size);
|
||||
if (!wdt->regs) {
|
||||
err = -ENODEV;
|
||||
goto out_release;
|
||||
}
|
||||
|
||||
dev_set_drvdata(&op->dev, wdt);
|
||||
spin_lock_init(&wdt->io_lock);
|
||||
|
||||
wdt->miscdev = (struct miscdevice) {
|
||||
.minor = WATCHDOG_MINOR,
|
||||
.name = "watchdog",
|
||||
.fops = &mpc5200_wdt_fops,
|
||||
.parent = &op->dev,
|
||||
};
|
||||
wdt_global = wdt;
|
||||
err = misc_register(&wdt->miscdev);
|
||||
if (!err)
|
||||
return 0;
|
||||
|
||||
iounmap(wdt->regs);
|
||||
out_release:
|
||||
release_mem_region(wdt->mem.start, size);
|
||||
out_free:
|
||||
kfree(wdt);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mpc5200_wdt_remove(struct of_device *op)
|
||||
{
|
||||
struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev);
|
||||
|
||||
mpc5200_wdt_stop(wdt);
|
||||
misc_deregister(&wdt->miscdev);
|
||||
iounmap(wdt->regs);
|
||||
release_mem_region(wdt->mem.start, wdt->mem.end - wdt->mem.start + 1);
|
||||
kfree(wdt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int mpc5200_wdt_suspend(struct of_device *op, pm_message_t state)
|
||||
{
|
||||
struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev);
|
||||
mpc5200_wdt_stop(wdt);
|
||||
return 0;
|
||||
}
|
||||
static int mpc5200_wdt_resume(struct of_device *op)
|
||||
{
|
||||
struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev);
|
||||
if (wdt->count)
|
||||
mpc5200_wdt_start(wdt);
|
||||
return 0;
|
||||
}
|
||||
static int mpc5200_wdt_shutdown(struct of_device *op)
|
||||
{
|
||||
struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev);
|
||||
mpc5200_wdt_stop(wdt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id mpc5200_wdt_match[] = {
|
||||
{ .compatible = "mpc5200-gpt", },
|
||||
{},
|
||||
};
|
||||
static struct of_platform_driver mpc5200_wdt_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "mpc5200-gpt-wdt",
|
||||
.match_table = mpc5200_wdt_match,
|
||||
.probe = mpc5200_wdt_probe,
|
||||
.remove = mpc5200_wdt_remove,
|
||||
.suspend = mpc5200_wdt_suspend,
|
||||
.resume = mpc5200_wdt_resume,
|
||||
.shutdown = mpc5200_wdt_shutdown,
|
||||
};
|
||||
|
||||
|
||||
static int __init mpc5200_wdt_init(void)
|
||||
{
|
||||
return of_register_platform_driver(&mpc5200_wdt_driver);
|
||||
}
|
||||
|
||||
static void __exit mpc5200_wdt_exit(void)
|
||||
{
|
||||
of_unregister_platform_driver(&mpc5200_wdt_driver);
|
||||
}
|
||||
|
||||
module_init(mpc5200_wdt_init);
|
||||
module_exit(mpc5200_wdt_exit);
|
||||
|
||||
MODULE_AUTHOR("Domen Puncer <domen.puncer@telargo.com>");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
|
||||
|
|
@ -119,6 +119,9 @@ static int mpc83xx_wdt_ioctl(struct inode *inode, struct file *file,
|
|||
switch (cmd) {
|
||||
case WDIOC_GETSUPPORT:
|
||||
return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
|
||||
case WDIOC_GETSTATUS:
|
||||
case WDIOC_GETBOOTSTATUS:
|
||||
return put_user(0, p);
|
||||
case WDIOC_KEEPALIVE:
|
||||
mpc83xx_wdt_keepalive();
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ static int mpc8xx_wdt_open(struct inode *inode, struct file *file)
|
|||
m8xx_wdt_reset();
|
||||
mpc8xx_wdt_handler_disable();
|
||||
|
||||
return 0;
|
||||
return nonseekable_open(inode, file);
|
||||
}
|
||||
|
||||
static int mpc8xx_wdt_release(struct inode *inode, struct file *file)
|
||||
|
|
|
|||
|
|
@ -328,12 +328,11 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev)
|
|||
goto err_out;
|
||||
}
|
||||
|
||||
wdt = kmalloc(sizeof(struct mpcore_wdt), GFP_KERNEL);
|
||||
wdt = kzalloc(sizeof(struct mpcore_wdt), GFP_KERNEL);
|
||||
if (!wdt) {
|
||||
ret = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
memset(wdt, 0, sizeof(struct mpcore_wdt));
|
||||
|
||||
wdt->dev = &dev->dev;
|
||||
wdt->irq = platform_get_irq(dev, 0);
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ static int mtx1_wdt_ioctl(struct inode *inode, struct file *file, unsigned int c
|
|||
mtx1_wdt_reset();
|
||||
break;
|
||||
case WDIOC_GETSTATUS:
|
||||
case WDIOC_GETBOOTSTATUS:
|
||||
if ( copy_to_user(argp, &value, sizeof(int)) )
|
||||
return -EFAULT;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -23,83 +23,126 @@
|
|||
#include <linux/watchdog.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/mv64x60.h>
|
||||
#include <linux/mv643xx.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
/* MV64x60 WDC (config) register access definitions */
|
||||
#define MV64x60_WDC_CTL1_MASK (3 << 24)
|
||||
#define MV64x60_WDC_CTL1(val) ((val & 3) << 24)
|
||||
#define MV64x60_WDC_CTL2_MASK (3 << 26)
|
||||
#define MV64x60_WDC_CTL2(val) ((val & 3) << 26)
|
||||
#define MV64x60_WDT_WDC_OFFSET 0
|
||||
|
||||
/*
|
||||
* The watchdog configuration register contains a pair of 2-bit fields,
|
||||
* 1. a reload field, bits 27-26, which triggers a reload of
|
||||
* the countdown register, and
|
||||
* 2. an enable field, bits 25-24, which toggles between
|
||||
* enabling and disabling the watchdog timer.
|
||||
* Bit 31 is a read-only field which indicates whether the
|
||||
* watchdog timer is currently enabled.
|
||||
*
|
||||
* The low 24 bits contain the timer reload value.
|
||||
*/
|
||||
#define MV64x60_WDC_ENABLE_SHIFT 24
|
||||
#define MV64x60_WDC_SERVICE_SHIFT 26
|
||||
#define MV64x60_WDC_ENABLED_SHIFT 31
|
||||
|
||||
#define MV64x60_WDC_ENABLED_TRUE 1
|
||||
#define MV64x60_WDC_ENABLED_FALSE 0
|
||||
|
||||
/* Flags bits */
|
||||
#define MV64x60_WDOG_FLAG_OPENED 0
|
||||
#define MV64x60_WDOG_FLAG_ENABLED 1
|
||||
|
||||
static unsigned long wdt_flags;
|
||||
static int wdt_status;
|
||||
static void __iomem *mv64x60_regs;
|
||||
static void __iomem *mv64x60_wdt_regs;
|
||||
static int mv64x60_wdt_timeout;
|
||||
static int mv64x60_wdt_count;
|
||||
static unsigned int bus_clk;
|
||||
static char expect_close;
|
||||
static DEFINE_SPINLOCK(mv64x60_wdt_spinlock);
|
||||
|
||||
static void mv64x60_wdt_reg_write(u32 val)
|
||||
static int nowayout = WATCHDOG_NOWAYOUT;
|
||||
module_param(nowayout, int, 0);
|
||||
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
|
||||
|
||||
static int mv64x60_wdt_toggle_wdc(int enabled_predicate, int field_shift)
|
||||
{
|
||||
/* Allow write only to CTL1 / CTL2 fields, retaining values in
|
||||
* other fields.
|
||||
*/
|
||||
u32 data = readl(mv64x60_regs + MV64x60_WDT_WDC);
|
||||
data &= ~(MV64x60_WDC_CTL1_MASK | MV64x60_WDC_CTL2_MASK);
|
||||
data |= val;
|
||||
writel(data, mv64x60_regs + MV64x60_WDT_WDC);
|
||||
u32 data;
|
||||
u32 enabled;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock(&mv64x60_wdt_spinlock);
|
||||
data = readl(mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET);
|
||||
enabled = (data >> MV64x60_WDC_ENABLED_SHIFT) & 1;
|
||||
|
||||
/* only toggle the requested field if enabled state matches predicate */
|
||||
if ((enabled ^ enabled_predicate) == 0) {
|
||||
/* We write a 1, then a 2 -- to the appropriate field */
|
||||
data = (1 << field_shift) | mv64x60_wdt_count;
|
||||
writel(data, mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET);
|
||||
|
||||
data = (2 << field_shift) | mv64x60_wdt_count;
|
||||
writel(data, mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET);
|
||||
ret = 1;
|
||||
}
|
||||
spin_unlock(&mv64x60_wdt_spinlock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mv64x60_wdt_service(void)
|
||||
{
|
||||
/* Write 01 followed by 10 to CTL2 */
|
||||
mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x01));
|
||||
mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x02));
|
||||
}
|
||||
|
||||
static void mv64x60_wdt_handler_disable(void)
|
||||
{
|
||||
if (test_and_clear_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) {
|
||||
/* Write 01 followed by 10 to CTL1 */
|
||||
mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01));
|
||||
mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02));
|
||||
printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n");
|
||||
}
|
||||
mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_TRUE,
|
||||
MV64x60_WDC_SERVICE_SHIFT);
|
||||
}
|
||||
|
||||
static void mv64x60_wdt_handler_enable(void)
|
||||
{
|
||||
if (!test_and_set_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) {
|
||||
/* Write 01 followed by 10 to CTL1 */
|
||||
mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01));
|
||||
mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02));
|
||||
if (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_FALSE,
|
||||
MV64x60_WDC_ENABLE_SHIFT)) {
|
||||
mv64x60_wdt_service();
|
||||
printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void mv64x60_wdt_handler_disable(void)
|
||||
{
|
||||
if (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_TRUE,
|
||||
MV64x60_WDC_ENABLE_SHIFT))
|
||||
printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n");
|
||||
}
|
||||
|
||||
static void mv64x60_wdt_set_timeout(unsigned int timeout)
|
||||
{
|
||||
/* maximum bus cycle count is 0xFFFFFFFF */
|
||||
if (timeout > 0xFFFFFFFF / bus_clk)
|
||||
timeout = 0xFFFFFFFF / bus_clk;
|
||||
|
||||
mv64x60_wdt_count = timeout * bus_clk >> 8;
|
||||
mv64x60_wdt_timeout = timeout;
|
||||
}
|
||||
|
||||
static int mv64x60_wdt_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags))
|
||||
return -EBUSY;
|
||||
|
||||
mv64x60_wdt_service();
|
||||
if (nowayout)
|
||||
__module_get(THIS_MODULE);
|
||||
|
||||
mv64x60_wdt_handler_enable();
|
||||
|
||||
nonseekable_open(inode, file);
|
||||
|
||||
return 0;
|
||||
return nonseekable_open(inode, file);
|
||||
}
|
||||
|
||||
static int mv64x60_wdt_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
mv64x60_wdt_service();
|
||||
|
||||
#if !defined(CONFIG_WATCHDOG_NOWAYOUT)
|
||||
mv64x60_wdt_handler_disable();
|
||||
#endif
|
||||
if (expect_close == 42)
|
||||
mv64x60_wdt_handler_disable();
|
||||
else {
|
||||
printk(KERN_CRIT
|
||||
"mv64x60_wdt: unexpected close, not stopping timer!\n");
|
||||
mv64x60_wdt_service();
|
||||
}
|
||||
expect_close = 0;
|
||||
|
||||
clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags);
|
||||
|
||||
|
|
@ -109,8 +152,22 @@ static int mv64x60_wdt_release(struct inode *inode, struct file *file)
|
|||
static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data,
|
||||
size_t len, loff_t * ppos)
|
||||
{
|
||||
if (len)
|
||||
if (len) {
|
||||
if (!nowayout) {
|
||||
size_t i;
|
||||
|
||||
expect_close = 0;
|
||||
|
||||
for (i = 0; i != len; i++) {
|
||||
char c;
|
||||
if(get_user(c, data + i))
|
||||
return -EFAULT;
|
||||
if (c == 'V')
|
||||
expect_close = 42;
|
||||
}
|
||||
}
|
||||
mv64x60_wdt_service();
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
|
@ -119,9 +176,12 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file,
|
|||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int timeout;
|
||||
int options;
|
||||
void __user *argp = (void __user *)arg;
|
||||
static struct watchdog_info info = {
|
||||
.options = WDIOF_KEEPALIVEPING,
|
||||
.options = WDIOF_SETTIMEOUT |
|
||||
WDIOF_MAGICCLOSE |
|
||||
WDIOF_KEEPALIVEPING,
|
||||
.firmware_version = 0,
|
||||
.identity = "MV64x60 watchdog",
|
||||
};
|
||||
|
|
@ -143,7 +203,15 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file,
|
|||
return -EOPNOTSUPP;
|
||||
|
||||
case WDIOC_SETOPTIONS:
|
||||
return -EOPNOTSUPP;
|
||||
if (get_user(options, (int __user *)argp))
|
||||
return -EFAULT;
|
||||
|
||||
if (options & WDIOS_DISABLECARD)
|
||||
mv64x60_wdt_handler_disable();
|
||||
|
||||
if (options & WDIOS_ENABLECARD)
|
||||
mv64x60_wdt_handler_enable();
|
||||
break;
|
||||
|
||||
case WDIOC_KEEPALIVE:
|
||||
mv64x60_wdt_service();
|
||||
|
|
@ -151,11 +219,13 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file,
|
|||
break;
|
||||
|
||||
case WDIOC_SETTIMEOUT:
|
||||
return -EOPNOTSUPP;
|
||||
if (get_user(timeout, (int __user *)argp))
|
||||
return -EFAULT;
|
||||
mv64x60_wdt_set_timeout(timeout);
|
||||
/* Fall through */
|
||||
|
||||
case WDIOC_GETTIMEOUT:
|
||||
timeout = mv64x60_wdt_timeout * HZ;
|
||||
if (put_user(timeout, (int __user *)argp))
|
||||
if (put_user(mv64x60_wdt_timeout, (int __user *)argp))
|
||||
return -EFAULT;
|
||||
break;
|
||||
|
||||
|
|
@ -184,18 +254,33 @@ static struct miscdevice mv64x60_wdt_miscdev = {
|
|||
static int __devinit mv64x60_wdt_probe(struct platform_device *dev)
|
||||
{
|
||||
struct mv64x60_wdt_pdata *pdata = dev->dev.platform_data;
|
||||
int bus_clk = 133;
|
||||
struct resource *r;
|
||||
int timeout = 10;
|
||||
|
||||
mv64x60_wdt_timeout = 10;
|
||||
bus_clk = 133; /* in MHz */
|
||||
if (pdata) {
|
||||
mv64x60_wdt_timeout = pdata->timeout;
|
||||
timeout = pdata->timeout;
|
||||
bus_clk = pdata->bus_clk;
|
||||
}
|
||||
|
||||
mv64x60_regs = mv64x60_get_bridge_vbase();
|
||||
/* Since bus_clk is truncated MHz, actual frequency could be
|
||||
* up to 1MHz higher. Round up, since it's better to time out
|
||||
* too late than too soon.
|
||||
*/
|
||||
bus_clk++;
|
||||
bus_clk *= 1000000; /* convert to Hz */
|
||||
|
||||
writel((mv64x60_wdt_timeout * (bus_clk * 1000000)) >> 8,
|
||||
mv64x60_regs + MV64x60_WDT_WDC);
|
||||
r = platform_get_resource(dev, IORESOURCE_MEM, 0);
|
||||
if (!r)
|
||||
return -ENODEV;
|
||||
|
||||
mv64x60_wdt_regs = ioremap(r->start, r->end - r->start + 1);
|
||||
if (mv64x60_wdt_regs == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
mv64x60_wdt_set_timeout(timeout);
|
||||
|
||||
mv64x60_wdt_handler_disable(); /* in case timer was already running */
|
||||
|
||||
return misc_register(&mv64x60_wdt_miscdev);
|
||||
}
|
||||
|
|
@ -204,9 +289,10 @@ static int __devexit mv64x60_wdt_remove(struct platform_device *dev)
|
|||
{
|
||||
misc_deregister(&mv64x60_wdt_miscdev);
|
||||
|
||||
mv64x60_wdt_service();
|
||||
mv64x60_wdt_handler_disable();
|
||||
|
||||
iounmap(mv64x60_wdt_regs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -219,40 +305,16 @@ static struct platform_driver mv64x60_wdt_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct platform_device *mv64x60_wdt_dev;
|
||||
|
||||
static int __init mv64x60_wdt_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printk(KERN_INFO "MV64x60 watchdog driver\n");
|
||||
|
||||
mv64x60_wdt_dev = platform_device_alloc(MV64x60_WDT_NAME, -1);
|
||||
if (!mv64x60_wdt_dev) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = platform_device_add(mv64x60_wdt_dev);
|
||||
if (ret) {
|
||||
platform_device_put(mv64x60_wdt_dev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = platform_driver_register(&mv64x60_wdt_driver);
|
||||
if (ret) {
|
||||
platform_device_unregister(mv64x60_wdt_dev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return platform_driver_register(&mv64x60_wdt_driver);
|
||||
}
|
||||
|
||||
static void __exit mv64x60_wdt_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&mv64x60_wdt_driver);
|
||||
platform_device_unregister(mv64x60_wdt_dev);
|
||||
}
|
||||
|
||||
module_init(mv64x60_wdt_init);
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ static int omap_wdt_open(struct inode *inode, struct file *file)
|
|||
|
||||
omap_wdt_set_timeout();
|
||||
omap_wdt_enable();
|
||||
return 0;
|
||||
return nonseekable_open(inode, file);
|
||||
}
|
||||
|
||||
static int omap_wdt_release(struct inode *inode, struct file *file)
|
||||
|
|
@ -197,7 +197,7 @@ omap_wdt_ioctl(struct inode *inode, struct file *file,
|
|||
|
||||
switch (cmd) {
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
return -ENOTTY;
|
||||
case WDIOC_GETSUPPORT:
|
||||
return copy_to_user((struct watchdog_info __user *)arg, &ident,
|
||||
sizeof(ident));
|
||||
|
|
|
|||
|
|
@ -626,12 +626,11 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi
|
|||
maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
|
||||
|
||||
/* allocate memory for our device and initialize it */
|
||||
usb_pcwd = kmalloc (sizeof(struct usb_pcwd_private), GFP_KERNEL);
|
||||
usb_pcwd = kzalloc (sizeof(struct usb_pcwd_private), GFP_KERNEL);
|
||||
if (usb_pcwd == NULL) {
|
||||
printk(KERN_ERR PFX "Out of memory\n");
|
||||
goto error;
|
||||
}
|
||||
memset (usb_pcwd, 0x00, sizeof (*usb_pcwd));
|
||||
|
||||
usb_pcwd_device = usb_pcwd;
|
||||
|
||||
|
|
|
|||
|
|
@ -52,10 +52,10 @@
|
|||
|
||||
#include <asm/arch/map.h>
|
||||
|
||||
#undef S3C24XX_VA_WATCHDOG
|
||||
#define S3C24XX_VA_WATCHDOG (0)
|
||||
#undef S3C_VA_WATCHDOG
|
||||
#define S3C_VA_WATCHDOG (0)
|
||||
|
||||
#include <asm/arch/regs-watchdog.h>
|
||||
#include <asm/plat-s3c/regs-watchdog.h>
|
||||
|
||||
#define PFX "s3c2410-wdt: "
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ static int boot_status;
|
|||
*/
|
||||
static int sa1100dog_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
nonseekable_open(inode, file);
|
||||
if (test_and_set_bit(1,&sa1100wdt_users))
|
||||
return -EBUSY;
|
||||
|
||||
|
|
@ -54,7 +53,7 @@ static int sa1100dog_open(struct inode *inode, struct file *file)
|
|||
OSSR = OSSR_M3;
|
||||
OWER = OWER_WME;
|
||||
OIER |= OIER_E3;
|
||||
return 0;
|
||||
return nonseekable_open(inode, file);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue