diff options
Diffstat (limited to 'drivers/char')
68 files changed, 2648 insertions, 1777 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 889cad07774e..78d928f9d9f1 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -291,7 +291,7 @@ config SX | |||
291 | 291 | ||
292 | config RIO | 292 | config RIO |
293 | tristate "Specialix RIO system support" | 293 | tristate "Specialix RIO system support" |
294 | depends on SERIAL_NONSTANDARD && !64BIT | 294 | depends on SERIAL_NONSTANDARD |
295 | help | 295 | help |
296 | This is a driver for the Specialix RIO, a smart serial card which | 296 | This is a driver for the Specialix RIO, a smart serial card which |
297 | drives an outboard box that can support up to 128 ports. Product | 297 | drives an outboard box that can support up to 128 ports. Product |
@@ -805,10 +805,6 @@ config S3C2410_RTC | |||
805 | Samsung S3C2410. This can provide periodic interrupt rates | 805 | Samsung S3C2410. This can provide periodic interrupt rates |
806 | from 1Hz to 64Hz for user programs, and wakeup from Alarm. | 806 | from 1Hz to 64Hz for user programs, and wakeup from Alarm. |
807 | 807 | ||
808 | config RTC_VR41XX | ||
809 | tristate "NEC VR4100 series Real Time Clock Support" | ||
810 | depends on CPU_VR41XX | ||
811 | |||
812 | config COBALT_LCD | 808 | config COBALT_LCD |
813 | bool "Support for Cobalt LCD" | 809 | bool "Support for Cobalt LCD" |
814 | depends on MIPS_COBALT | 810 | depends on MIPS_COBALT |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index a73cb4956928..fb919bfb2824 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -41,9 +41,9 @@ obj-$(CONFIG_N_HDLC) += n_hdlc.o | |||
41 | obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o | 41 | obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o |
42 | obj-$(CONFIG_SX) += sx.o generic_serial.o | 42 | obj-$(CONFIG_SX) += sx.o generic_serial.o |
43 | obj-$(CONFIG_RIO) += rio/ generic_serial.o | 43 | obj-$(CONFIG_RIO) += rio/ generic_serial.o |
44 | obj-$(CONFIG_HVC_DRIVER) += hvc_console.o | ||
45 | obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o | 44 | obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o |
46 | obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o | 45 | obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o |
46 | obj-$(CONFIG_HVC_DRIVER) += hvc_console.o | ||
47 | obj-$(CONFIG_RAW_DRIVER) += raw.o | 47 | obj-$(CONFIG_RAW_DRIVER) += raw.o |
48 | obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o | 48 | obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o |
49 | obj-$(CONFIG_MMTIMER) += mmtimer.o | 49 | obj-$(CONFIG_MMTIMER) += mmtimer.o |
@@ -67,7 +67,6 @@ obj-$(CONFIG_SGI_DS1286) += ds1286.o | |||
67 | obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o | 67 | obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o |
68 | obj-$(CONFIG_DS1302) += ds1302.o | 68 | obj-$(CONFIG_DS1302) += ds1302.o |
69 | obj-$(CONFIG_S3C2410_RTC) += s3c2410-rtc.o | 69 | obj-$(CONFIG_S3C2410_RTC) += s3c2410-rtc.o |
70 | obj-$(CONFIG_RTC_VR41XX) += vr41xx_rtc.o | ||
71 | ifeq ($(CONFIG_GENERIC_NVRAM),y) | 70 | ifeq ($(CONFIG_GENERIC_NVRAM),y) |
72 | obj-$(CONFIG_NVRAM) += generic_nvram.o | 71 | obj-$(CONFIG_NVRAM) += generic_nvram.o |
73 | else | 72 | else |
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index 0b9cf9c59a21..7c88c060a9e6 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig | |||
@@ -86,7 +86,7 @@ config AGP_NVIDIA | |||
86 | 86 | ||
87 | config AGP_SIS | 87 | config AGP_SIS |
88 | tristate "SiS chipset support" | 88 | tristate "SiS chipset support" |
89 | depends on AGP && X86_32 | 89 | depends on AGP |
90 | help | 90 | help |
91 | This option gives you AGP support for the GLX component of | 91 | This option gives you AGP support for the GLX component of |
92 | X on Silicon Integrated Systems [SiS] chipsets. | 92 | X on Silicon Integrated Systems [SiS] chipsets. |
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 36517d4d1ad9..ac3c33a2e37d 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c | |||
@@ -617,6 +617,9 @@ static int agp_amd64_resume(struct pci_dev *pdev) | |||
617 | pci_set_power_state(pdev, PCI_D0); | 617 | pci_set_power_state(pdev, PCI_D0); |
618 | pci_restore_state(pdev); | 618 | pci_restore_state(pdev); |
619 | 619 | ||
620 | if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) | ||
621 | nforce3_agp_init(pdev); | ||
622 | |||
620 | return amd_8151_configure(); | 623 | return amd_8151_configure(); |
621 | } | 624 | } |
622 | 625 | ||
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c index fed0a87448d8..86a966b65236 100644 --- a/drivers/char/agp/efficeon-agp.c +++ b/drivers/char/agp/efficeon-agp.c | |||
@@ -64,6 +64,12 @@ static struct gatt_mask efficeon_generic_masks[] = | |||
64 | {.mask = 0x00000001, .type = 0} | 64 | {.mask = 0x00000001, .type = 0} |
65 | }; | 65 | }; |
66 | 66 | ||
67 | /* This function does the same thing as mask_memory() for this chipset... */ | ||
68 | static inline unsigned long efficeon_mask_memory(unsigned long addr) | ||
69 | { | ||
70 | return addr | 0x00000001; | ||
71 | } | ||
72 | |||
67 | static struct aper_size_info_lvl2 efficeon_generic_sizes[4] = | 73 | static struct aper_size_info_lvl2 efficeon_generic_sizes[4] = |
68 | { | 74 | { |
69 | {256, 65536, 0}, | 75 | {256, 65536, 0}, |
@@ -251,7 +257,7 @@ static int efficeon_insert_memory(struct agp_memory * mem, off_t pg_start, int t | |||
251 | last_page = NULL; | 257 | last_page = NULL; |
252 | for (i = 0; i < count; i++) { | 258 | for (i = 0; i < count; i++) { |
253 | int index = pg_start + i; | 259 | int index = pg_start + i; |
254 | unsigned long insert = mem->memory[i]; | 260 | unsigned long insert = efficeon_mask_memory(mem->memory[i]); |
255 | 261 | ||
256 | page = (unsigned int *) efficeon_private.l1_table[index >> 10]; | 262 | page = (unsigned int *) efficeon_private.l1_table[index >> 10]; |
257 | 263 | ||
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c index 97b0a890ba7f..b8ec25d17478 100644 --- a/drivers/char/agp/via-agp.c +++ b/drivers/char/agp/via-agp.c | |||
@@ -345,6 +345,12 @@ static struct agp_device_ids via_agp_device_ids[] __devinitdata = | |||
345 | .chipset_name = "PT880", | 345 | .chipset_name = "PT880", |
346 | }, | 346 | }, |
347 | 347 | ||
348 | /* PT880 Ultra */ | ||
349 | { | ||
350 | .device_id = PCI_DEVICE_ID_VIA_PT880ULTRA, | ||
351 | .chipset_name = "PT880 Ultra", | ||
352 | }, | ||
353 | |||
348 | /* PT890 */ | 354 | /* PT890 */ |
349 | { | 355 | { |
350 | .device_id = PCI_DEVICE_ID_VIA_8783_0, | 356 | .device_id = PCI_DEVICE_ID_VIA_8783_0, |
@@ -511,6 +517,7 @@ static struct pci_device_id agp_via_pci_table[] = { | |||
511 | ID(PCI_DEVICE_ID_VIA_8763_0), | 517 | ID(PCI_DEVICE_ID_VIA_8763_0), |
512 | ID(PCI_DEVICE_ID_VIA_8378_0), | 518 | ID(PCI_DEVICE_ID_VIA_8378_0), |
513 | ID(PCI_DEVICE_ID_VIA_PT880), | 519 | ID(PCI_DEVICE_ID_VIA_PT880), |
520 | ID(PCI_DEVICE_ID_VIA_PT880ULTRA), | ||
514 | ID(PCI_DEVICE_ID_VIA_8783_0), | 521 | ID(PCI_DEVICE_ID_VIA_8783_0), |
515 | ID(PCI_DEVICE_ID_VIA_PX8X0_0), | 522 | ID(PCI_DEVICE_ID_VIA_PX8X0_0), |
516 | ID(PCI_DEVICE_ID_VIA_3269_0), | 523 | ID(PCI_DEVICE_ID_VIA_3269_0), |
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c index 927a5bbe112c..a370e7a0bad5 100644 --- a/drivers/char/applicom.c +++ b/drivers/char/applicom.c | |||
@@ -142,7 +142,7 @@ static int ac_register_board(unsigned long physloc, void __iomem *loc, | |||
142 | if (!boardno) | 142 | if (!boardno) |
143 | boardno = readb(loc + NUMCARD_OWNER_TO_PC); | 143 | boardno = readb(loc + NUMCARD_OWNER_TO_PC); |
144 | 144 | ||
145 | if (!boardno && boardno > MAX_BOARD) { | 145 | if (!boardno || boardno > MAX_BOARD) { |
146 | printk(KERN_WARNING "Board #%d (at 0x%lx) is out of range (1 <= x <= %d).\n", | 146 | printk(KERN_WARNING "Board #%d (at 0x%lx) is out of range (1 <= x <= %d).\n", |
147 | boardno, physloc, MAX_BOARD); | 147 | boardno, physloc, MAX_BOARD); |
148 | return 0; | 148 | return 0; |
diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c index 5d72f50de1ac..46d66037b917 100644 --- a/drivers/char/cs5535_gpio.c +++ b/drivers/char/cs5535_gpio.c | |||
@@ -241,9 +241,10 @@ static int __init cs5535_gpio_init(void) | |||
241 | static void __exit cs5535_gpio_cleanup(void) | 241 | static void __exit cs5535_gpio_cleanup(void) |
242 | { | 242 | { |
243 | dev_t dev_id = MKDEV(major, 0); | 243 | dev_t dev_id = MKDEV(major, 0); |
244 | |||
245 | cdev_del(&cs5535_gpio_cdev); | ||
244 | unregister_chrdev_region(dev_id, CS5535_GPIO_COUNT); | 246 | unregister_chrdev_region(dev_id, CS5535_GPIO_COUNT); |
245 | if (gpio_base != 0) | 247 | release_region(gpio_base, CS5535_GPIO_SIZE); |
246 | release_region(gpio_base, CS5535_GPIO_SIZE); | ||
247 | } | 248 | } |
248 | 249 | ||
249 | module_init(cs5535_gpio_init); | 250 | module_init(cs5535_gpio_init); |
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index edc72a6348a7..cb76e5ca9a23 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h | |||
@@ -815,8 +815,6 @@ extern int drm_mem_info(char *buf, char **start, off_t offset, | |||
815 | extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area); | 815 | extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area); |
816 | extern void *drm_ioremap(unsigned long offset, unsigned long size, | 816 | extern void *drm_ioremap(unsigned long offset, unsigned long size, |
817 | drm_device_t * dev); | 817 | drm_device_t * dev); |
818 | extern void *drm_ioremap_nocache(unsigned long offset, unsigned long size, | ||
819 | drm_device_t * dev); | ||
820 | extern void drm_ioremapfree(void *pt, unsigned long size, drm_device_t * dev); | 818 | extern void drm_ioremapfree(void *pt, unsigned long size, drm_device_t * dev); |
821 | 819 | ||
822 | extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type); | 820 | extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type); |
@@ -891,7 +889,6 @@ extern int drm_lock_free(drm_device_t * dev, | |||
891 | /* Buffer management support (drm_bufs.h) */ | 889 | /* Buffer management support (drm_bufs.h) */ |
892 | extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request); | 890 | extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request); |
893 | extern int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request); | 891 | extern int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request); |
894 | extern int drm_addbufs_fb(drm_device_t *dev, drm_buf_desc_t *request); | ||
895 | extern int drm_addmap(drm_device_t * dev, unsigned int offset, | 892 | extern int drm_addmap(drm_device_t * dev, unsigned int offset, |
896 | unsigned int size, drm_map_type_t type, | 893 | unsigned int size, drm_map_type_t type, |
897 | drm_map_flags_t flags, drm_local_map_t ** map_ptr); | 894 | drm_map_flags_t flags, drm_local_map_t ** map_ptr); |
@@ -1022,11 +1019,13 @@ static __inline__ void drm_core_ioremap(struct drm_map *map, | |||
1022 | map->handle = drm_ioremap(map->offset, map->size, dev); | 1019 | map->handle = drm_ioremap(map->offset, map->size, dev); |
1023 | } | 1020 | } |
1024 | 1021 | ||
1022 | #if 0 | ||
1025 | static __inline__ void drm_core_ioremap_nocache(struct drm_map *map, | 1023 | static __inline__ void drm_core_ioremap_nocache(struct drm_map *map, |
1026 | struct drm_device *dev) | 1024 | struct drm_device *dev) |
1027 | { | 1025 | { |
1028 | map->handle = drm_ioremap_nocache(map->offset, map->size, dev); | 1026 | map->handle = drm_ioremap_nocache(map->offset, map->size, dev); |
1029 | } | 1027 | } |
1028 | #endif /* 0 */ | ||
1030 | 1029 | ||
1031 | static __inline__ void drm_core_ioremapfree(struct drm_map *map, | 1030 | static __inline__ void drm_core_ioremapfree(struct drm_map *map, |
1032 | struct drm_device *dev) | 1031 | struct drm_device *dev) |
diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c index fabc930c67a2..40bfd9b01e39 100644 --- a/drivers/char/drm/drm_agpsupport.c +++ b/drivers/char/drm/drm_agpsupport.c | |||
@@ -503,8 +503,6 @@ int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start) | |||
503 | return agp_bind_memory(handle, start); | 503 | return agp_bind_memory(handle, start); |
504 | } | 504 | } |
505 | 505 | ||
506 | EXPORT_SYMBOL(drm_agp_bind_memory); | ||
507 | |||
508 | /** Calls agp_unbind_memory() */ | 506 | /** Calls agp_unbind_memory() */ |
509 | int drm_agp_unbind_memory(DRM_AGP_MEM * handle) | 507 | int drm_agp_unbind_memory(DRM_AGP_MEM * handle) |
510 | { | 508 | { |
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index 8a9cf12e6183..006b06d29727 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c | |||
@@ -386,7 +386,6 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map) | |||
386 | 386 | ||
387 | return 0; | 387 | return 0; |
388 | } | 388 | } |
389 | EXPORT_SYMBOL(drm_rmmap_locked); | ||
390 | 389 | ||
391 | int drm_rmmap(drm_device_t *dev, drm_local_map_t *map) | 390 | int drm_rmmap(drm_device_t *dev, drm_local_map_t *map) |
392 | { | 391 | { |
@@ -398,7 +397,6 @@ int drm_rmmap(drm_device_t *dev, drm_local_map_t *map) | |||
398 | 397 | ||
399 | return ret; | 398 | return ret; |
400 | } | 399 | } |
401 | EXPORT_SYMBOL(drm_rmmap); | ||
402 | 400 | ||
403 | /* The rmmap ioctl appears to be unnecessary. All mappings are torn down on | 401 | /* The rmmap ioctl appears to be unnecessary. All mappings are torn down on |
404 | * the last close of the device, and this is necessary for cleanup when things | 402 | * the last close of the device, and this is necessary for cleanup when things |
@@ -1053,7 +1051,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) | |||
1053 | return 0; | 1051 | return 0; |
1054 | } | 1052 | } |
1055 | 1053 | ||
1056 | int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) | 1054 | static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) |
1057 | { | 1055 | { |
1058 | drm_device_dma_t *dma = dev->dma; | 1056 | drm_device_dma_t *dma = dev->dma; |
1059 | drm_buf_entry_t *entry; | 1057 | drm_buf_entry_t *entry; |
@@ -1212,7 +1210,6 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) | |||
1212 | atomic_dec(&dev->buf_alloc); | 1210 | atomic_dec(&dev->buf_alloc); |
1213 | return 0; | 1211 | return 0; |
1214 | } | 1212 | } |
1215 | EXPORT_SYMBOL(drm_addbufs_fb); | ||
1216 | 1213 | ||
1217 | 1214 | ||
1218 | /** | 1215 | /** |
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c index dc6bbe8a18dc..3c0b882a8e72 100644 --- a/drivers/char/drm/drm_drv.c +++ b/drivers/char/drm/drm_drv.c | |||
@@ -75,8 +75,8 @@ static drm_ioctl_desc_t drm_ioctls[] = { | |||
75 | [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = {drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, | 75 | [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = {drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
76 | [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = {drm_getsareactx, DRM_AUTH}, | 76 | [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = {drm_getsareactx, DRM_AUTH}, |
77 | 77 | ||
78 | [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, | 78 | [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_ROOT_ONLY}, |
79 | [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, | 79 | [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_ROOT_ONLY}, |
80 | [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, | 80 | [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
81 | [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, DRM_AUTH}, | 81 | [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, DRM_AUTH}, |
82 | [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, | 82 | [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c index dddf8de66143..7e3318e1d1c6 100644 --- a/drivers/char/drm/drm_memory.c +++ b/drivers/char/drm/drm_memory.c | |||
@@ -80,6 +80,71 @@ void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area) | |||
80 | } | 80 | } |
81 | 81 | ||
82 | #if __OS_HAS_AGP | 82 | #if __OS_HAS_AGP |
83 | /* | ||
84 | * Find the drm_map that covers the range [offset, offset+size). | ||
85 | */ | ||
86 | static drm_map_t *drm_lookup_map(unsigned long offset, | ||
87 | unsigned long size, drm_device_t * dev) | ||
88 | { | ||
89 | struct list_head *list; | ||
90 | drm_map_list_t *r_list; | ||
91 | drm_map_t *map; | ||
92 | |||
93 | list_for_each(list, &dev->maplist->head) { | ||
94 | r_list = (drm_map_list_t *) list; | ||
95 | map = r_list->map; | ||
96 | if (!map) | ||
97 | continue; | ||
98 | if (map->offset <= offset | ||
99 | && (offset + size) <= (map->offset + map->size)) | ||
100 | return map; | ||
101 | } | ||
102 | return NULL; | ||
103 | } | ||
104 | |||
105 | static void *agp_remap(unsigned long offset, unsigned long size, | ||
106 | drm_device_t * dev) | ||
107 | { | ||
108 | unsigned long *phys_addr_map, i, num_pages = | ||
109 | PAGE_ALIGN(size) / PAGE_SIZE; | ||
110 | struct drm_agp_mem *agpmem; | ||
111 | struct page **page_map; | ||
112 | void *addr; | ||
113 | |||
114 | size = PAGE_ALIGN(size); | ||
115 | |||
116 | #ifdef __alpha__ | ||
117 | offset -= dev->hose->mem_space->start; | ||
118 | #endif | ||
119 | |||
120 | for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) | ||
121 | if (agpmem->bound <= offset | ||
122 | && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >= | ||
123 | (offset + size)) | ||
124 | break; | ||
125 | if (!agpmem) | ||
126 | return NULL; | ||
127 | |||
128 | /* | ||
129 | * OK, we're mapping AGP space on a chipset/platform on which memory accesses by | ||
130 | * the CPU do not get remapped by the GART. We fix this by using the kernel's | ||
131 | * page-table instead (that's probably faster anyhow...). | ||
132 | */ | ||
133 | /* note: use vmalloc() because num_pages could be large... */ | ||
134 | page_map = vmalloc(num_pages * sizeof(struct page *)); | ||
135 | if (!page_map) | ||
136 | return NULL; | ||
137 | |||
138 | phys_addr_map = | ||
139 | agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE; | ||
140 | for (i = 0; i < num_pages; ++i) | ||
141 | page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT); | ||
142 | addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP); | ||
143 | vfree(page_map); | ||
144 | |||
145 | return addr; | ||
146 | } | ||
147 | |||
83 | /** Wrapper around agp_allocate_memory() */ | 148 | /** Wrapper around agp_allocate_memory() */ |
84 | DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type) | 149 | DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type) |
85 | { | 150 | { |
@@ -103,5 +168,74 @@ int drm_unbind_agp(DRM_AGP_MEM * handle) | |||
103 | { | 168 | { |
104 | return drm_agp_unbind_memory(handle); | 169 | return drm_agp_unbind_memory(handle); |
105 | } | 170 | } |
171 | |||
172 | #else /* __OS_HAS_AGP */ | ||
173 | |||
174 | static inline drm_map_t *drm_lookup_map(unsigned long offset, | ||
175 | unsigned long size, drm_device_t * dev) | ||
176 | { | ||
177 | return NULL; | ||
178 | } | ||
179 | |||
180 | static inline void *agp_remap(unsigned long offset, unsigned long size, | ||
181 | drm_device_t * dev) | ||
182 | { | ||
183 | return NULL; | ||
184 | } | ||
185 | |||
106 | #endif /* agp */ | 186 | #endif /* agp */ |
187 | |||
188 | void *drm_ioremap(unsigned long offset, unsigned long size, | ||
189 | drm_device_t * dev) | ||
190 | { | ||
191 | if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) { | ||
192 | drm_map_t *map = drm_lookup_map(offset, size, dev); | ||
193 | |||
194 | if (map && map->type == _DRM_AGP) | ||
195 | return agp_remap(offset, size, dev); | ||
196 | } | ||
197 | return ioremap(offset, size); | ||
198 | } | ||
199 | EXPORT_SYMBOL(drm_ioremap); | ||
200 | |||
201 | #if 0 | ||
202 | void *drm_ioremap_nocache(unsigned long offset, | ||
203 | unsigned long size, drm_device_t * dev) | ||
204 | { | ||
205 | if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) { | ||
206 | drm_map_t *map = drm_lookup_map(offset, size, dev); | ||
207 | |||
208 | if (map && map->type == _DRM_AGP) | ||
209 | return agp_remap(offset, size, dev); | ||
210 | } | ||
211 | return ioremap_nocache(offset, size); | ||
212 | } | ||
213 | #endif /* 0 */ | ||
214 | |||
215 | void drm_ioremapfree(void *pt, unsigned long size, | ||
216 | drm_device_t * dev) | ||
217 | { | ||
218 | /* | ||
219 | * This is a bit ugly. It would be much cleaner if the DRM API would use separate | ||
220 | * routines for handling mappings in the AGP space. Hopefully this can be done in | ||
221 | * a future revision of the interface... | ||
222 | */ | ||
223 | if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture | ||
224 | && ((unsigned long)pt >= VMALLOC_START | ||
225 | && (unsigned long)pt < VMALLOC_END)) { | ||
226 | unsigned long offset; | ||
227 | drm_map_t *map; | ||
228 | |||
229 | offset = drm_follow_page(pt) | ((unsigned long)pt & ~PAGE_MASK); | ||
230 | map = drm_lookup_map(offset, size, dev); | ||
231 | if (map && map->type == _DRM_AGP) { | ||
232 | vunmap(pt); | ||
233 | return; | ||
234 | } | ||
235 | } | ||
236 | |||
237 | iounmap(pt); | ||
238 | } | ||
239 | EXPORT_SYMBOL(drm_ioremapfree); | ||
240 | |||
107 | #endif /* debug_memory */ | 241 | #endif /* debug_memory */ |
diff --git a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h index 3732a61c3762..714d9aedcff5 100644 --- a/drivers/char/drm/drm_memory.h +++ b/drivers/char/drm/drm_memory.h | |||
@@ -57,71 +57,6 @@ | |||
57 | # endif | 57 | # endif |
58 | #endif | 58 | #endif |
59 | 59 | ||
60 | /* | ||
61 | * Find the drm_map that covers the range [offset, offset+size). | ||
62 | */ | ||
63 | static inline drm_map_t *drm_lookup_map(unsigned long offset, | ||
64 | unsigned long size, drm_device_t * dev) | ||
65 | { | ||
66 | struct list_head *list; | ||
67 | drm_map_list_t *r_list; | ||
68 | drm_map_t *map; | ||
69 | |||
70 | list_for_each(list, &dev->maplist->head) { | ||
71 | r_list = (drm_map_list_t *) list; | ||
72 | map = r_list->map; | ||
73 | if (!map) | ||
74 | continue; | ||
75 | if (map->offset <= offset | ||
76 | && (offset + size) <= (map->offset + map->size)) | ||
77 | return map; | ||
78 | } | ||
79 | return NULL; | ||
80 | } | ||
81 | |||
82 | static inline void *agp_remap(unsigned long offset, unsigned long size, | ||
83 | drm_device_t * dev) | ||
84 | { | ||
85 | unsigned long *phys_addr_map, i, num_pages = | ||
86 | PAGE_ALIGN(size) / PAGE_SIZE; | ||
87 | struct drm_agp_mem *agpmem; | ||
88 | struct page **page_map; | ||
89 | void *addr; | ||
90 | |||
91 | size = PAGE_ALIGN(size); | ||
92 | |||
93 | #ifdef __alpha__ | ||
94 | offset -= dev->hose->mem_space->start; | ||
95 | #endif | ||
96 | |||
97 | for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) | ||
98 | if (agpmem->bound <= offset | ||
99 | && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >= | ||
100 | (offset + size)) | ||
101 | break; | ||
102 | if (!agpmem) | ||
103 | return NULL; | ||
104 | |||
105 | /* | ||
106 | * OK, we're mapping AGP space on a chipset/platform on which memory accesses by | ||
107 | * the CPU do not get remapped by the GART. We fix this by using the kernel's | ||
108 | * page-table instead (that's probably faster anyhow...). | ||
109 | */ | ||
110 | /* note: use vmalloc() because num_pages could be large... */ | ||
111 | page_map = vmalloc(num_pages * sizeof(struct page *)); | ||
112 | if (!page_map) | ||
113 | return NULL; | ||
114 | |||
115 | phys_addr_map = | ||
116 | agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE; | ||
117 | for (i = 0; i < num_pages; ++i) | ||
118 | page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT); | ||
119 | addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP); | ||
120 | vfree(page_map); | ||
121 | |||
122 | return addr; | ||
123 | } | ||
124 | |||
125 | static inline unsigned long drm_follow_page(void *vaddr) | 60 | static inline unsigned long drm_follow_page(void *vaddr) |
126 | { | 61 | { |
127 | pgd_t *pgd = pgd_offset_k((unsigned long)vaddr); | 62 | pgd_t *pgd = pgd_offset_k((unsigned long)vaddr); |
@@ -133,18 +68,6 @@ static inline unsigned long drm_follow_page(void *vaddr) | |||
133 | 68 | ||
134 | #else /* __OS_HAS_AGP */ | 69 | #else /* __OS_HAS_AGP */ |
135 | 70 | ||
136 | static inline drm_map_t *drm_lookup_map(unsigned long offset, | ||
137 | unsigned long size, drm_device_t * dev) | ||
138 | { | ||
139 | return NULL; | ||
140 | } | ||
141 | |||
142 | static inline void *agp_remap(unsigned long offset, unsigned long size, | ||
143 | drm_device_t * dev) | ||
144 | { | ||
145 | return NULL; | ||
146 | } | ||
147 | |||
148 | static inline unsigned long drm_follow_page(void *vaddr) | 71 | static inline unsigned long drm_follow_page(void *vaddr) |
149 | { | 72 | { |
150 | return 0; | 73 | return 0; |
@@ -152,51 +75,8 @@ static inline unsigned long drm_follow_page(void *vaddr) | |||
152 | 75 | ||
153 | #endif | 76 | #endif |
154 | 77 | ||
155 | static inline void *drm_ioremap(unsigned long offset, unsigned long size, | 78 | void *drm_ioremap(unsigned long offset, unsigned long size, |
156 | drm_device_t * dev) | 79 | drm_device_t * dev); |
157 | { | ||
158 | if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) { | ||
159 | drm_map_t *map = drm_lookup_map(offset, size, dev); | ||
160 | |||
161 | if (map && map->type == _DRM_AGP) | ||
162 | return agp_remap(offset, size, dev); | ||
163 | } | ||
164 | return ioremap(offset, size); | ||
165 | } | ||
166 | |||
167 | static inline void *drm_ioremap_nocache(unsigned long offset, | ||
168 | unsigned long size, drm_device_t * dev) | ||
169 | { | ||
170 | if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) { | ||
171 | drm_map_t *map = drm_lookup_map(offset, size, dev); | ||
172 | |||
173 | if (map && map->type == _DRM_AGP) | ||
174 | return agp_remap(offset, size, dev); | ||
175 | } | ||
176 | return ioremap_nocache(offset, size); | ||
177 | } | ||
178 | |||
179 | static inline void drm_ioremapfree(void *pt, unsigned long size, | ||
180 | drm_device_t * dev) | ||
181 | { | ||
182 | /* | ||
183 | * This is a bit ugly. It would be much cleaner if the DRM API would use separate | ||
184 | * routines for handling mappings in the AGP space. Hopefully this can be done in | ||
185 | * a future revision of the interface... | ||
186 | */ | ||
187 | if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture | ||
188 | && ((unsigned long)pt >= VMALLOC_START | ||
189 | && (unsigned long)pt < VMALLOC_END)) { | ||
190 | unsigned long offset; | ||
191 | drm_map_t *map; | ||
192 | |||
193 | offset = drm_follow_page(pt) | ((unsigned long)pt & ~PAGE_MASK); | ||
194 | map = drm_lookup_map(offset, size, dev); | ||
195 | if (map && map->type == _DRM_AGP) { | ||
196 | vunmap(pt); | ||
197 | return; | ||
198 | } | ||
199 | } | ||
200 | 80 | ||
201 | iounmap(pt); | 81 | void drm_ioremapfree(void *pt, unsigned long size, |
202 | } | 82 | drm_device_t * dev); |
diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h index 7868341817da..6543b9a14c42 100644 --- a/drivers/char/drm/drm_memory_debug.h +++ b/drivers/char/drm/drm_memory_debug.h | |||
@@ -229,6 +229,7 @@ void *drm_ioremap (unsigned long offset, unsigned long size, | |||
229 | return pt; | 229 | return pt; |
230 | } | 230 | } |
231 | 231 | ||
232 | #if 0 | ||
232 | void *drm_ioremap_nocache (unsigned long offset, unsigned long size, | 233 | void *drm_ioremap_nocache (unsigned long offset, unsigned long size, |
233 | drm_device_t * dev) { | 234 | drm_device_t * dev) { |
234 | void *pt; | 235 | void *pt; |
@@ -251,6 +252,7 @@ void *drm_ioremap_nocache (unsigned long offset, unsigned long size, | |||
251 | spin_unlock(&drm_mem_lock); | 252 | spin_unlock(&drm_mem_lock); |
252 | return pt; | 253 | return pt; |
253 | } | 254 | } |
255 | #endif /* 0 */ | ||
254 | 256 | ||
255 | void drm_ioremapfree (void *pt, unsigned long size, drm_device_t * dev) { | 257 | void drm_ioremapfree (void *pt, unsigned long size, drm_device_t * dev) { |
256 | int alloc_count; | 258 | int alloc_count; |
diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c index b28ca9cea8a2..86a0f1c22091 100644 --- a/drivers/char/drm/drm_pci.c +++ b/drivers/char/drm/drm_pci.c | |||
@@ -37,6 +37,7 @@ | |||
37 | */ | 37 | */ |
38 | 38 | ||
39 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
40 | #include <linux/dma-mapping.h> | ||
40 | #include "drmP.h" | 41 | #include "drmP.h" |
41 | 42 | ||
42 | /**********************************************************************/ | 43 | /**********************************************************************/ |
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c index 68073e14fdec..9a842a36bb27 100644 --- a/drivers/char/drm/drm_stub.c +++ b/drivers/char/drm/drm_stub.c | |||
@@ -229,8 +229,6 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, | |||
229 | return ret; | 229 | return ret; |
230 | } | 230 | } |
231 | 231 | ||
232 | EXPORT_SYMBOL(drm_get_dev); | ||
233 | |||
234 | /** | 232 | /** |
235 | * Put a device minor number. | 233 | * Put a device minor number. |
236 | * | 234 | * |
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c index b108c7f913b2..26bdf2ca59d7 100644 --- a/drivers/char/drm/r300_cmdbuf.c +++ b/drivers/char/drm/r300_cmdbuf.c | |||
@@ -723,7 +723,7 @@ static int r300_scratch(drm_radeon_private_t *dev_priv, | |||
723 | 723 | ||
724 | dev_priv->scratch_ages[header.scratch.reg]++; | 724 | dev_priv->scratch_ages[header.scratch.reg]++; |
725 | 725 | ||
726 | ref_age_base = *(u32 **)cmdbuf->buf; | 726 | ref_age_base = (u32 *)(unsigned long)*((uint64_t *)cmdbuf->buf); |
727 | 727 | ||
728 | cmdbuf->buf += sizeof(u64); | 728 | cmdbuf->buf += sizeof(u64); |
729 | cmdbuf->bufsz -= sizeof(u64); | 729 | cmdbuf->bufsz -= sizeof(u64); |
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c index 6152415644e9..c33d068cde19 100644 --- a/drivers/char/drm/via_irq.c +++ b/drivers/char/drm/via_irq.c | |||
@@ -196,9 +196,9 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence, | |||
196 | { | 196 | { |
197 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; | 197 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; |
198 | unsigned int cur_irq_sequence; | 198 | unsigned int cur_irq_sequence; |
199 | drm_via_irq_t *cur_irq = dev_priv->via_irqs; | 199 | drm_via_irq_t *cur_irq; |
200 | int ret = 0; | 200 | int ret = 0; |
201 | maskarray_t *masks = dev_priv->irq_masks; | 201 | maskarray_t *masks; |
202 | int real_irq; | 202 | int real_irq; |
203 | 203 | ||
204 | DRM_DEBUG("%s\n", __FUNCTION__); | 204 | DRM_DEBUG("%s\n", __FUNCTION__); |
@@ -221,8 +221,9 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence, | |||
221 | __FUNCTION__, irq); | 221 | __FUNCTION__, irq); |
222 | return DRM_ERR(EINVAL); | 222 | return DRM_ERR(EINVAL); |
223 | } | 223 | } |
224 | 224 | ||
225 | cur_irq += real_irq; | 225 | masks = dev_priv->irq_masks; |
226 | cur_irq = dev_priv->via_irqs + real_irq; | ||
226 | 227 | ||
227 | if (masks[real_irq][2] && !force_sequence) { | 228 | if (masks[real_irq][2] && !force_sequence) { |
228 | DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ, | 229 | DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ, |
@@ -247,11 +248,12 @@ void via_driver_irq_preinstall(drm_device_t * dev) | |||
247 | { | 248 | { |
248 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; | 249 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; |
249 | u32 status; | 250 | u32 status; |
250 | drm_via_irq_t *cur_irq = dev_priv->via_irqs; | 251 | drm_via_irq_t *cur_irq; |
251 | int i; | 252 | int i; |
252 | 253 | ||
253 | DRM_DEBUG("driver_irq_preinstall: dev_priv: %p\n", dev_priv); | 254 | DRM_DEBUG("driver_irq_preinstall: dev_priv: %p\n", dev_priv); |
254 | if (dev_priv) { | 255 | if (dev_priv) { |
256 | cur_irq = dev_priv->via_irqs; | ||
255 | 257 | ||
256 | dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE; | 258 | dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE; |
257 | dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING; | 259 | dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING; |
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c index a229915ce1b2..87dcaa237f07 100644 --- a/drivers/char/dtlk.c +++ b/drivers/char/dtlk.c | |||
@@ -490,7 +490,7 @@ for (i = 0; i < 10; i++) \ | |||
490 | release_region(dtlk_portlist[i], DTLK_IO_EXTENT); | 490 | release_region(dtlk_portlist[i], DTLK_IO_EXTENT); |
491 | } | 491 | } |
492 | 492 | ||
493 | printk(KERN_INFO "\nDoubleTalk PC - not found\n"); | 493 | printk(KERN_INFO "DoubleTalk PC - not found\n"); |
494 | return -ENODEV; | 494 | return -ENODEV; |
495 | } | 495 | } |
496 | 496 | ||
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c index d3a2bc36129b..588fca542a98 100644 --- a/drivers/char/genrtc.c +++ b/drivers/char/genrtc.c | |||
@@ -200,13 +200,13 @@ static ssize_t gen_rtc_read(struct file *file, char __user *buf, | |||
200 | /* first test allows optimizer to nuke this case for 32-bit machines */ | 200 | /* first test allows optimizer to nuke this case for 32-bit machines */ |
201 | if (sizeof (int) != sizeof (long) && count == sizeof (unsigned int)) { | 201 | if (sizeof (int) != sizeof (long) && count == sizeof (unsigned int)) { |
202 | unsigned int uidata = data; | 202 | unsigned int uidata = data; |
203 | retval = put_user(uidata, (unsigned long __user *)buf); | 203 | retval = put_user(uidata, (unsigned int __user *)buf) ?: |
204 | sizeof(unsigned int); | ||
204 | } | 205 | } |
205 | else { | 206 | else { |
206 | retval = put_user(data, (unsigned long __user *)buf); | 207 | retval = put_user(data, (unsigned long __user *)buf) ?: |
208 | sizeof(unsigned long); | ||
207 | } | 209 | } |
208 | if (!retval) | ||
209 | retval = sizeof(unsigned long); | ||
210 | out: | 210 | out: |
211 | current->state = TASK_RUNNING; | 211 | current->state = TASK_RUNNING; |
212 | remove_wait_queue(&gen_rtc_wait, &wait); | 212 | remove_wait_queue(&gen_rtc_wait, &wait); |
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 327b00c3c45e..8d97b3911293 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c | |||
@@ -904,7 +904,7 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address, | |||
904 | * It is possible the vty-server was removed after the irq was | 904 | * It is possible the vty-server was removed after the irq was |
905 | * requested but before we have time to enable interrupts. | 905 | * requested but before we have time to enable interrupts. |
906 | */ | 906 | */ |
907 | if (vio_enable_interrupts(vdev) == H_Success) | 907 | if (vio_enable_interrupts(vdev) == H_SUCCESS) |
908 | return 0; | 908 | return 0; |
909 | else { | 909 | else { |
910 | printk(KERN_ERR "HVCS: int enable failed for" | 910 | printk(KERN_ERR "HVCS: int enable failed for" |
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c index 58dcdee1cd71..0030cd8e2e95 100644 --- a/drivers/char/ipmi/ipmi_bt_sm.c +++ b/drivers/char/ipmi/ipmi_bt_sm.c | |||
@@ -165,7 +165,7 @@ static int bt_start_transaction(struct si_sm_data *bt, | |||
165 | { | 165 | { |
166 | unsigned int i; | 166 | unsigned int i; |
167 | 167 | ||
168 | if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH)) | 168 | if ((size < 2) || (size > (IPMI_MAX_MSG_LENGTH - 2))) |
169 | return -1; | 169 | return -1; |
170 | 170 | ||
171 | if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED)) | 171 | if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED)) |
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index 932feedda262..e1c95374984c 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c | |||
@@ -42,7 +42,7 @@ | |||
42 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
43 | #include <linux/devfs_fs_kernel.h> | 43 | #include <linux/devfs_fs_kernel.h> |
44 | #include <linux/ipmi.h> | 44 | #include <linux/ipmi.h> |
45 | #include <asm/semaphore.h> | 45 | #include <linux/mutex.h> |
46 | #include <linux/init.h> | 46 | #include <linux/init.h> |
47 | #include <linux/device.h> | 47 | #include <linux/device.h> |
48 | #include <linux/compat.h> | 48 | #include <linux/compat.h> |
@@ -55,7 +55,7 @@ struct ipmi_file_private | |||
55 | struct file *file; | 55 | struct file *file; |
56 | struct fasync_struct *fasync_queue; | 56 | struct fasync_struct *fasync_queue; |
57 | wait_queue_head_t wait; | 57 | wait_queue_head_t wait; |
58 | struct semaphore recv_sem; | 58 | struct mutex recv_mutex; |
59 | int default_retries; | 59 | int default_retries; |
60 | unsigned int default_retry_time_ms; | 60 | unsigned int default_retry_time_ms; |
61 | }; | 61 | }; |
@@ -141,7 +141,7 @@ static int ipmi_open(struct inode *inode, struct file *file) | |||
141 | INIT_LIST_HEAD(&(priv->recv_msgs)); | 141 | INIT_LIST_HEAD(&(priv->recv_msgs)); |
142 | init_waitqueue_head(&priv->wait); | 142 | init_waitqueue_head(&priv->wait); |
143 | priv->fasync_queue = NULL; | 143 | priv->fasync_queue = NULL; |
144 | sema_init(&(priv->recv_sem), 1); | 144 | mutex_init(&priv->recv_mutex); |
145 | 145 | ||
146 | /* Use the low-level defaults. */ | 146 | /* Use the low-level defaults. */ |
147 | priv->default_retries = -1; | 147 | priv->default_retries = -1; |
@@ -285,15 +285,15 @@ static int ipmi_ioctl(struct inode *inode, | |||
285 | break; | 285 | break; |
286 | } | 286 | } |
287 | 287 | ||
288 | /* We claim a semaphore because we don't want two | 288 | /* We claim a mutex because we don't want two |
289 | users getting something from the queue at a time. | 289 | users getting something from the queue at a time. |
290 | Since we have to release the spinlock before we can | 290 | Since we have to release the spinlock before we can |
291 | copy the data to the user, it's possible another | 291 | copy the data to the user, it's possible another |
292 | user will grab something from the queue, too. Then | 292 | user will grab something from the queue, too. Then |
293 | the messages might get out of order if something | 293 | the messages might get out of order if something |
294 | fails and the message gets put back onto the | 294 | fails and the message gets put back onto the |
295 | queue. This semaphore prevents that problem. */ | 295 | queue. This mutex prevents that problem. */ |
296 | down(&(priv->recv_sem)); | 296 | mutex_lock(&priv->recv_mutex); |
297 | 297 | ||
298 | /* Grab the message off the list. */ | 298 | /* Grab the message off the list. */ |
299 | spin_lock_irqsave(&(priv->recv_msg_lock), flags); | 299 | spin_lock_irqsave(&(priv->recv_msg_lock), flags); |
@@ -352,7 +352,7 @@ static int ipmi_ioctl(struct inode *inode, | |||
352 | goto recv_putback_on_err; | 352 | goto recv_putback_on_err; |
353 | } | 353 | } |
354 | 354 | ||
355 | up(&(priv->recv_sem)); | 355 | mutex_unlock(&priv->recv_mutex); |
356 | ipmi_free_recv_msg(msg); | 356 | ipmi_free_recv_msg(msg); |
357 | break; | 357 | break; |
358 | 358 | ||
@@ -362,11 +362,11 @@ static int ipmi_ioctl(struct inode *inode, | |||
362 | spin_lock_irqsave(&(priv->recv_msg_lock), flags); | 362 | spin_lock_irqsave(&(priv->recv_msg_lock), flags); |
363 | list_add(entry, &(priv->recv_msgs)); | 363 | list_add(entry, &(priv->recv_msgs)); |
364 | spin_unlock_irqrestore(&(priv->recv_msg_lock), flags); | 364 | spin_unlock_irqrestore(&(priv->recv_msg_lock), flags); |
365 | up(&(priv->recv_sem)); | 365 | mutex_unlock(&priv->recv_mutex); |
366 | break; | 366 | break; |
367 | 367 | ||
368 | recv_err: | 368 | recv_err: |
369 | up(&(priv->recv_sem)); | 369 | mutex_unlock(&priv->recv_mutex); |
370 | break; | 370 | break; |
371 | } | 371 | } |
372 | 372 | ||
diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c index da1554194d3d..2062675f9e99 100644 --- a/drivers/char/ipmi/ipmi_kcs_sm.c +++ b/drivers/char/ipmi/ipmi_kcs_sm.c | |||
@@ -227,7 +227,7 @@ static inline int check_ibf(struct si_sm_data *kcs, unsigned char status, | |||
227 | static inline int check_obf(struct si_sm_data *kcs, unsigned char status, | 227 | static inline int check_obf(struct si_sm_data *kcs, unsigned char status, |
228 | long time) | 228 | long time) |
229 | { | 229 | { |
230 | if (! GET_STATUS_OBF(status)) { | 230 | if (!GET_STATUS_OBF(status)) { |
231 | kcs->obf_timeout -= time; | 231 | kcs->obf_timeout -= time; |
232 | if (kcs->obf_timeout < 0) { | 232 | if (kcs->obf_timeout < 0) { |
233 | start_error_recovery(kcs, "OBF not ready in time"); | 233 | start_error_recovery(kcs, "OBF not ready in time"); |
@@ -407,7 +407,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time) | |||
407 | } | 407 | } |
408 | 408 | ||
409 | if (state == KCS_READ_STATE) { | 409 | if (state == KCS_READ_STATE) { |
410 | if (! check_obf(kcs, status, time)) | 410 | if (!check_obf(kcs, status, time)) |
411 | return SI_SM_CALL_WITH_DELAY; | 411 | return SI_SM_CALL_WITH_DELAY; |
412 | read_next_byte(kcs); | 412 | read_next_byte(kcs); |
413 | } else { | 413 | } else { |
@@ -447,7 +447,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time) | |||
447 | "Not in read state for error2"); | 447 | "Not in read state for error2"); |
448 | break; | 448 | break; |
449 | } | 449 | } |
450 | if (! check_obf(kcs, status, time)) | 450 | if (!check_obf(kcs, status, time)) |
451 | return SI_SM_CALL_WITH_DELAY; | 451 | return SI_SM_CALL_WITH_DELAY; |
452 | 452 | ||
453 | clear_obf(kcs, status); | 453 | clear_obf(kcs, status); |
@@ -462,7 +462,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time) | |||
462 | break; | 462 | break; |
463 | } | 463 | } |
464 | 464 | ||
465 | if (! check_obf(kcs, status, time)) | 465 | if (!check_obf(kcs, status, time)) |
466 | return SI_SM_CALL_WITH_DELAY; | 466 | return SI_SM_CALL_WITH_DELAY; |
467 | 467 | ||
468 | clear_obf(kcs, status); | 468 | clear_obf(kcs, status); |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 40eb005b9d77..9f2f8fdec69a 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/sched.h> | 38 | #include <linux/sched.h> |
39 | #include <linux/poll.h> | 39 | #include <linux/poll.h> |
40 | #include <linux/spinlock.h> | 40 | #include <linux/spinlock.h> |
41 | #include <linux/mutex.h> | ||
41 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
42 | #include <linux/ipmi.h> | 43 | #include <linux/ipmi.h> |
43 | #include <linux/ipmi_smi.h> | 44 | #include <linux/ipmi_smi.h> |
@@ -234,7 +235,7 @@ struct ipmi_smi | |||
234 | 235 | ||
235 | /* The list of command receivers that are registered for commands | 236 | /* The list of command receivers that are registered for commands |
236 | on this interface. */ | 237 | on this interface. */ |
237 | struct semaphore cmd_rcvrs_lock; | 238 | struct mutex cmd_rcvrs_mutex; |
238 | struct list_head cmd_rcvrs; | 239 | struct list_head cmd_rcvrs; |
239 | 240 | ||
240 | /* Events that were queues because no one was there to receive | 241 | /* Events that were queues because no one was there to receive |
@@ -387,10 +388,10 @@ static void clean_up_interface_data(ipmi_smi_t intf) | |||
387 | 388 | ||
388 | /* Wholesale remove all the entries from the list in the | 389 | /* Wholesale remove all the entries from the list in the |
389 | * interface and wait for RCU to know that none are in use. */ | 390 | * interface and wait for RCU to know that none are in use. */ |
390 | down(&intf->cmd_rcvrs_lock); | 391 | mutex_lock(&intf->cmd_rcvrs_mutex); |
391 | list_add_rcu(&list, &intf->cmd_rcvrs); | 392 | list_add_rcu(&list, &intf->cmd_rcvrs); |
392 | list_del_rcu(&intf->cmd_rcvrs); | 393 | list_del_rcu(&intf->cmd_rcvrs); |
393 | up(&intf->cmd_rcvrs_lock); | 394 | mutex_unlock(&intf->cmd_rcvrs_mutex); |
394 | synchronize_rcu(); | 395 | synchronize_rcu(); |
395 | 396 | ||
396 | list_for_each_entry_safe(rcvr, rcvr2, &list, link) | 397 | list_for_each_entry_safe(rcvr, rcvr2, &list, link) |
@@ -557,7 +558,7 @@ unsigned int ipmi_addr_length(int addr_type) | |||
557 | 558 | ||
558 | static void deliver_response(struct ipmi_recv_msg *msg) | 559 | static void deliver_response(struct ipmi_recv_msg *msg) |
559 | { | 560 | { |
560 | if (! msg->user) { | 561 | if (!msg->user) { |
561 | ipmi_smi_t intf = msg->user_msg_data; | 562 | ipmi_smi_t intf = msg->user_msg_data; |
562 | unsigned long flags; | 563 | unsigned long flags; |
563 | 564 | ||
@@ -598,11 +599,11 @@ static int intf_next_seq(ipmi_smi_t intf, | |||
598 | (i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq; | 599 | (i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq; |
599 | i = (i+1)%IPMI_IPMB_NUM_SEQ) | 600 | i = (i+1)%IPMI_IPMB_NUM_SEQ) |
600 | { | 601 | { |
601 | if (! intf->seq_table[i].inuse) | 602 | if (!intf->seq_table[i].inuse) |
602 | break; | 603 | break; |
603 | } | 604 | } |
604 | 605 | ||
605 | if (! intf->seq_table[i].inuse) { | 606 | if (!intf->seq_table[i].inuse) { |
606 | intf->seq_table[i].recv_msg = recv_msg; | 607 | intf->seq_table[i].recv_msg = recv_msg; |
607 | 608 | ||
608 | /* Start with the maximum timeout, when the send response | 609 | /* Start with the maximum timeout, when the send response |
@@ -763,7 +764,7 @@ int ipmi_create_user(unsigned int if_num, | |||
763 | } | 764 | } |
764 | 765 | ||
765 | new_user = kmalloc(sizeof(*new_user), GFP_KERNEL); | 766 | new_user = kmalloc(sizeof(*new_user), GFP_KERNEL); |
766 | if (! new_user) | 767 | if (!new_user) |
767 | return -ENOMEM; | 768 | return -ENOMEM; |
768 | 769 | ||
769 | spin_lock_irqsave(&interfaces_lock, flags); | 770 | spin_lock_irqsave(&interfaces_lock, flags); |
@@ -819,14 +820,13 @@ static void free_user(struct kref *ref) | |||
819 | 820 | ||
820 | int ipmi_destroy_user(ipmi_user_t user) | 821 | int ipmi_destroy_user(ipmi_user_t user) |
821 | { | 822 | { |
822 | int rv = -ENODEV; | ||
823 | ipmi_smi_t intf = user->intf; | 823 | ipmi_smi_t intf = user->intf; |
824 | int i; | 824 | int i; |
825 | unsigned long flags; | 825 | unsigned long flags; |
826 | struct cmd_rcvr *rcvr; | 826 | struct cmd_rcvr *rcvr; |
827 | struct cmd_rcvr *rcvrs = NULL; | 827 | struct cmd_rcvr *rcvrs = NULL; |
828 | 828 | ||
829 | user->valid = 1; | 829 | user->valid = 0; |
830 | 830 | ||
831 | /* Remove the user from the interface's sequence table. */ | 831 | /* Remove the user from the interface's sequence table. */ |
832 | spin_lock_irqsave(&intf->seq_lock, flags); | 832 | spin_lock_irqsave(&intf->seq_lock, flags); |
@@ -847,7 +847,7 @@ int ipmi_destroy_user(ipmi_user_t user) | |||
847 | * since other things may be using it till we do | 847 | * since other things may be using it till we do |
848 | * synchronize_rcu()) then free everything in that list. | 848 | * synchronize_rcu()) then free everything in that list. |
849 | */ | 849 | */ |
850 | down(&intf->cmd_rcvrs_lock); | 850 | mutex_lock(&intf->cmd_rcvrs_mutex); |
851 | list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) { | 851 | list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) { |
852 | if (rcvr->user == user) { | 852 | if (rcvr->user == user) { |
853 | list_del_rcu(&rcvr->link); | 853 | list_del_rcu(&rcvr->link); |
@@ -855,7 +855,7 @@ int ipmi_destroy_user(ipmi_user_t user) | |||
855 | rcvrs = rcvr; | 855 | rcvrs = rcvr; |
856 | } | 856 | } |
857 | } | 857 | } |
858 | up(&intf->cmd_rcvrs_lock); | 858 | mutex_unlock(&intf->cmd_rcvrs_mutex); |
859 | synchronize_rcu(); | 859 | synchronize_rcu(); |
860 | while (rcvrs) { | 860 | while (rcvrs) { |
861 | rcvr = rcvrs; | 861 | rcvr = rcvrs; |
@@ -871,7 +871,7 @@ int ipmi_destroy_user(ipmi_user_t user) | |||
871 | 871 | ||
872 | kref_put(&user->refcount, free_user); | 872 | kref_put(&user->refcount, free_user); |
873 | 873 | ||
874 | return rv; | 874 | return 0; |
875 | } | 875 | } |
876 | 876 | ||
877 | void ipmi_get_version(ipmi_user_t user, | 877 | void ipmi_get_version(ipmi_user_t user, |
@@ -936,10 +936,12 @@ int ipmi_set_gets_events(ipmi_user_t user, int val) | |||
936 | 936 | ||
937 | if (val) { | 937 | if (val) { |
938 | /* Deliver any queued events. */ | 938 | /* Deliver any queued events. */ |
939 | list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link) { | 939 | list_for_each_entry_safe(msg, msg2, &intf->waiting_events, |
940 | link) { | ||
940 | list_del(&msg->link); | 941 | list_del(&msg->link); |
941 | list_add_tail(&msg->link, &msgs); | 942 | list_add_tail(&msg->link, &msgs); |
942 | } | 943 | } |
944 | intf->waiting_events_count = 0; | ||
943 | } | 945 | } |
944 | 946 | ||
945 | /* Hold the events lock while doing this to preserve order. */ | 947 | /* Hold the events lock while doing this to preserve order. */ |
@@ -978,13 +980,13 @@ int ipmi_register_for_cmd(ipmi_user_t user, | |||
978 | 980 | ||
979 | 981 | ||
980 | rcvr = kmalloc(sizeof(*rcvr), GFP_KERNEL); | 982 | rcvr = kmalloc(sizeof(*rcvr), GFP_KERNEL); |
981 | if (! rcvr) | 983 | if (!rcvr) |
982 | return -ENOMEM; | 984 | return -ENOMEM; |
983 | rcvr->cmd = cmd; | 985 | rcvr->cmd = cmd; |
984 | rcvr->netfn = netfn; | 986 | rcvr->netfn = netfn; |
985 | rcvr->user = user; | 987 | rcvr->user = user; |
986 | 988 | ||
987 | down(&intf->cmd_rcvrs_lock); | 989 | mutex_lock(&intf->cmd_rcvrs_mutex); |
988 | /* Make sure the command/netfn is not already registered. */ | 990 | /* Make sure the command/netfn is not already registered. */ |
989 | entry = find_cmd_rcvr(intf, netfn, cmd); | 991 | entry = find_cmd_rcvr(intf, netfn, cmd); |
990 | if (entry) { | 992 | if (entry) { |
@@ -995,7 +997,7 @@ int ipmi_register_for_cmd(ipmi_user_t user, | |||
995 | list_add_rcu(&rcvr->link, &intf->cmd_rcvrs); | 997 | list_add_rcu(&rcvr->link, &intf->cmd_rcvrs); |
996 | 998 | ||
997 | out_unlock: | 999 | out_unlock: |
998 | up(&intf->cmd_rcvrs_lock); | 1000 | mutex_unlock(&intf->cmd_rcvrs_mutex); |
999 | if (rv) | 1001 | if (rv) |
1000 | kfree(rcvr); | 1002 | kfree(rcvr); |
1001 | 1003 | ||
@@ -1009,17 +1011,17 @@ int ipmi_unregister_for_cmd(ipmi_user_t user, | |||
1009 | ipmi_smi_t intf = user->intf; | 1011 | ipmi_smi_t intf = user->intf; |
1010 | struct cmd_rcvr *rcvr; | 1012 | struct cmd_rcvr *rcvr; |
1011 | 1013 | ||
1012 | down(&intf->cmd_rcvrs_lock); | 1014 | mutex_lock(&intf->cmd_rcvrs_mutex); |
1013 | /* Make sure the command/netfn is not already registered. */ | 1015 | /* Make sure the command/netfn is not already registered. */ |
1014 | rcvr = find_cmd_rcvr(intf, netfn, cmd); | 1016 | rcvr = find_cmd_rcvr(intf, netfn, cmd); |
1015 | if ((rcvr) && (rcvr->user == user)) { | 1017 | if ((rcvr) && (rcvr->user == user)) { |
1016 | list_del_rcu(&rcvr->link); | 1018 | list_del_rcu(&rcvr->link); |
1017 | up(&intf->cmd_rcvrs_lock); | 1019 | mutex_unlock(&intf->cmd_rcvrs_mutex); |
1018 | synchronize_rcu(); | 1020 | synchronize_rcu(); |
1019 | kfree(rcvr); | 1021 | kfree(rcvr); |
1020 | return 0; | 1022 | return 0; |
1021 | } else { | 1023 | } else { |
1022 | up(&intf->cmd_rcvrs_lock); | 1024 | mutex_unlock(&intf->cmd_rcvrs_mutex); |
1023 | return -ENOENT; | 1025 | return -ENOENT; |
1024 | } | 1026 | } |
1025 | } | 1027 | } |
@@ -1514,7 +1516,7 @@ int ipmi_request_settime(ipmi_user_t user, | |||
1514 | unsigned char saddr, lun; | 1516 | unsigned char saddr, lun; |
1515 | int rv; | 1517 | int rv; |
1516 | 1518 | ||
1517 | if (! user) | 1519 | if (!user) |
1518 | return -EINVAL; | 1520 | return -EINVAL; |
1519 | rv = check_addr(user->intf, addr, &saddr, &lun); | 1521 | rv = check_addr(user->intf, addr, &saddr, &lun); |
1520 | if (rv) | 1522 | if (rv) |
@@ -1545,7 +1547,7 @@ int ipmi_request_supply_msgs(ipmi_user_t user, | |||
1545 | unsigned char saddr, lun; | 1547 | unsigned char saddr, lun; |
1546 | int rv; | 1548 | int rv; |
1547 | 1549 | ||
1548 | if (! user) | 1550 | if (!user) |
1549 | return -EINVAL; | 1551 | return -EINVAL; |
1550 | rv = check_addr(user->intf, addr, &saddr, &lun); | 1552 | rv = check_addr(user->intf, addr, &saddr, &lun); |
1551 | if (rv) | 1553 | if (rv) |
@@ -1570,7 +1572,7 @@ static int ipmb_file_read_proc(char *page, char **start, off_t off, | |||
1570 | char *out = (char *) page; | 1572 | char *out = (char *) page; |
1571 | ipmi_smi_t intf = data; | 1573 | ipmi_smi_t intf = data; |
1572 | int i; | 1574 | int i; |
1573 | int rv= 0; | 1575 | int rv = 0; |
1574 | 1576 | ||
1575 | for (i = 0; i < IPMI_MAX_CHANNELS; i++) | 1577 | for (i = 0; i < IPMI_MAX_CHANNELS; i++) |
1576 | rv += sprintf(out+rv, "%x ", intf->channels[i].address); | 1578 | rv += sprintf(out+rv, "%x ", intf->channels[i].address); |
@@ -1989,7 +1991,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf) | |||
1989 | } else { | 1991 | } else { |
1990 | bmc->dev = platform_device_alloc("ipmi_bmc", | 1992 | bmc->dev = platform_device_alloc("ipmi_bmc", |
1991 | bmc->id.device_id); | 1993 | bmc->id.device_id); |
1992 | if (! bmc->dev) { | 1994 | if (!bmc->dev) { |
1993 | printk(KERN_ERR | 1995 | printk(KERN_ERR |
1994 | "ipmi_msghandler:" | 1996 | "ipmi_msghandler:" |
1995 | " Unable to allocate platform device\n"); | 1997 | " Unable to allocate platform device\n"); |
@@ -2305,8 +2307,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
2305 | void *send_info, | 2307 | void *send_info, |
2306 | struct ipmi_device_id *device_id, | 2308 | struct ipmi_device_id *device_id, |
2307 | struct device *si_dev, | 2309 | struct device *si_dev, |
2308 | unsigned char slave_addr, | 2310 | unsigned char slave_addr) |
2309 | ipmi_smi_t *new_intf) | ||
2310 | { | 2311 | { |
2311 | int i, j; | 2312 | int i, j; |
2312 | int rv; | 2313 | int rv; |
@@ -2366,7 +2367,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
2366 | spin_lock_init(&intf->events_lock); | 2367 | spin_lock_init(&intf->events_lock); |
2367 | INIT_LIST_HEAD(&intf->waiting_events); | 2368 | INIT_LIST_HEAD(&intf->waiting_events); |
2368 | intf->waiting_events_count = 0; | 2369 | intf->waiting_events_count = 0; |
2369 | init_MUTEX(&intf->cmd_rcvrs_lock); | 2370 | mutex_init(&intf->cmd_rcvrs_mutex); |
2370 | INIT_LIST_HEAD(&intf->cmd_rcvrs); | 2371 | INIT_LIST_HEAD(&intf->cmd_rcvrs); |
2371 | init_waitqueue_head(&intf->waitq); | 2372 | init_waitqueue_head(&intf->waitq); |
2372 | 2373 | ||
@@ -2388,9 +2389,9 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
2388 | if (rv) | 2389 | if (rv) |
2389 | goto out; | 2390 | goto out; |
2390 | 2391 | ||
2391 | /* FIXME - this is an ugly kludge, this sets the intf for the | 2392 | rv = handlers->start_processing(send_info, intf); |
2392 | caller before sending any messages with it. */ | 2393 | if (rv) |
2393 | *new_intf = intf; | 2394 | goto out; |
2394 | 2395 | ||
2395 | get_guid(intf); | 2396 | get_guid(intf); |
2396 | 2397 | ||
@@ -2622,7 +2623,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, | |||
2622 | spin_unlock_irqrestore(&intf->counter_lock, flags); | 2623 | spin_unlock_irqrestore(&intf->counter_lock, flags); |
2623 | 2624 | ||
2624 | recv_msg = ipmi_alloc_recv_msg(); | 2625 | recv_msg = ipmi_alloc_recv_msg(); |
2625 | if (! recv_msg) { | 2626 | if (!recv_msg) { |
2626 | /* We couldn't allocate memory for the | 2627 | /* We couldn't allocate memory for the |
2627 | message, so requeue it for handling | 2628 | message, so requeue it for handling |
2628 | later. */ | 2629 | later. */ |
@@ -2777,7 +2778,7 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf, | |||
2777 | spin_unlock_irqrestore(&intf->counter_lock, flags); | 2778 | spin_unlock_irqrestore(&intf->counter_lock, flags); |
2778 | 2779 | ||
2779 | recv_msg = ipmi_alloc_recv_msg(); | 2780 | recv_msg = ipmi_alloc_recv_msg(); |
2780 | if (! recv_msg) { | 2781 | if (!recv_msg) { |
2781 | /* We couldn't allocate memory for the | 2782 | /* We couldn't allocate memory for the |
2782 | message, so requeue it for handling | 2783 | message, so requeue it for handling |
2783 | later. */ | 2784 | later. */ |
@@ -2869,13 +2870,14 @@ static int handle_read_event_rsp(ipmi_smi_t intf, | |||
2869 | events. */ | 2870 | events. */ |
2870 | rcu_read_lock(); | 2871 | rcu_read_lock(); |
2871 | list_for_each_entry_rcu(user, &intf->users, link) { | 2872 | list_for_each_entry_rcu(user, &intf->users, link) { |
2872 | if (! user->gets_events) | 2873 | if (!user->gets_events) |
2873 | continue; | 2874 | continue; |
2874 | 2875 | ||
2875 | recv_msg = ipmi_alloc_recv_msg(); | 2876 | recv_msg = ipmi_alloc_recv_msg(); |
2876 | if (! recv_msg) { | 2877 | if (!recv_msg) { |
2877 | rcu_read_unlock(); | 2878 | rcu_read_unlock(); |
2878 | list_for_each_entry_safe(recv_msg, recv_msg2, &msgs, link) { | 2879 | list_for_each_entry_safe(recv_msg, recv_msg2, &msgs, |
2880 | link) { | ||
2879 | list_del(&recv_msg->link); | 2881 | list_del(&recv_msg->link); |
2880 | ipmi_free_recv_msg(recv_msg); | 2882 | ipmi_free_recv_msg(recv_msg); |
2881 | } | 2883 | } |
@@ -2905,7 +2907,7 @@ static int handle_read_event_rsp(ipmi_smi_t intf, | |||
2905 | /* No one to receive the message, put it in queue if there's | 2907 | /* No one to receive the message, put it in queue if there's |
2906 | not already too many things in the queue. */ | 2908 | not already too many things in the queue. */ |
2907 | recv_msg = ipmi_alloc_recv_msg(); | 2909 | recv_msg = ipmi_alloc_recv_msg(); |
2908 | if (! recv_msg) { | 2910 | if (!recv_msg) { |
2909 | /* We couldn't allocate memory for the | 2911 | /* We couldn't allocate memory for the |
2910 | message, so requeue it for handling | 2912 | message, so requeue it for handling |
2911 | later. */ | 2913 | later. */ |
@@ -2915,6 +2917,7 @@ static int handle_read_event_rsp(ipmi_smi_t intf, | |||
2915 | 2917 | ||
2916 | copy_event_into_recv_msg(recv_msg, msg); | 2918 | copy_event_into_recv_msg(recv_msg, msg); |
2917 | list_add_tail(&(recv_msg->link), &(intf->waiting_events)); | 2919 | list_add_tail(&(recv_msg->link), &(intf->waiting_events)); |
2920 | intf->waiting_events_count++; | ||
2918 | } else { | 2921 | } else { |
2919 | /* There's too many things in the queue, discard this | 2922 | /* There's too many things in the queue, discard this |
2920 | message. */ | 2923 | message. */ |
@@ -3190,7 +3193,7 @@ void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf) | |||
3190 | 3193 | ||
3191 | rcu_read_lock(); | 3194 | rcu_read_lock(); |
3192 | list_for_each_entry_rcu(user, &intf->users, link) { | 3195 | list_for_each_entry_rcu(user, &intf->users, link) { |
3193 | if (! user->handler->ipmi_watchdog_pretimeout) | 3196 | if (!user->handler->ipmi_watchdog_pretimeout) |
3194 | continue; | 3197 | continue; |
3195 | 3198 | ||
3196 | user->handler->ipmi_watchdog_pretimeout(user->handler_data); | 3199 | user->handler->ipmi_watchdog_pretimeout(user->handler_data); |
@@ -3278,7 +3281,7 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, | |||
3278 | 3281 | ||
3279 | smi_msg = smi_from_recv_msg(intf, ent->recv_msg, slot, | 3282 | smi_msg = smi_from_recv_msg(intf, ent->recv_msg, slot, |
3280 | ent->seqid); | 3283 | ent->seqid); |
3281 | if (! smi_msg) | 3284 | if (!smi_msg) |
3282 | return; | 3285 | return; |
3283 | 3286 | ||
3284 | spin_unlock_irqrestore(&intf->seq_lock, *flags); | 3287 | spin_unlock_irqrestore(&intf->seq_lock, *flags); |
@@ -3314,8 +3317,9 @@ static void ipmi_timeout_handler(long timeout_period) | |||
3314 | 3317 | ||
3315 | /* See if any waiting messages need to be processed. */ | 3318 | /* See if any waiting messages need to be processed. */ |
3316 | spin_lock_irqsave(&intf->waiting_msgs_lock, flags); | 3319 | spin_lock_irqsave(&intf->waiting_msgs_lock, flags); |
3317 | list_for_each_entry_safe(smi_msg, smi_msg2, &intf->waiting_msgs, link) { | 3320 | list_for_each_entry_safe(smi_msg, smi_msg2, |
3318 | if (! handle_new_recv_msg(intf, smi_msg)) { | 3321 | &intf->waiting_msgs, link) { |
3322 | if (!handle_new_recv_msg(intf, smi_msg)) { | ||
3319 | list_del(&smi_msg->link); | 3323 | list_del(&smi_msg->link); |
3320 | ipmi_free_smi_msg(smi_msg); | 3324 | ipmi_free_smi_msg(smi_msg); |
3321 | } else { | 3325 | } else { |
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index 786a2802ca34..d0b5c08e7b4e 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c | |||
@@ -346,7 +346,7 @@ static int ipmi_dell_chassis_detect (ipmi_user_t user) | |||
346 | { | 346 | { |
347 | const char ipmi_version_major = ipmi_version & 0xF; | 347 | const char ipmi_version_major = ipmi_version & 0xF; |
348 | const char ipmi_version_minor = (ipmi_version >> 4) & 0xF; | 348 | const char ipmi_version_minor = (ipmi_version >> 4) & 0xF; |
349 | const char mfr[3]=DELL_IANA_MFR_ID; | 349 | const char mfr[3] = DELL_IANA_MFR_ID; |
350 | if (!memcmp(mfr, &mfg_id, sizeof(mfr)) && | 350 | if (!memcmp(mfr, &mfg_id, sizeof(mfr)) && |
351 | ipmi_version_major <= 1 && | 351 | ipmi_version_major <= 1 && |
352 | ipmi_version_minor < 5) | 352 | ipmi_version_minor < 5) |
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 35fbd4d8ed4b..02a7dd7a8a55 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -803,7 +803,7 @@ static int ipmi_thread(void *data) | |||
803 | set_user_nice(current, 19); | 803 | set_user_nice(current, 19); |
804 | while (!kthread_should_stop()) { | 804 | while (!kthread_should_stop()) { |
805 | spin_lock_irqsave(&(smi_info->si_lock), flags); | 805 | spin_lock_irqsave(&(smi_info->si_lock), flags); |
806 | smi_result=smi_event_handler(smi_info, 0); | 806 | smi_result = smi_event_handler(smi_info, 0); |
807 | spin_unlock_irqrestore(&(smi_info->si_lock), flags); | 807 | spin_unlock_irqrestore(&(smi_info->si_lock), flags); |
808 | if (smi_result == SI_SM_CALL_WITHOUT_DELAY) { | 808 | if (smi_result == SI_SM_CALL_WITHOUT_DELAY) { |
809 | /* do nothing */ | 809 | /* do nothing */ |
@@ -972,10 +972,37 @@ static irqreturn_t si_bt_irq_handler(int irq, void *data, struct pt_regs *regs) | |||
972 | return si_irq_handler(irq, data, regs); | 972 | return si_irq_handler(irq, data, regs); |
973 | } | 973 | } |
974 | 974 | ||
975 | static int smi_start_processing(void *send_info, | ||
976 | ipmi_smi_t intf) | ||
977 | { | ||
978 | struct smi_info *new_smi = send_info; | ||
979 | |||
980 | new_smi->intf = intf; | ||
981 | |||
982 | /* Set up the timer that drives the interface. */ | ||
983 | setup_timer(&new_smi->si_timer, smi_timeout, (long)new_smi); | ||
984 | new_smi->last_timeout_jiffies = jiffies; | ||
985 | mod_timer(&new_smi->si_timer, jiffies + SI_TIMEOUT_JIFFIES); | ||
986 | |||
987 | if (new_smi->si_type != SI_BT) { | ||
988 | new_smi->thread = kthread_run(ipmi_thread, new_smi, | ||
989 | "kipmi%d", new_smi->intf_num); | ||
990 | if (IS_ERR(new_smi->thread)) { | ||
991 | printk(KERN_NOTICE "ipmi_si_intf: Could not start" | ||
992 | " kernel thread due to error %ld, only using" | ||
993 | " timers to drive the interface\n", | ||
994 | PTR_ERR(new_smi->thread)); | ||
995 | new_smi->thread = NULL; | ||
996 | } | ||
997 | } | ||
998 | |||
999 | return 0; | ||
1000 | } | ||
975 | 1001 | ||
976 | static struct ipmi_smi_handlers handlers = | 1002 | static struct ipmi_smi_handlers handlers = |
977 | { | 1003 | { |
978 | .owner = THIS_MODULE, | 1004 | .owner = THIS_MODULE, |
1005 | .start_processing = smi_start_processing, | ||
979 | .sender = sender, | 1006 | .sender = sender, |
980 | .request_events = request_events, | 1007 | .request_events = request_events, |
981 | .set_run_to_completion = set_run_to_completion, | 1008 | .set_run_to_completion = set_run_to_completion, |
@@ -987,7 +1014,7 @@ static struct ipmi_smi_handlers handlers = | |||
987 | 1014 | ||
988 | #define SI_MAX_PARMS 4 | 1015 | #define SI_MAX_PARMS 4 |
989 | static LIST_HEAD(smi_infos); | 1016 | static LIST_HEAD(smi_infos); |
990 | static DECLARE_MUTEX(smi_infos_lock); | 1017 | static DEFINE_MUTEX(smi_infos_lock); |
991 | static int smi_num; /* Used to sequence the SMIs */ | 1018 | static int smi_num; /* Used to sequence the SMIs */ |
992 | 1019 | ||
993 | #define DEFAULT_REGSPACING 1 | 1020 | #define DEFAULT_REGSPACING 1 |
@@ -1157,20 +1184,20 @@ static void port_outl(struct si_sm_io *io, unsigned int offset, | |||
1157 | static void port_cleanup(struct smi_info *info) | 1184 | static void port_cleanup(struct smi_info *info) |
1158 | { | 1185 | { |
1159 | unsigned int addr = info->io.addr_data; | 1186 | unsigned int addr = info->io.addr_data; |
1160 | int mapsize; | 1187 | int idx; |
1161 | 1188 | ||
1162 | if (addr) { | 1189 | if (addr) { |
1163 | mapsize = ((info->io_size * info->io.regspacing) | 1190 | for (idx = 0; idx < info->io_size; idx++) { |
1164 | - (info->io.regspacing - info->io.regsize)); | 1191 | release_region(addr + idx * info->io.regspacing, |
1165 | 1192 | info->io.regsize); | |
1166 | release_region (addr, mapsize); | 1193 | } |
1167 | } | 1194 | } |
1168 | } | 1195 | } |
1169 | 1196 | ||
1170 | static int port_setup(struct smi_info *info) | 1197 | static int port_setup(struct smi_info *info) |
1171 | { | 1198 | { |
1172 | unsigned int addr = info->io.addr_data; | 1199 | unsigned int addr = info->io.addr_data; |
1173 | int mapsize; | 1200 | int idx; |
1174 | 1201 | ||
1175 | if (!addr) | 1202 | if (!addr) |
1176 | return -ENODEV; | 1203 | return -ENODEV; |
@@ -1198,16 +1225,22 @@ static int port_setup(struct smi_info *info) | |||
1198 | return -EINVAL; | 1225 | return -EINVAL; |
1199 | } | 1226 | } |
1200 | 1227 | ||
1201 | /* Calculate the total amount of memory to claim. This is an | 1228 | /* Some BIOSes reserve disjoint I/O regions in their ACPI |
1202 | * unusual looking calculation, but it avoids claiming any | 1229 | * tables. This causes problems when trying to register the |
1203 | * more memory than it has to. It will claim everything | 1230 | * entire I/O region. Therefore we must register each I/O |
1204 | * between the first address to the end of the last full | 1231 | * port separately. |
1205 | * register. */ | 1232 | */ |
1206 | mapsize = ((info->io_size * info->io.regspacing) | 1233 | for (idx = 0; idx < info->io_size; idx++) { |
1207 | - (info->io.regspacing - info->io.regsize)); | 1234 | if (request_region(addr + idx * info->io.regspacing, |
1208 | 1235 | info->io.regsize, DEVICE_NAME) == NULL) { | |
1209 | if (request_region(addr, mapsize, DEVICE_NAME) == NULL) | 1236 | /* Undo allocations */ |
1210 | return -EIO; | 1237 | while (idx--) { |
1238 | release_region(addr + idx * info->io.regspacing, | ||
1239 | info->io.regsize); | ||
1240 | } | ||
1241 | return -EIO; | ||
1242 | } | ||
1243 | } | ||
1211 | return 0; | 1244 | return 0; |
1212 | } | 1245 | } |
1213 | 1246 | ||
@@ -2162,16 +2195,20 @@ static void setup_xaction_handlers(struct smi_info *smi_info) | |||
2162 | 2195 | ||
2163 | static inline void wait_for_timer_and_thread(struct smi_info *smi_info) | 2196 | static inline void wait_for_timer_and_thread(struct smi_info *smi_info) |
2164 | { | 2197 | { |
2165 | if (smi_info->thread != NULL && smi_info->thread != ERR_PTR(-ENOMEM)) | 2198 | if (smi_info->intf) { |
2166 | kthread_stop(smi_info->thread); | 2199 | /* The timer and thread are only running if the |
2167 | del_timer_sync(&smi_info->si_timer); | 2200 | interface has been started up and registered. */ |
2201 | if (smi_info->thread != NULL) | ||
2202 | kthread_stop(smi_info->thread); | ||
2203 | del_timer_sync(&smi_info->si_timer); | ||
2204 | } | ||
2168 | } | 2205 | } |
2169 | 2206 | ||
2170 | static struct ipmi_default_vals | 2207 | static __devinitdata struct ipmi_default_vals |
2171 | { | 2208 | { |
2172 | int type; | 2209 | int type; |
2173 | int port; | 2210 | int port; |
2174 | } __devinit ipmi_defaults[] = | 2211 | } ipmi_defaults[] = |
2175 | { | 2212 | { |
2176 | { .type = SI_KCS, .port = 0xca2 }, | 2213 | { .type = SI_KCS, .port = 0xca2 }, |
2177 | { .type = SI_SMIC, .port = 0xca9 }, | 2214 | { .type = SI_SMIC, .port = 0xca9 }, |
@@ -2245,7 +2282,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2245 | new_smi->slave_addr, new_smi->irq); | 2282 | new_smi->slave_addr, new_smi->irq); |
2246 | } | 2283 | } |
2247 | 2284 | ||
2248 | down(&smi_infos_lock); | 2285 | mutex_lock(&smi_infos_lock); |
2249 | if (!is_new_interface(new_smi)) { | 2286 | if (!is_new_interface(new_smi)) { |
2250 | printk(KERN_WARNING "ipmi_si: duplicate interface\n"); | 2287 | printk(KERN_WARNING "ipmi_si: duplicate interface\n"); |
2251 | rv = -EBUSY; | 2288 | rv = -EBUSY; |
@@ -2341,21 +2378,6 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2341 | if (new_smi->irq) | 2378 | if (new_smi->irq) |
2342 | new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ; | 2379 | new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ; |
2343 | 2380 | ||
2344 | /* The ipmi_register_smi() code does some operations to | ||
2345 | determine the channel information, so we must be ready to | ||
2346 | handle operations before it is called. This means we have | ||
2347 | to stop the timer if we get an error after this point. */ | ||
2348 | init_timer(&(new_smi->si_timer)); | ||
2349 | new_smi->si_timer.data = (long) new_smi; | ||
2350 | new_smi->si_timer.function = smi_timeout; | ||
2351 | new_smi->last_timeout_jiffies = jiffies; | ||
2352 | new_smi->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; | ||
2353 | |||
2354 | add_timer(&(new_smi->si_timer)); | ||
2355 | if (new_smi->si_type != SI_BT) | ||
2356 | new_smi->thread = kthread_run(ipmi_thread, new_smi, | ||
2357 | "kipmi%d", new_smi->intf_num); | ||
2358 | |||
2359 | if (!new_smi->dev) { | 2381 | if (!new_smi->dev) { |
2360 | /* If we don't already have a device from something | 2382 | /* If we don't already have a device from something |
2361 | * else (like PCI), then register a new one. */ | 2383 | * else (like PCI), then register a new one. */ |
@@ -2365,7 +2387,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2365 | printk(KERN_ERR | 2387 | printk(KERN_ERR |
2366 | "ipmi_si_intf:" | 2388 | "ipmi_si_intf:" |
2367 | " Unable to allocate platform device\n"); | 2389 | " Unable to allocate platform device\n"); |
2368 | goto out_err_stop_timer; | 2390 | goto out_err; |
2369 | } | 2391 | } |
2370 | new_smi->dev = &new_smi->pdev->dev; | 2392 | new_smi->dev = &new_smi->pdev->dev; |
2371 | new_smi->dev->driver = &ipmi_driver; | 2393 | new_smi->dev->driver = &ipmi_driver; |
@@ -2377,7 +2399,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2377 | " Unable to register system interface device:" | 2399 | " Unable to register system interface device:" |
2378 | " %d\n", | 2400 | " %d\n", |
2379 | rv); | 2401 | rv); |
2380 | goto out_err_stop_timer; | 2402 | goto out_err; |
2381 | } | 2403 | } |
2382 | new_smi->dev_registered = 1; | 2404 | new_smi->dev_registered = 1; |
2383 | } | 2405 | } |
@@ -2386,8 +2408,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2386 | new_smi, | 2408 | new_smi, |
2387 | &new_smi->device_id, | 2409 | &new_smi->device_id, |
2388 | new_smi->dev, | 2410 | new_smi->dev, |
2389 | new_smi->slave_addr, | 2411 | new_smi->slave_addr); |
2390 | &(new_smi->intf)); | ||
2391 | if (rv) { | 2412 | if (rv) { |
2392 | printk(KERN_ERR | 2413 | printk(KERN_ERR |
2393 | "ipmi_si: Unable to register device: error %d\n", | 2414 | "ipmi_si: Unable to register device: error %d\n", |
@@ -2417,7 +2438,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2417 | 2438 | ||
2418 | list_add_tail(&new_smi->link, &smi_infos); | 2439 | list_add_tail(&new_smi->link, &smi_infos); |
2419 | 2440 | ||
2420 | up(&smi_infos_lock); | 2441 | mutex_unlock(&smi_infos_lock); |
2421 | 2442 | ||
2422 | printk(" IPMI %s interface initialized\n",si_to_str[new_smi->si_type]); | 2443 | printk(" IPMI %s interface initialized\n",si_to_str[new_smi->si_type]); |
2423 | 2444 | ||
@@ -2454,7 +2475,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2454 | 2475 | ||
2455 | kfree(new_smi); | 2476 | kfree(new_smi); |
2456 | 2477 | ||
2457 | up(&smi_infos_lock); | 2478 | mutex_unlock(&smi_infos_lock); |
2458 | 2479 | ||
2459 | return rv; | 2480 | return rv; |
2460 | } | 2481 | } |
@@ -2512,26 +2533,26 @@ static __devinit int init_ipmi_si(void) | |||
2512 | #endif | 2533 | #endif |
2513 | 2534 | ||
2514 | if (si_trydefaults) { | 2535 | if (si_trydefaults) { |
2515 | down(&smi_infos_lock); | 2536 | mutex_lock(&smi_infos_lock); |
2516 | if (list_empty(&smi_infos)) { | 2537 | if (list_empty(&smi_infos)) { |
2517 | /* No BMC was found, try defaults. */ | 2538 | /* No BMC was found, try defaults. */ |
2518 | up(&smi_infos_lock); | 2539 | mutex_unlock(&smi_infos_lock); |
2519 | default_find_bmc(); | 2540 | default_find_bmc(); |
2520 | } else { | 2541 | } else { |
2521 | up(&smi_infos_lock); | 2542 | mutex_unlock(&smi_infos_lock); |
2522 | } | 2543 | } |
2523 | } | 2544 | } |
2524 | 2545 | ||
2525 | down(&smi_infos_lock); | 2546 | mutex_lock(&smi_infos_lock); |
2526 | if (list_empty(&smi_infos)) { | 2547 | if (list_empty(&smi_infos)) { |
2527 | up(&smi_infos_lock); | 2548 | mutex_unlock(&smi_infos_lock); |
2528 | #ifdef CONFIG_PCI | 2549 | #ifdef CONFIG_PCI |
2529 | pci_unregister_driver(&ipmi_pci_driver); | 2550 | pci_unregister_driver(&ipmi_pci_driver); |
2530 | #endif | 2551 | #endif |
2531 | printk("ipmi_si: Unable to find any System Interface(s)\n"); | 2552 | printk("ipmi_si: Unable to find any System Interface(s)\n"); |
2532 | return -ENODEV; | 2553 | return -ENODEV; |
2533 | } else { | 2554 | } else { |
2534 | up(&smi_infos_lock); | 2555 | mutex_unlock(&smi_infos_lock); |
2535 | return 0; | 2556 | return 0; |
2536 | } | 2557 | } |
2537 | } | 2558 | } |
@@ -2607,10 +2628,10 @@ static __exit void cleanup_ipmi_si(void) | |||
2607 | pci_unregister_driver(&ipmi_pci_driver); | 2628 | pci_unregister_driver(&ipmi_pci_driver); |
2608 | #endif | 2629 | #endif |
2609 | 2630 | ||
2610 | down(&smi_infos_lock); | 2631 | mutex_lock(&smi_infos_lock); |
2611 | list_for_each_entry_safe(e, tmp_e, &smi_infos, link) | 2632 | list_for_each_entry_safe(e, tmp_e, &smi_infos, link) |
2612 | cleanup_one_si(e); | 2633 | cleanup_one_si(e); |
2613 | up(&smi_infos_lock); | 2634 | mutex_unlock(&smi_infos_lock); |
2614 | 2635 | ||
2615 | driver_unregister(&ipmi_driver); | 2636 | driver_unregister(&ipmi_driver); |
2616 | } | 2637 | } |
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 7ece9f3c8f70..2d11ddd99e55 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/watchdog.h> | 39 | #include <linux/watchdog.h> |
40 | #include <linux/miscdevice.h> | 40 | #include <linux/miscdevice.h> |
41 | #include <linux/init.h> | 41 | #include <linux/init.h> |
42 | #include <linux/completion.h> | ||
42 | #include <linux/rwsem.h> | 43 | #include <linux/rwsem.h> |
43 | #include <linux/errno.h> | 44 | #include <linux/errno.h> |
44 | #include <asm/uaccess.h> | 45 | #include <asm/uaccess.h> |
@@ -303,21 +304,22 @@ static int ipmi_heartbeat(void); | |||
303 | static void panic_halt_ipmi_heartbeat(void); | 304 | static void panic_halt_ipmi_heartbeat(void); |
304 | 305 | ||
305 | 306 | ||
306 | /* We use a semaphore to make sure that only one thing can send a set | 307 | /* We use a mutex to make sure that only one thing can send a set |
307 | timeout at one time, because we only have one copy of the data. | 308 | timeout at one time, because we only have one copy of the data. |
308 | The semaphore is claimed when the set_timeout is sent and freed | 309 | The mutex is claimed when the set_timeout is sent and freed |
309 | when both messages are free. */ | 310 | when both messages are free. */ |
310 | static atomic_t set_timeout_tofree = ATOMIC_INIT(0); | 311 | static atomic_t set_timeout_tofree = ATOMIC_INIT(0); |
311 | static DECLARE_MUTEX(set_timeout_lock); | 312 | static DEFINE_MUTEX(set_timeout_lock); |
313 | static DECLARE_COMPLETION(set_timeout_wait); | ||
312 | static void set_timeout_free_smi(struct ipmi_smi_msg *msg) | 314 | static void set_timeout_free_smi(struct ipmi_smi_msg *msg) |
313 | { | 315 | { |
314 | if (atomic_dec_and_test(&set_timeout_tofree)) | 316 | if (atomic_dec_and_test(&set_timeout_tofree)) |
315 | up(&set_timeout_lock); | 317 | complete(&set_timeout_wait); |
316 | } | 318 | } |
317 | static void set_timeout_free_recv(struct ipmi_recv_msg *msg) | 319 | static void set_timeout_free_recv(struct ipmi_recv_msg *msg) |
318 | { | 320 | { |
319 | if (atomic_dec_and_test(&set_timeout_tofree)) | 321 | if (atomic_dec_and_test(&set_timeout_tofree)) |
320 | up(&set_timeout_lock); | 322 | complete(&set_timeout_wait); |
321 | } | 323 | } |
322 | static struct ipmi_smi_msg set_timeout_smi_msg = | 324 | static struct ipmi_smi_msg set_timeout_smi_msg = |
323 | { | 325 | { |
@@ -399,7 +401,7 @@ static int ipmi_set_timeout(int do_heartbeat) | |||
399 | 401 | ||
400 | 402 | ||
401 | /* We can only send one of these at a time. */ | 403 | /* We can only send one of these at a time. */ |
402 | down(&set_timeout_lock); | 404 | mutex_lock(&set_timeout_lock); |
403 | 405 | ||
404 | atomic_set(&set_timeout_tofree, 2); | 406 | atomic_set(&set_timeout_tofree, 2); |
405 | 407 | ||
@@ -407,16 +409,21 @@ static int ipmi_set_timeout(int do_heartbeat) | |||
407 | &set_timeout_recv_msg, | 409 | &set_timeout_recv_msg, |
408 | &send_heartbeat_now); | 410 | &send_heartbeat_now); |
409 | if (rv) { | 411 | if (rv) { |
410 | up(&set_timeout_lock); | 412 | mutex_unlock(&set_timeout_lock); |
411 | } else { | 413 | goto out; |
412 | if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB) | ||
413 | || ((send_heartbeat_now) | ||
414 | && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY))) | ||
415 | { | ||
416 | rv = ipmi_heartbeat(); | ||
417 | } | ||
418 | } | 414 | } |
419 | 415 | ||
416 | wait_for_completion(&set_timeout_wait); | ||
417 | |||
418 | if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB) | ||
419 | || ((send_heartbeat_now) | ||
420 | && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY))) | ||
421 | { | ||
422 | rv = ipmi_heartbeat(); | ||
423 | } | ||
424 | mutex_unlock(&set_timeout_lock); | ||
425 | |||
426 | out: | ||
420 | return rv; | 427 | return rv; |
421 | } | 428 | } |
422 | 429 | ||
@@ -458,17 +465,17 @@ static void panic_halt_ipmi_set_timeout(void) | |||
458 | The semaphore is claimed when the set_timeout is sent and freed | 465 | The semaphore is claimed when the set_timeout is sent and freed |
459 | when both messages are free. */ | 466 | when both messages are free. */ |
460 | static atomic_t heartbeat_tofree = ATOMIC_INIT(0); | 467 | static atomic_t heartbeat_tofree = ATOMIC_INIT(0); |
461 | static DECLARE_MUTEX(heartbeat_lock); | 468 | static DEFINE_MUTEX(heartbeat_lock); |
462 | static DECLARE_MUTEX_LOCKED(heartbeat_wait_lock); | 469 | static DECLARE_COMPLETION(heartbeat_wait); |
463 | static void heartbeat_free_smi(struct ipmi_smi_msg *msg) | 470 | static void heartbeat_free_smi(struct ipmi_smi_msg *msg) |
464 | { | 471 | { |
465 | if (atomic_dec_and_test(&heartbeat_tofree)) | 472 | if (atomic_dec_and_test(&heartbeat_tofree)) |
466 | up(&heartbeat_wait_lock); | 473 | complete(&heartbeat_wait); |
467 | } | 474 | } |
468 | static void heartbeat_free_recv(struct ipmi_recv_msg *msg) | 475 | static void heartbeat_free_recv(struct ipmi_recv_msg *msg) |
469 | { | 476 | { |
470 | if (atomic_dec_and_test(&heartbeat_tofree)) | 477 | if (atomic_dec_and_test(&heartbeat_tofree)) |
471 | up(&heartbeat_wait_lock); | 478 | complete(&heartbeat_wait); |
472 | } | 479 | } |
473 | static struct ipmi_smi_msg heartbeat_smi_msg = | 480 | static struct ipmi_smi_msg heartbeat_smi_msg = |
474 | { | 481 | { |
@@ -511,14 +518,14 @@ static int ipmi_heartbeat(void) | |||
511 | return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); | 518 | return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); |
512 | } | 519 | } |
513 | 520 | ||
514 | down(&heartbeat_lock); | 521 | mutex_lock(&heartbeat_lock); |
515 | 522 | ||
516 | atomic_set(&heartbeat_tofree, 2); | 523 | atomic_set(&heartbeat_tofree, 2); |
517 | 524 | ||
518 | /* Don't reset the timer if we have the timer turned off, that | 525 | /* Don't reset the timer if we have the timer turned off, that |
519 | re-enables the watchdog. */ | 526 | re-enables the watchdog. */ |
520 | if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) { | 527 | if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) { |
521 | up(&heartbeat_lock); | 528 | mutex_unlock(&heartbeat_lock); |
522 | return 0; | 529 | return 0; |
523 | } | 530 | } |
524 | 531 | ||
@@ -539,14 +546,14 @@ static int ipmi_heartbeat(void) | |||
539 | &heartbeat_recv_msg, | 546 | &heartbeat_recv_msg, |
540 | 1); | 547 | 1); |
541 | if (rv) { | 548 | if (rv) { |
542 | up(&heartbeat_lock); | 549 | mutex_unlock(&heartbeat_lock); |
543 | printk(KERN_WARNING PFX "heartbeat failure: %d\n", | 550 | printk(KERN_WARNING PFX "heartbeat failure: %d\n", |
544 | rv); | 551 | rv); |
545 | return rv; | 552 | return rv; |
546 | } | 553 | } |
547 | 554 | ||
548 | /* Wait for the heartbeat to be sent. */ | 555 | /* Wait for the heartbeat to be sent. */ |
549 | down(&heartbeat_wait_lock); | 556 | wait_for_completion(&heartbeat_wait); |
550 | 557 | ||
551 | if (heartbeat_recv_msg.msg.data[0] != 0) { | 558 | if (heartbeat_recv_msg.msg.data[0] != 0) { |
552 | /* Got an error in the heartbeat response. It was already | 559 | /* Got an error in the heartbeat response. It was already |
@@ -555,7 +562,7 @@ static int ipmi_heartbeat(void) | |||
555 | rv = -EINVAL; | 562 | rv = -EINVAL; |
556 | } | 563 | } |
557 | 564 | ||
558 | up(&heartbeat_lock); | 565 | mutex_unlock(&heartbeat_lock); |
559 | 566 | ||
560 | return rv; | 567 | return rv; |
561 | } | 568 | } |
@@ -589,7 +596,7 @@ static void panic_halt_ipmi_heartbeat(void) | |||
589 | 1); | 596 | 1); |
590 | } | 597 | } |
591 | 598 | ||
592 | static struct watchdog_info ident= | 599 | static struct watchdog_info ident = |
593 | { | 600 | { |
594 | .options = 0, /* WDIOF_SETTIMEOUT, */ | 601 | .options = 0, /* WDIOF_SETTIMEOUT, */ |
595 | .firmware_version = 1, | 602 | .firmware_version = 1, |
@@ -790,13 +797,13 @@ static int ipmi_fasync(int fd, struct file *file, int on) | |||
790 | 797 | ||
791 | static int ipmi_close(struct inode *ino, struct file *filep) | 798 | static int ipmi_close(struct inode *ino, struct file *filep) |
792 | { | 799 | { |
793 | if (iminor(ino)==WATCHDOG_MINOR) | 800 | if (iminor(ino) == WATCHDOG_MINOR) { |
794 | { | ||
795 | if (expect_close == 42) { | 801 | if (expect_close == 42) { |
796 | ipmi_watchdog_state = WDOG_TIMEOUT_NONE; | 802 | ipmi_watchdog_state = WDOG_TIMEOUT_NONE; |
797 | ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); | 803 | ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); |
798 | } else { | 804 | } else { |
799 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | 805 | printk(KERN_CRIT PFX |
806 | "Unexpected close, not stopping watchdog!\n"); | ||
800 | ipmi_heartbeat(); | 807 | ipmi_heartbeat(); |
801 | } | 808 | } |
802 | clear_bit(0, &ipmi_wdog_open); | 809 | clear_bit(0, &ipmi_wdog_open); |
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index e5247f85a446..ef20c1fc9c4c 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -706,7 +706,6 @@ static int stli_portcmdstats(stliport_t *portp); | |||
706 | static int stli_clrportstats(stliport_t *portp, comstats_t __user *cp); | 706 | static int stli_clrportstats(stliport_t *portp, comstats_t __user *cp); |
707 | static int stli_getportstruct(stliport_t __user *arg); | 707 | static int stli_getportstruct(stliport_t __user *arg); |
708 | static int stli_getbrdstruct(stlibrd_t __user *arg); | 708 | static int stli_getbrdstruct(stlibrd_t __user *arg); |
709 | static void *stli_memalloc(int len); | ||
710 | static stlibrd_t *stli_allocbrd(void); | 709 | static stlibrd_t *stli_allocbrd(void); |
711 | 710 | ||
712 | static void stli_ecpinit(stlibrd_t *brdp); | 711 | static void stli_ecpinit(stlibrd_t *brdp); |
@@ -997,17 +996,6 @@ static int stli_parsebrd(stlconf_t *confp, char **argp) | |||
997 | 996 | ||
998 | /*****************************************************************************/ | 997 | /*****************************************************************************/ |
999 | 998 | ||
1000 | /* | ||
1001 | * Local driver kernel malloc routine. | ||
1002 | */ | ||
1003 | |||
1004 | static void *stli_memalloc(int len) | ||
1005 | { | ||
1006 | return((void *) kmalloc(len, GFP_KERNEL)); | ||
1007 | } | ||
1008 | |||
1009 | /*****************************************************************************/ | ||
1010 | |||
1011 | static int stli_open(struct tty_struct *tty, struct file *filp) | 999 | static int stli_open(struct tty_struct *tty, struct file *filp) |
1012 | { | 1000 | { |
1013 | stlibrd_t *brdp; | 1001 | stlibrd_t *brdp; |
@@ -3227,13 +3215,12 @@ static int stli_initports(stlibrd_t *brdp) | |||
3227 | #endif | 3215 | #endif |
3228 | 3216 | ||
3229 | for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) { | 3217 | for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) { |
3230 | portp = (stliport_t *) stli_memalloc(sizeof(stliport_t)); | 3218 | portp = kzalloc(sizeof(stliport_t), GFP_KERNEL); |
3231 | if (portp == (stliport_t *) NULL) { | 3219 | if (!portp) { |
3232 | printk("STALLION: failed to allocate port structure\n"); | 3220 | printk("STALLION: failed to allocate port structure\n"); |
3233 | continue; | 3221 | continue; |
3234 | } | 3222 | } |
3235 | 3223 | ||
3236 | memset(portp, 0, sizeof(stliport_t)); | ||
3237 | portp->magic = STLI_PORTMAGIC; | 3224 | portp->magic = STLI_PORTMAGIC; |
3238 | portp->portnr = i; | 3225 | portp->portnr = i; |
3239 | portp->brdnr = brdp->brdnr; | 3226 | portp->brdnr = brdp->brdnr; |
@@ -4610,14 +4597,13 @@ static stlibrd_t *stli_allocbrd(void) | |||
4610 | { | 4597 | { |
4611 | stlibrd_t *brdp; | 4598 | stlibrd_t *brdp; |
4612 | 4599 | ||
4613 | brdp = (stlibrd_t *) stli_memalloc(sizeof(stlibrd_t)); | 4600 | brdp = kzalloc(sizeof(stlibrd_t), GFP_KERNEL); |
4614 | if (brdp == (stlibrd_t *) NULL) { | 4601 | if (!brdp) { |
4615 | printk(KERN_ERR "STALLION: failed to allocate memory " | 4602 | printk(KERN_ERR "STALLION: failed to allocate memory " |
4616 | "(size=%d)\n", sizeof(stlibrd_t)); | 4603 | "(size=%d)\n", sizeof(stlibrd_t)); |
4617 | return((stlibrd_t *) NULL); | 4604 | return NULL; |
4618 | } | 4605 | } |
4619 | 4606 | ||
4620 | memset(brdp, 0, sizeof(stlibrd_t)); | ||
4621 | brdp->magic = STLI_BOARDMAGIC; | 4607 | brdp->magic = STLI_BOARDMAGIC; |
4622 | return(brdp); | 4608 | return(brdp); |
4623 | } | 4609 | } |
@@ -5210,12 +5196,12 @@ int __init stli_init(void) | |||
5210 | /* | 5196 | /* |
5211 | * Allocate a temporary write buffer. | 5197 | * Allocate a temporary write buffer. |
5212 | */ | 5198 | */ |
5213 | stli_tmpwritebuf = (char *) stli_memalloc(STLI_TXBUFSIZE); | 5199 | stli_tmpwritebuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL); |
5214 | if (stli_tmpwritebuf == (char *) NULL) | 5200 | if (!stli_tmpwritebuf) |
5215 | printk(KERN_ERR "STALLION: failed to allocate memory " | 5201 | printk(KERN_ERR "STALLION: failed to allocate memory " |
5216 | "(size=%d)\n", STLI_TXBUFSIZE); | 5202 | "(size=%d)\n", STLI_TXBUFSIZE); |
5217 | stli_txcookbuf = stli_memalloc(STLI_TXBUFSIZE); | 5203 | stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL); |
5218 | if (stli_txcookbuf == (char *) NULL) | 5204 | if (!stli_txcookbuf) |
5219 | printk(KERN_ERR "STALLION: failed to allocate memory " | 5205 | printk(KERN_ERR "STALLION: failed to allocate memory " |
5220 | "(size=%d)\n", STLI_TXBUFSIZE); | 5206 | "(size=%d)\n", STLI_TXBUFSIZE); |
5221 | 5207 | ||
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 8b603b2d1c42..5755b7e5f187 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
@@ -74,7 +74,7 @@ void compute_shiftstate(void); | |||
74 | k_self, k_fn, k_spec, k_pad,\ | 74 | k_self, k_fn, k_spec, k_pad,\ |
75 | k_dead, k_cons, k_cur, k_shift,\ | 75 | k_dead, k_cons, k_cur, k_shift,\ |
76 | k_meta, k_ascii, k_lock, k_lowercase,\ | 76 | k_meta, k_ascii, k_lock, k_lowercase,\ |
77 | k_slock, k_dead2, k_ignore, k_ignore | 77 | k_slock, k_dead2, k_brl, k_ignore |
78 | 78 | ||
79 | typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value, | 79 | typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value, |
80 | char up_flag, struct pt_regs *regs); | 80 | char up_flag, struct pt_regs *regs); |
@@ -100,7 +100,7 @@ static fn_handler_fn *fn_handler[] = { FN_HANDLERS }; | |||
100 | const int max_vals[] = { | 100 | const int max_vals[] = { |
101 | 255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1, | 101 | 255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1, |
102 | NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1, | 102 | NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1, |
103 | 255, NR_LOCK - 1, 255 | 103 | 255, NR_LOCK - 1, 255, NR_BRL - 1 |
104 | }; | 104 | }; |
105 | 105 | ||
106 | const int NR_TYPES = ARRAY_SIZE(max_vals); | 106 | const int NR_TYPES = ARRAY_SIZE(max_vals); |
@@ -126,7 +126,7 @@ static unsigned long key_down[NBITS(KEY_MAX)]; /* keyboard key bitmap */ | |||
126 | static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */ | 126 | static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */ |
127 | static int dead_key_next; | 127 | static int dead_key_next; |
128 | static int npadch = -1; /* -1 or number assembled on pad */ | 128 | static int npadch = -1; /* -1 or number assembled on pad */ |
129 | static unsigned char diacr; | 129 | static unsigned int diacr; |
130 | static char rep; /* flag telling character repeat */ | 130 | static char rep; /* flag telling character repeat */ |
131 | 131 | ||
132 | static unsigned char ledstate = 0xff; /* undefined */ | 132 | static unsigned char ledstate = 0xff; /* undefined */ |
@@ -394,22 +394,30 @@ void compute_shiftstate(void) | |||
394 | * Otherwise, conclude that DIACR was not combining after all, | 394 | * Otherwise, conclude that DIACR was not combining after all, |
395 | * queue it and return CH. | 395 | * queue it and return CH. |
396 | */ | 396 | */ |
397 | static unsigned char handle_diacr(struct vc_data *vc, unsigned char ch) | 397 | static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch) |
398 | { | 398 | { |
399 | int d = diacr; | 399 | unsigned int d = diacr; |
400 | unsigned int i; | 400 | unsigned int i; |
401 | 401 | ||
402 | diacr = 0; | 402 | diacr = 0; |
403 | 403 | ||
404 | for (i = 0; i < accent_table_size; i++) { | 404 | if ((d & ~0xff) == BRL_UC_ROW) { |
405 | if (accent_table[i].diacr == d && accent_table[i].base == ch) | 405 | if ((ch & ~0xff) == BRL_UC_ROW) |
406 | return accent_table[i].result; | 406 | return d | ch; |
407 | } else { | ||
408 | for (i = 0; i < accent_table_size; i++) | ||
409 | if (accent_table[i].diacr == d && accent_table[i].base == ch) | ||
410 | return accent_table[i].result; | ||
407 | } | 411 | } |
408 | 412 | ||
409 | if (ch == ' ' || ch == d) | 413 | if (ch == ' ' || ch == (BRL_UC_ROW|0) || ch == d) |
410 | return d; | 414 | return d; |
411 | 415 | ||
412 | put_queue(vc, d); | 416 | if (kbd->kbdmode == VC_UNICODE) |
417 | to_utf8(vc, d); | ||
418 | else if (d < 0x100) | ||
419 | put_queue(vc, d); | ||
420 | |||
413 | return ch; | 421 | return ch; |
414 | } | 422 | } |
415 | 423 | ||
@@ -419,7 +427,10 @@ static unsigned char handle_diacr(struct vc_data *vc, unsigned char ch) | |||
419 | static void fn_enter(struct vc_data *vc, struct pt_regs *regs) | 427 | static void fn_enter(struct vc_data *vc, struct pt_regs *regs) |
420 | { | 428 | { |
421 | if (diacr) { | 429 | if (diacr) { |
422 | put_queue(vc, diacr); | 430 | if (kbd->kbdmode == VC_UNICODE) |
431 | to_utf8(vc, diacr); | ||
432 | else if (diacr < 0x100) | ||
433 | put_queue(vc, diacr); | ||
423 | diacr = 0; | 434 | diacr = 0; |
424 | } | 435 | } |
425 | put_queue(vc, 13); | 436 | put_queue(vc, 13); |
@@ -615,7 +626,7 @@ static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag, s | |||
615 | printk(KERN_ERR "keyboard.c: k_lowercase was called - impossible\n"); | 626 | printk(KERN_ERR "keyboard.c: k_lowercase was called - impossible\n"); |
616 | } | 627 | } |
617 | 628 | ||
618 | static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) | 629 | static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag, struct pt_regs *regs) |
619 | { | 630 | { |
620 | if (up_flag) | 631 | if (up_flag) |
621 | return; /* no action, if this is a key release */ | 632 | return; /* no action, if this is a key release */ |
@@ -628,7 +639,10 @@ static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct | |||
628 | diacr = value; | 639 | diacr = value; |
629 | return; | 640 | return; |
630 | } | 641 | } |
631 | put_queue(vc, value); | 642 | if (kbd->kbdmode == VC_UNICODE) |
643 | to_utf8(vc, value); | ||
644 | else if (value < 0x100) | ||
645 | put_queue(vc, value); | ||
632 | } | 646 | } |
633 | 647 | ||
634 | /* | 648 | /* |
@@ -636,13 +650,23 @@ static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct | |||
636 | * dead keys modifying the same character. Very useful | 650 | * dead keys modifying the same character. Very useful |
637 | * for Vietnamese. | 651 | * for Vietnamese. |
638 | */ | 652 | */ |
639 | static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) | 653 | static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag, struct pt_regs *regs) |
640 | { | 654 | { |
641 | if (up_flag) | 655 | if (up_flag) |
642 | return; | 656 | return; |
643 | diacr = (diacr ? handle_diacr(vc, value) : value); | 657 | diacr = (diacr ? handle_diacr(vc, value) : value); |
644 | } | 658 | } |
645 | 659 | ||
660 | static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) | ||
661 | { | ||
662 | k_unicode(vc, value, up_flag, regs); | ||
663 | } | ||
664 | |||
665 | static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) | ||
666 | { | ||
667 | k_deadunicode(vc, value, up_flag, regs); | ||
668 | } | ||
669 | |||
646 | /* | 670 | /* |
647 | * Obsolete - for backwards compatibility only | 671 | * Obsolete - for backwards compatibility only |
648 | */ | 672 | */ |
@@ -650,7 +674,7 @@ static void k_dead(struct vc_data *vc, unsigned char value, char up_flag, struct | |||
650 | { | 674 | { |
651 | static unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' }; | 675 | static unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' }; |
652 | value = ret_diacr[value]; | 676 | value = ret_diacr[value]; |
653 | k_dead2(vc, value, up_flag, regs); | 677 | k_deadunicode(vc, value, up_flag, regs); |
654 | } | 678 | } |
655 | 679 | ||
656 | static void k_cons(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) | 680 | static void k_cons(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) |
@@ -835,6 +859,80 @@ static void k_slock(struct vc_data *vc, unsigned char value, char up_flag, struc | |||
835 | } | 859 | } |
836 | } | 860 | } |
837 | 861 | ||
862 | /* by default, 300ms interval for combination release */ | ||
863 | static unsigned brl_timeout = 300; | ||
864 | MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for commit on first key release)"); | ||
865 | module_param(brl_timeout, uint, 0644); | ||
866 | |||
867 | static unsigned brl_nbchords = 1; | ||
868 | MODULE_PARM_DESC(brl_nbchords, "Number of chords that produce a braille pattern (0 for dead chords)"); | ||
869 | module_param(brl_nbchords, uint, 0644); | ||
870 | |||
871 | static void k_brlcommit(struct vc_data *vc, unsigned int pattern, char up_flag, struct pt_regs *regs) | ||
872 | { | ||
873 | static unsigned long chords; | ||
874 | static unsigned committed; | ||
875 | |||
876 | if (!brl_nbchords) | ||
877 | k_deadunicode(vc, BRL_UC_ROW | pattern, up_flag, regs); | ||
878 | else { | ||
879 | committed |= pattern; | ||
880 | chords++; | ||
881 | if (chords == brl_nbchords) { | ||
882 | k_unicode(vc, BRL_UC_ROW | committed, up_flag, regs); | ||
883 | chords = 0; | ||
884 | committed = 0; | ||
885 | } | ||
886 | } | ||
887 | } | ||
888 | |||
889 | static void k_brl(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) | ||
890 | { | ||
891 | static unsigned pressed,committing; | ||
892 | static unsigned long releasestart; | ||
893 | |||
894 | if (kbd->kbdmode != VC_UNICODE) { | ||
895 | if (!up_flag) | ||
896 | printk("keyboard mode must be unicode for braille patterns\n"); | ||
897 | return; | ||
898 | } | ||
899 | |||
900 | if (!value) { | ||
901 | k_unicode(vc, BRL_UC_ROW, up_flag, regs); | ||
902 | return; | ||
903 | } | ||
904 | |||
905 | if (value > 8) | ||
906 | return; | ||
907 | |||
908 | if (up_flag) { | ||
909 | if (brl_timeout) { | ||
910 | if (!committing || | ||
911 | jiffies - releasestart > (brl_timeout * HZ) / 1000) { | ||
912 | committing = pressed; | ||
913 | releasestart = jiffies; | ||
914 | } | ||
915 | pressed &= ~(1 << (value - 1)); | ||
916 | if (!pressed) { | ||
917 | if (committing) { | ||
918 | k_brlcommit(vc, committing, 0, regs); | ||
919 | committing = 0; | ||
920 | } | ||
921 | } | ||
922 | } else { | ||
923 | if (committing) { | ||
924 | k_brlcommit(vc, committing, 0, regs); | ||
925 | committing = 0; | ||
926 | } | ||
927 | pressed &= ~(1 << (value - 1)); | ||
928 | } | ||
929 | } else { | ||
930 | pressed |= 1 << (value - 1); | ||
931 | if (!brl_timeout) | ||
932 | committing = pressed; | ||
933 | } | ||
934 | } | ||
935 | |||
838 | /* | 936 | /* |
839 | * The leds display either (i) the status of NumLock, CapsLock, ScrollLock, | 937 | * The leds display either (i) the status of NumLock, CapsLock, ScrollLock, |
840 | * or (ii) whatever pattern of lights people want to show using KDSETLED, | 938 | * or (ii) whatever pattern of lights people want to show using KDSETLED, |
@@ -1125,9 +1223,13 @@ static void kbd_keycode(unsigned int keycode, int down, | |||
1125 | } | 1223 | } |
1126 | 1224 | ||
1127 | if (keycode > NR_KEYS) | 1225 | if (keycode > NR_KEYS) |
1128 | return; | 1226 | if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8) |
1227 | keysym = K(KT_BRL, keycode - KEY_BRL_DOT1 + 1); | ||
1228 | else | ||
1229 | return; | ||
1230 | else | ||
1231 | keysym = key_map[keycode]; | ||
1129 | 1232 | ||
1130 | keysym = key_map[keycode]; | ||
1131 | type = KTYP(keysym); | 1233 | type = KTYP(keysym); |
1132 | 1234 | ||
1133 | if (type < 0xf0) { | 1235 | if (type < 0xf0) { |
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 66719f9d294c..1fa9fa157c12 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/crash_dump.h> | 27 | #include <linux/crash_dump.h> |
28 | #include <linux/backing-dev.h> | 28 | #include <linux/backing-dev.h> |
29 | #include <linux/bootmem.h> | 29 | #include <linux/bootmem.h> |
30 | #include <linux/pipe_fs_i.h> | ||
30 | 31 | ||
31 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
32 | #include <asm/io.h> | 33 | #include <asm/io.h> |
@@ -578,6 +579,18 @@ static ssize_t write_null(struct file * file, const char __user * buf, | |||
578 | return count; | 579 | return count; |
579 | } | 580 | } |
580 | 581 | ||
582 | static int pipe_to_null(struct pipe_inode_info *info, struct pipe_buffer *buf, | ||
583 | struct splice_desc *sd) | ||
584 | { | ||
585 | return sd->len; | ||
586 | } | ||
587 | |||
588 | static ssize_t splice_write_null(struct pipe_inode_info *pipe,struct file *out, | ||
589 | loff_t *ppos, size_t len, unsigned int flags) | ||
590 | { | ||
591 | return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_null); | ||
592 | } | ||
593 | |||
581 | #ifdef CONFIG_MMU | 594 | #ifdef CONFIG_MMU |
582 | /* | 595 | /* |
583 | * For fun, we are using the MMU for this. | 596 | * For fun, we are using the MMU for this. |
@@ -785,6 +798,7 @@ static struct file_operations null_fops = { | |||
785 | .llseek = null_lseek, | 798 | .llseek = null_lseek, |
786 | .read = read_null, | 799 | .read = read_null, |
787 | .write = write_null, | 800 | .write = write_null, |
801 | .splice_write = splice_write_null, | ||
788 | }; | 802 | }; |
789 | 803 | ||
790 | #if defined(CONFIG_ISA) || !defined(__mc68000__) | 804 | #if defined(CONFIG_ISA) || !defined(__mc68000__) |
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c index 8666171e187b..d3ba2f860ef0 100644 --- a/drivers/char/mwave/mwavedd.c +++ b/drivers/char/mwave/mwavedd.c | |||
@@ -271,7 +271,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
271 | ipcnum, | 271 | ipcnum, |
272 | pDrvData->IPCs[ipcnum].usIntCount); | 272 | pDrvData->IPCs[ipcnum].usIntCount); |
273 | 273 | ||
274 | if (ipcnum > ARRAY_SIZE(pDrvData->IPCs)) { | 274 | if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) { |
275 | PRINTK_ERROR(KERN_ERR_MWAVE | 275 | PRINTK_ERROR(KERN_ERR_MWAVE |
276 | "mwavedd::mwave_ioctl:" | 276 | "mwavedd::mwave_ioctl:" |
277 | " IOCTL_MW_REGISTER_IPC:" | 277 | " IOCTL_MW_REGISTER_IPC:" |
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index ede365d05387..b9371d5bf790 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c | |||
@@ -1384,8 +1384,10 @@ do_it_again: | |||
1384 | * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode, | 1384 | * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode, |
1385 | * we won't get any more characters. | 1385 | * we won't get any more characters. |
1386 | */ | 1386 | */ |
1387 | if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE) | 1387 | if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE) { |
1388 | n_tty_set_room(tty); | ||
1388 | check_unthrottle(tty); | 1389 | check_unthrottle(tty); |
1390 | } | ||
1389 | 1391 | ||
1390 | if (b - buf >= minimum) | 1392 | if (b - buf >= minimum) |
1391 | break; | 1393 | break; |
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 5fdf18515433..eab5394da666 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c | |||
@@ -46,7 +46,7 @@ | |||
46 | /* #define ATR_CSUM */ | 46 | /* #define ATR_CSUM */ |
47 | 47 | ||
48 | #ifdef PCMCIA_DEBUG | 48 | #ifdef PCMCIA_DEBUG |
49 | #define reader_to_dev(x) (&handle_to_dev(x->link.handle)) | 49 | #define reader_to_dev(x) (&handle_to_dev(x->p_dev->handle)) |
50 | static int pc_debug = PCMCIA_DEBUG; | 50 | static int pc_debug = PCMCIA_DEBUG; |
51 | module_param(pc_debug, int, 0600); | 51 | module_param(pc_debug, int, 0600); |
52 | #define DEBUGP(n, rdr, x, args...) do { \ | 52 | #define DEBUGP(n, rdr, x, args...) do { \ |
@@ -67,7 +67,7 @@ static char *version = "cm4000_cs.c v2.4.0gm6 - All bugs added by Harald Welte"; | |||
67 | #define T_100MSEC msecs_to_jiffies(100) | 67 | #define T_100MSEC msecs_to_jiffies(100) |
68 | #define T_500MSEC msecs_to_jiffies(500) | 68 | #define T_500MSEC msecs_to_jiffies(500) |
69 | 69 | ||
70 | static void cm4000_release(dev_link_t *link); | 70 | static void cm4000_release(struct pcmcia_device *link); |
71 | 71 | ||
72 | static int major; /* major number we get from the kernel */ | 72 | static int major; /* major number we get from the kernel */ |
73 | 73 | ||
@@ -106,7 +106,7 @@ static int major; /* major number we get from the kernel */ | |||
106 | #define REG_STOPBITS(x) (x + 7) | 106 | #define REG_STOPBITS(x) (x + 7) |
107 | 107 | ||
108 | struct cm4000_dev { | 108 | struct cm4000_dev { |
109 | dev_link_t link; /* pcmcia link */ | 109 | struct pcmcia_device *p_dev; |
110 | dev_node_t node; /* OS node (major,minor) */ | 110 | dev_node_t node; /* OS node (major,minor) */ |
111 | 111 | ||
112 | unsigned char atr[MAX_ATR]; | 112 | unsigned char atr[MAX_ATR]; |
@@ -149,14 +149,14 @@ struct cm4000_dev { | |||
149 | #define ZERO_DEV(dev) \ | 149 | #define ZERO_DEV(dev) \ |
150 | memset(&dev->atr_csum,0, \ | 150 | memset(&dev->atr_csum,0, \ |
151 | sizeof(struct cm4000_dev) - \ | 151 | sizeof(struct cm4000_dev) - \ |
152 | /*link*/ sizeof(dev_link_t) - \ | 152 | /*link*/ sizeof(struct pcmcia_device *) - \ |
153 | /*node*/ sizeof(dev_node_t) - \ | 153 | /*node*/ sizeof(dev_node_t) - \ |
154 | /*atr*/ MAX_ATR*sizeof(char) - \ | 154 | /*atr*/ MAX_ATR*sizeof(char) - \ |
155 | /*rbuf*/ 512*sizeof(char) - \ | 155 | /*rbuf*/ 512*sizeof(char) - \ |
156 | /*sbuf*/ 512*sizeof(char) - \ | 156 | /*sbuf*/ 512*sizeof(char) - \ |
157 | /*queue*/ 4*sizeof(wait_queue_head_t)) | 157 | /*queue*/ 4*sizeof(wait_queue_head_t)) |
158 | 158 | ||
159 | static dev_link_t *dev_table[CM4000_MAX_DEV]; | 159 | static struct pcmcia_device *dev_table[CM4000_MAX_DEV]; |
160 | static struct class *cmm_class; | 160 | static struct class *cmm_class; |
161 | 161 | ||
162 | /* This table doesn't use spaces after the comma between fields and thus | 162 | /* This table doesn't use spaces after the comma between fields and thus |
@@ -454,7 +454,7 @@ static struct card_fixup card_fixups[] = { | |||
454 | static void set_cardparameter(struct cm4000_dev *dev) | 454 | static void set_cardparameter(struct cm4000_dev *dev) |
455 | { | 455 | { |
456 | int i; | 456 | int i; |
457 | ioaddr_t iobase = dev->link.io.BasePort1; | 457 | ioaddr_t iobase = dev->p_dev->io.BasePort1; |
458 | u_int8_t stopbits = 0x02; /* ISO default */ | 458 | u_int8_t stopbits = 0x02; /* ISO default */ |
459 | 459 | ||
460 | DEBUGP(3, dev, "-> set_cardparameter\n"); | 460 | DEBUGP(3, dev, "-> set_cardparameter\n"); |
@@ -487,7 +487,7 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq) | |||
487 | unsigned short num_bytes_read; | 487 | unsigned short num_bytes_read; |
488 | unsigned char pts_reply[4]; | 488 | unsigned char pts_reply[4]; |
489 | ssize_t rc; | 489 | ssize_t rc; |
490 | ioaddr_t iobase = dev->link.io.BasePort1; | 490 | ioaddr_t iobase = dev->p_dev->io.BasePort1; |
491 | 491 | ||
492 | rc = 0; | 492 | rc = 0; |
493 | 493 | ||
@@ -699,7 +699,7 @@ static void terminate_monitor(struct cm4000_dev *dev) | |||
699 | static void monitor_card(unsigned long p) | 699 | static void monitor_card(unsigned long p) |
700 | { | 700 | { |
701 | struct cm4000_dev *dev = (struct cm4000_dev *) p; | 701 | struct cm4000_dev *dev = (struct cm4000_dev *) p; |
702 | ioaddr_t iobase = dev->link.io.BasePort1; | 702 | ioaddr_t iobase = dev->p_dev->io.BasePort1; |
703 | unsigned short s; | 703 | unsigned short s; |
704 | struct ptsreq ptsreq; | 704 | struct ptsreq ptsreq; |
705 | int i, atrc; | 705 | int i, atrc; |
@@ -962,7 +962,7 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count, | |||
962 | loff_t *ppos) | 962 | loff_t *ppos) |
963 | { | 963 | { |
964 | struct cm4000_dev *dev = filp->private_data; | 964 | struct cm4000_dev *dev = filp->private_data; |
965 | ioaddr_t iobase = dev->link.io.BasePort1; | 965 | ioaddr_t iobase = dev->p_dev->io.BasePort1; |
966 | ssize_t rc; | 966 | ssize_t rc; |
967 | int i, j, k; | 967 | int i, j, k; |
968 | 968 | ||
@@ -971,7 +971,7 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count, | |||
971 | if (count == 0) /* according to manpage */ | 971 | if (count == 0) /* according to manpage */ |
972 | return 0; | 972 | return 0; |
973 | 973 | ||
974 | if ((dev->link.state & DEV_PRESENT) == 0 || /* socket removed */ | 974 | if (!pcmcia_dev_present(dev->p_dev) || /* device removed */ |
975 | test_bit(IS_CMM_ABSENT, &dev->flags)) | 975 | test_bit(IS_CMM_ABSENT, &dev->flags)) |
976 | return -ENODEV; | 976 | return -ENODEV; |
977 | 977 | ||
@@ -1083,7 +1083,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf, | |||
1083 | size_t count, loff_t *ppos) | 1083 | size_t count, loff_t *ppos) |
1084 | { | 1084 | { |
1085 | struct cm4000_dev *dev = (struct cm4000_dev *) filp->private_data; | 1085 | struct cm4000_dev *dev = (struct cm4000_dev *) filp->private_data; |
1086 | ioaddr_t iobase = dev->link.io.BasePort1; | 1086 | ioaddr_t iobase = dev->p_dev->io.BasePort1; |
1087 | unsigned short s; | 1087 | unsigned short s; |
1088 | unsigned char tmp; | 1088 | unsigned char tmp; |
1089 | unsigned char infolen; | 1089 | unsigned char infolen; |
@@ -1108,7 +1108,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf, | |||
1108 | 1108 | ||
1109 | sendT0 = dev->proto ? 0 : nr > 5 ? 0x08 : 0; | 1109 | sendT0 = dev->proto ? 0 : nr > 5 ? 0x08 : 0; |
1110 | 1110 | ||
1111 | if ((dev->link.state & DEV_PRESENT) == 0 || /* socket removed */ | 1111 | if (!pcmcia_dev_present(dev->p_dev) || /* device removed */ |
1112 | test_bit(IS_CMM_ABSENT, &dev->flags)) | 1112 | test_bit(IS_CMM_ABSENT, &dev->flags)) |
1113 | return -ENODEV; | 1113 | return -ENODEV; |
1114 | 1114 | ||
@@ -1440,8 +1440,8 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
1440 | unsigned long arg) | 1440 | unsigned long arg) |
1441 | { | 1441 | { |
1442 | struct cm4000_dev *dev = filp->private_data; | 1442 | struct cm4000_dev *dev = filp->private_data; |
1443 | ioaddr_t iobase = dev->link.io.BasePort1; | 1443 | ioaddr_t iobase = dev->p_dev->io.BasePort1; |
1444 | dev_link_t *link; | 1444 | struct pcmcia_device *link; |
1445 | int size; | 1445 | int size; |
1446 | int rc; | 1446 | int rc; |
1447 | void __user *argp = (void __user *)arg; | 1447 | void __user *argp = (void __user *)arg; |
@@ -1458,7 +1458,7 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
1458 | iminor(inode), ioctl_names[_IOC_NR(cmd)]); | 1458 | iminor(inode), ioctl_names[_IOC_NR(cmd)]); |
1459 | 1459 | ||
1460 | link = dev_table[iminor(inode)]; | 1460 | link = dev_table[iminor(inode)]; |
1461 | if (!(DEV_OK(link))) { | 1461 | if (!pcmcia_dev_present(link)) { |
1462 | DEBUGP(4, dev, "DEV_OK false\n"); | 1462 | DEBUGP(4, dev, "DEV_OK false\n"); |
1463 | return -ENODEV; | 1463 | return -ENODEV; |
1464 | } | 1464 | } |
@@ -1660,14 +1660,14 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
1660 | static int cmm_open(struct inode *inode, struct file *filp) | 1660 | static int cmm_open(struct inode *inode, struct file *filp) |
1661 | { | 1661 | { |
1662 | struct cm4000_dev *dev; | 1662 | struct cm4000_dev *dev; |
1663 | dev_link_t *link; | 1663 | struct pcmcia_device *link; |
1664 | int rc, minor = iminor(inode); | 1664 | int rc, minor = iminor(inode); |
1665 | 1665 | ||
1666 | if (minor >= CM4000_MAX_DEV) | 1666 | if (minor >= CM4000_MAX_DEV) |
1667 | return -ENODEV; | 1667 | return -ENODEV; |
1668 | 1668 | ||
1669 | link = dev_table[minor]; | 1669 | link = dev_table[minor]; |
1670 | if (link == NULL || !(DEV_OK(link))) | 1670 | if (link == NULL || !pcmcia_dev_present(link)) |
1671 | return -ENODEV; | 1671 | return -ENODEV; |
1672 | 1672 | ||
1673 | if (link->open) | 1673 | if (link->open) |
@@ -1709,7 +1709,7 @@ static int cmm_open(struct inode *inode, struct file *filp) | |||
1709 | static int cmm_close(struct inode *inode, struct file *filp) | 1709 | static int cmm_close(struct inode *inode, struct file *filp) |
1710 | { | 1710 | { |
1711 | struct cm4000_dev *dev; | 1711 | struct cm4000_dev *dev; |
1712 | dev_link_t *link; | 1712 | struct pcmcia_device *link; |
1713 | int minor = iminor(inode); | 1713 | int minor = iminor(inode); |
1714 | 1714 | ||
1715 | if (minor >= CM4000_MAX_DEV) | 1715 | if (minor >= CM4000_MAX_DEV) |
@@ -1735,7 +1735,7 @@ static int cmm_close(struct inode *inode, struct file *filp) | |||
1735 | return 0; | 1735 | return 0; |
1736 | } | 1736 | } |
1737 | 1737 | ||
1738 | static void cmm_cm4000_release(dev_link_t * link) | 1738 | static void cmm_cm4000_release(struct pcmcia_device * link) |
1739 | { | 1739 | { |
1740 | struct cm4000_dev *dev = link->priv; | 1740 | struct cm4000_dev *dev = link->priv; |
1741 | 1741 | ||
@@ -1759,13 +1759,11 @@ static void cmm_cm4000_release(dev_link_t * link) | |||
1759 | 1759 | ||
1760 | /*==== Interface to PCMCIA Layer =======================================*/ | 1760 | /*==== Interface to PCMCIA Layer =======================================*/ |
1761 | 1761 | ||
1762 | static void cm4000_config(dev_link_t * link, int devno) | 1762 | static int cm4000_config(struct pcmcia_device * link, int devno) |
1763 | { | 1763 | { |
1764 | client_handle_t handle = link->handle; | ||
1765 | struct cm4000_dev *dev; | 1764 | struct cm4000_dev *dev; |
1766 | tuple_t tuple; | 1765 | tuple_t tuple; |
1767 | cisparse_t parse; | 1766 | cisparse_t parse; |
1768 | config_info_t conf; | ||
1769 | u_char buf[64]; | 1767 | u_char buf[64]; |
1770 | int fail_fn, fail_rc; | 1768 | int fail_fn, fail_rc; |
1771 | int rc; | 1769 | int rc; |
@@ -1777,41 +1775,34 @@ static void cm4000_config(dev_link_t * link, int devno) | |||
1777 | tuple.TupleDataMax = sizeof(buf); | 1775 | tuple.TupleDataMax = sizeof(buf); |
1778 | tuple.TupleOffset = 0; | 1776 | tuple.TupleOffset = 0; |
1779 | 1777 | ||
1780 | if ((fail_rc = pcmcia_get_first_tuple(handle, &tuple)) != CS_SUCCESS) { | 1778 | if ((fail_rc = pcmcia_get_first_tuple(link, &tuple)) != CS_SUCCESS) { |
1781 | fail_fn = GetFirstTuple; | 1779 | fail_fn = GetFirstTuple; |
1782 | goto cs_failed; | 1780 | goto cs_failed; |
1783 | } | 1781 | } |
1784 | if ((fail_rc = pcmcia_get_tuple_data(handle, &tuple)) != CS_SUCCESS) { | 1782 | if ((fail_rc = pcmcia_get_tuple_data(link, &tuple)) != CS_SUCCESS) { |
1785 | fail_fn = GetTupleData; | 1783 | fail_fn = GetTupleData; |
1786 | goto cs_failed; | 1784 | goto cs_failed; |
1787 | } | 1785 | } |
1788 | if ((fail_rc = | 1786 | if ((fail_rc = |
1789 | pcmcia_parse_tuple(handle, &tuple, &parse)) != CS_SUCCESS) { | 1787 | pcmcia_parse_tuple(link, &tuple, &parse)) != CS_SUCCESS) { |
1790 | fail_fn = ParseTuple; | 1788 | fail_fn = ParseTuple; |
1791 | goto cs_failed; | 1789 | goto cs_failed; |
1792 | } | 1790 | } |
1793 | if ((fail_rc = | ||
1794 | pcmcia_get_configuration_info(handle, &conf)) != CS_SUCCESS) { | ||
1795 | fail_fn = GetConfigurationInfo; | ||
1796 | goto cs_failed; | ||
1797 | } | ||
1798 | 1791 | ||
1799 | link->state |= DEV_CONFIG; | ||
1800 | link->conf.ConfigBase = parse.config.base; | 1792 | link->conf.ConfigBase = parse.config.base; |
1801 | link->conf.Present = parse.config.rmask[0]; | 1793 | link->conf.Present = parse.config.rmask[0]; |
1802 | link->conf.Vcc = conf.Vcc; | ||
1803 | 1794 | ||
1804 | link->io.BasePort2 = 0; | 1795 | link->io.BasePort2 = 0; |
1805 | link->io.NumPorts2 = 0; | 1796 | link->io.NumPorts2 = 0; |
1806 | link->io.Attributes2 = 0; | 1797 | link->io.Attributes2 = 0; |
1807 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 1798 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
1808 | for (rc = pcmcia_get_first_tuple(handle, &tuple); | 1799 | for (rc = pcmcia_get_first_tuple(link, &tuple); |
1809 | rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(handle, &tuple)) { | 1800 | rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(link, &tuple)) { |
1810 | 1801 | ||
1811 | rc = pcmcia_get_tuple_data(handle, &tuple); | 1802 | rc = pcmcia_get_tuple_data(link, &tuple); |
1812 | if (rc != CS_SUCCESS) | 1803 | if (rc != CS_SUCCESS) |
1813 | continue; | 1804 | continue; |
1814 | rc = pcmcia_parse_tuple(handle, &tuple, &parse); | 1805 | rc = pcmcia_parse_tuple(link, &tuple, &parse); |
1815 | if (rc != CS_SUCCESS) | 1806 | if (rc != CS_SUCCESS) |
1816 | continue; | 1807 | continue; |
1817 | 1808 | ||
@@ -1831,7 +1822,7 @@ static void cm4000_config(dev_link_t * link, int devno) | |||
1831 | link->io.IOAddrLines = parse.cftable_entry.io.flags | 1822 | link->io.IOAddrLines = parse.cftable_entry.io.flags |
1832 | & CISTPL_IO_LINES_MASK; | 1823 | & CISTPL_IO_LINES_MASK; |
1833 | 1824 | ||
1834 | rc = pcmcia_request_io(handle, &link->io); | 1825 | rc = pcmcia_request_io(link, &link->io); |
1835 | if (rc == CS_SUCCESS) | 1826 | if (rc == CS_SUCCESS) |
1836 | break; /* we are done */ | 1827 | break; /* we are done */ |
1837 | } | 1828 | } |
@@ -1841,7 +1832,7 @@ static void cm4000_config(dev_link_t * link, int devno) | |||
1841 | link->conf.IntType = 00000002; | 1832 | link->conf.IntType = 00000002; |
1842 | 1833 | ||
1843 | if ((fail_rc = | 1834 | if ((fail_rc = |
1844 | pcmcia_request_configuration(handle, &link->conf)) != CS_SUCCESS) { | 1835 | pcmcia_request_configuration(link, &link->conf)) != CS_SUCCESS) { |
1845 | fail_fn = RequestConfiguration; | 1836 | fail_fn = RequestConfiguration; |
1846 | goto cs_release; | 1837 | goto cs_release; |
1847 | } | 1838 | } |
@@ -1851,63 +1842,48 @@ static void cm4000_config(dev_link_t * link, int devno) | |||
1851 | dev->node.major = major; | 1842 | dev->node.major = major; |
1852 | dev->node.minor = devno; | 1843 | dev->node.minor = devno; |
1853 | dev->node.next = NULL; | 1844 | dev->node.next = NULL; |
1854 | link->dev = &dev->node; | 1845 | link->dev_node = &dev->node; |
1855 | link->state &= ~DEV_CONFIG_PENDING; | ||
1856 | 1846 | ||
1857 | return; | 1847 | return 0; |
1858 | 1848 | ||
1859 | cs_failed: | 1849 | cs_failed: |
1860 | cs_error(handle, fail_fn, fail_rc); | 1850 | cs_error(link, fail_fn, fail_rc); |
1861 | cs_release: | 1851 | cs_release: |
1862 | cm4000_release(link); | 1852 | cm4000_release(link); |
1863 | 1853 | return -ENODEV; | |
1864 | link->state &= ~DEV_CONFIG_PENDING; | ||
1865 | } | 1854 | } |
1866 | 1855 | ||
1867 | static int cm4000_suspend(struct pcmcia_device *p_dev) | 1856 | static int cm4000_suspend(struct pcmcia_device *link) |
1868 | { | 1857 | { |
1869 | dev_link_t *link = dev_to_instance(p_dev); | ||
1870 | struct cm4000_dev *dev; | 1858 | struct cm4000_dev *dev; |
1871 | 1859 | ||
1872 | dev = link->priv; | 1860 | dev = link->priv; |
1873 | |||
1874 | link->state |= DEV_SUSPEND; | ||
1875 | if (link->state & DEV_CONFIG) | ||
1876 | pcmcia_release_configuration(link->handle); | ||
1877 | stop_monitor(dev); | 1861 | stop_monitor(dev); |
1878 | 1862 | ||
1879 | return 0; | 1863 | return 0; |
1880 | } | 1864 | } |
1881 | 1865 | ||
1882 | static int cm4000_resume(struct pcmcia_device *p_dev) | 1866 | static int cm4000_resume(struct pcmcia_device *link) |
1883 | { | 1867 | { |
1884 | dev_link_t *link = dev_to_instance(p_dev); | ||
1885 | struct cm4000_dev *dev; | 1868 | struct cm4000_dev *dev; |
1886 | 1869 | ||
1887 | dev = link->priv; | 1870 | dev = link->priv; |
1888 | |||
1889 | link->state &= ~DEV_SUSPEND; | ||
1890 | if (link->state & DEV_CONFIG) | ||
1891 | pcmcia_request_configuration(link->handle, &link->conf); | ||
1892 | |||
1893 | if (link->open) | 1871 | if (link->open) |
1894 | start_monitor(dev); | 1872 | start_monitor(dev); |
1895 | 1873 | ||
1896 | return 0; | 1874 | return 0; |
1897 | } | 1875 | } |
1898 | 1876 | ||
1899 | static void cm4000_release(dev_link_t *link) | 1877 | static void cm4000_release(struct pcmcia_device *link) |
1900 | { | 1878 | { |
1901 | cmm_cm4000_release(link->priv); /* delay release until device closed */ | 1879 | cmm_cm4000_release(link->priv); /* delay release until device closed */ |
1902 | pcmcia_release_configuration(link->handle); | 1880 | pcmcia_disable_device(link); |
1903 | pcmcia_release_io(link->handle, &link->io); | ||
1904 | } | 1881 | } |
1905 | 1882 | ||
1906 | static int cm4000_attach(struct pcmcia_device *p_dev) | 1883 | static int cm4000_probe(struct pcmcia_device *link) |
1907 | { | 1884 | { |
1908 | struct cm4000_dev *dev; | 1885 | struct cm4000_dev *dev; |
1909 | dev_link_t *link; | 1886 | int i, ret; |
1910 | int i; | ||
1911 | 1887 | ||
1912 | for (i = 0; i < CM4000_MAX_DEV; i++) | 1888 | for (i = 0; i < CM4000_MAX_DEV; i++) |
1913 | if (dev_table[i] == NULL) | 1889 | if (dev_table[i] == NULL) |
@@ -1923,7 +1899,7 @@ static int cm4000_attach(struct pcmcia_device *p_dev) | |||
1923 | if (dev == NULL) | 1899 | if (dev == NULL) |
1924 | return -ENOMEM; | 1900 | return -ENOMEM; |
1925 | 1901 | ||
1926 | link = &dev->link; | 1902 | dev->p_dev = link; |
1927 | link->priv = dev; | 1903 | link->priv = dev; |
1928 | link->conf.IntType = INT_MEMORY_AND_IO; | 1904 | link->conf.IntType = INT_MEMORY_AND_IO; |
1929 | dev_table[i] = link; | 1905 | dev_table[i] = link; |
@@ -1933,11 +1909,9 @@ static int cm4000_attach(struct pcmcia_device *p_dev) | |||
1933 | init_waitqueue_head(&dev->atrq); | 1909 | init_waitqueue_head(&dev->atrq); |
1934 | init_waitqueue_head(&dev->readq); | 1910 | init_waitqueue_head(&dev->readq); |
1935 | 1911 | ||
1936 | link->handle = p_dev; | 1912 | ret = cm4000_config(link, i); |
1937 | p_dev->instance = link; | 1913 | if (ret) |
1938 | 1914 | return ret; | |
1939 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
1940 | cm4000_config(link, i); | ||
1941 | 1915 | ||
1942 | class_device_create(cmm_class, NULL, MKDEV(major, i), NULL, | 1916 | class_device_create(cmm_class, NULL, MKDEV(major, i), NULL, |
1943 | "cmm%d", i); | 1917 | "cmm%d", i); |
@@ -1945,9 +1919,8 @@ static int cm4000_attach(struct pcmcia_device *p_dev) | |||
1945 | return 0; | 1919 | return 0; |
1946 | } | 1920 | } |
1947 | 1921 | ||
1948 | static void cm4000_detach(struct pcmcia_device *p_dev) | 1922 | static void cm4000_detach(struct pcmcia_device *link) |
1949 | { | 1923 | { |
1950 | dev_link_t *link = dev_to_instance(p_dev); | ||
1951 | struct cm4000_dev *dev = link->priv; | 1924 | struct cm4000_dev *dev = link->priv; |
1952 | int devno; | 1925 | int devno; |
1953 | 1926 | ||
@@ -1958,11 +1931,9 @@ static void cm4000_detach(struct pcmcia_device *p_dev) | |||
1958 | if (devno == CM4000_MAX_DEV) | 1931 | if (devno == CM4000_MAX_DEV) |
1959 | return; | 1932 | return; |
1960 | 1933 | ||
1961 | link->state &= ~DEV_PRESENT; | ||
1962 | stop_monitor(dev); | 1934 | stop_monitor(dev); |
1963 | 1935 | ||
1964 | if (link->state & DEV_CONFIG) | 1936 | cm4000_release(link); |
1965 | cm4000_release(link); | ||
1966 | 1937 | ||
1967 | dev_table[devno] = NULL; | 1938 | dev_table[devno] = NULL; |
1968 | kfree(dev); | 1939 | kfree(dev); |
@@ -1993,7 +1964,7 @@ static struct pcmcia_driver cm4000_driver = { | |||
1993 | .drv = { | 1964 | .drv = { |
1994 | .name = "cm4000_cs", | 1965 | .name = "cm4000_cs", |
1995 | }, | 1966 | }, |
1996 | .probe = cm4000_attach, | 1967 | .probe = cm4000_probe, |
1997 | .remove = cm4000_detach, | 1968 | .remove = cm4000_detach, |
1998 | .suspend = cm4000_suspend, | 1969 | .suspend = cm4000_suspend, |
1999 | .resume = cm4000_resume, | 1970 | .resume = cm4000_resume, |
@@ -2010,10 +1981,6 @@ static int __init cmm_init(void) | |||
2010 | if (!cmm_class) | 1981 | if (!cmm_class) |
2011 | return -1; | 1982 | return -1; |
2012 | 1983 | ||
2013 | rc = pcmcia_register_driver(&cm4000_driver); | ||
2014 | if (rc < 0) | ||
2015 | return rc; | ||
2016 | |||
2017 | major = register_chrdev(0, DEVICE_NAME, &cm4000_fops); | 1984 | major = register_chrdev(0, DEVICE_NAME, &cm4000_fops); |
2018 | if (major < 0) { | 1985 | if (major < 0) { |
2019 | printk(KERN_WARNING MODULE_NAME | 1986 | printk(KERN_WARNING MODULE_NAME |
@@ -2021,6 +1988,12 @@ static int __init cmm_init(void) | |||
2021 | return -1; | 1988 | return -1; |
2022 | } | 1989 | } |
2023 | 1990 | ||
1991 | rc = pcmcia_register_driver(&cm4000_driver); | ||
1992 | if (rc < 0) { | ||
1993 | unregister_chrdev(major, DEVICE_NAME); | ||
1994 | return rc; | ||
1995 | } | ||
1996 | |||
2024 | return 0; | 1997 | return 0; |
2025 | } | 1998 | } |
2026 | 1999 | ||
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 466e33bab029..47a8465bf95b 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c | |||
@@ -41,7 +41,7 @@ | |||
41 | 41 | ||
42 | 42 | ||
43 | #ifdef PCMCIA_DEBUG | 43 | #ifdef PCMCIA_DEBUG |
44 | #define reader_to_dev(x) (&handle_to_dev(x->link.handle)) | 44 | #define reader_to_dev(x) (&handle_to_dev(x->p_dev->handle)) |
45 | static int pc_debug = PCMCIA_DEBUG; | 45 | static int pc_debug = PCMCIA_DEBUG; |
46 | module_param(pc_debug, int, 0600); | 46 | module_param(pc_debug, int, 0600); |
47 | #define DEBUGP(n, rdr, x, args...) do { \ | 47 | #define DEBUGP(n, rdr, x, args...) do { \ |
@@ -65,7 +65,7 @@ static char *version = | |||
65 | /* how often to poll for fifo status change */ | 65 | /* how often to poll for fifo status change */ |
66 | #define POLL_PERIOD msecs_to_jiffies(10) | 66 | #define POLL_PERIOD msecs_to_jiffies(10) |
67 | 67 | ||
68 | static void reader_release(dev_link_t *link); | 68 | static void reader_release(struct pcmcia_device *link); |
69 | 69 | ||
70 | static int major; | 70 | static int major; |
71 | static struct class *cmx_class; | 71 | static struct class *cmx_class; |
@@ -74,7 +74,7 @@ static struct class *cmx_class; | |||
74 | #define BS_WRITABLE 0x02 | 74 | #define BS_WRITABLE 0x02 |
75 | 75 | ||
76 | struct reader_dev { | 76 | struct reader_dev { |
77 | dev_link_t link; | 77 | struct pcmcia_device *p_dev; |
78 | dev_node_t node; | 78 | dev_node_t node; |
79 | wait_queue_head_t devq; | 79 | wait_queue_head_t devq; |
80 | wait_queue_head_t poll_wait; | 80 | wait_queue_head_t poll_wait; |
@@ -87,7 +87,7 @@ struct reader_dev { | |||
87 | struct timer_list poll_timer; | 87 | struct timer_list poll_timer; |
88 | }; | 88 | }; |
89 | 89 | ||
90 | static dev_link_t *dev_table[CM_MAX_DEV]; | 90 | static struct pcmcia_device *dev_table[CM_MAX_DEV]; |
91 | 91 | ||
92 | #ifndef PCMCIA_DEBUG | 92 | #ifndef PCMCIA_DEBUG |
93 | #define xoutb outb | 93 | #define xoutb outb |
@@ -116,7 +116,7 @@ static inline unsigned char xinb(unsigned short port) | |||
116 | static void cm4040_do_poll(unsigned long dummy) | 116 | static void cm4040_do_poll(unsigned long dummy) |
117 | { | 117 | { |
118 | struct reader_dev *dev = (struct reader_dev *) dummy; | 118 | struct reader_dev *dev = (struct reader_dev *) dummy; |
119 | unsigned int obs = xinb(dev->link.io.BasePort1 | 119 | unsigned int obs = xinb(dev->p_dev->io.BasePort1 |
120 | + REG_OFFSET_BUFFER_STATUS); | 120 | + REG_OFFSET_BUFFER_STATUS); |
121 | 121 | ||
122 | if ((obs & BSR_BULK_IN_FULL)) { | 122 | if ((obs & BSR_BULK_IN_FULL)) { |
@@ -147,7 +147,7 @@ static void cm4040_stop_poll(struct reader_dev *dev) | |||
147 | static int wait_for_bulk_out_ready(struct reader_dev *dev) | 147 | static int wait_for_bulk_out_ready(struct reader_dev *dev) |
148 | { | 148 | { |
149 | int i, rc; | 149 | int i, rc; |
150 | int iobase = dev->link.io.BasePort1; | 150 | int iobase = dev->p_dev->io.BasePort1; |
151 | 151 | ||
152 | for (i = 0; i < POLL_LOOP_COUNT; i++) { | 152 | for (i = 0; i < POLL_LOOP_COUNT; i++) { |
153 | if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS) | 153 | if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS) |
@@ -177,7 +177,7 @@ static int wait_for_bulk_out_ready(struct reader_dev *dev) | |||
177 | /* Write to Sync Control Register */ | 177 | /* Write to Sync Control Register */ |
178 | static int write_sync_reg(unsigned char val, struct reader_dev *dev) | 178 | static int write_sync_reg(unsigned char val, struct reader_dev *dev) |
179 | { | 179 | { |
180 | int iobase = dev->link.io.BasePort1; | 180 | int iobase = dev->p_dev->io.BasePort1; |
181 | int rc; | 181 | int rc; |
182 | 182 | ||
183 | rc = wait_for_bulk_out_ready(dev); | 183 | rc = wait_for_bulk_out_ready(dev); |
@@ -195,7 +195,7 @@ static int write_sync_reg(unsigned char val, struct reader_dev *dev) | |||
195 | static int wait_for_bulk_in_ready(struct reader_dev *dev) | 195 | static int wait_for_bulk_in_ready(struct reader_dev *dev) |
196 | { | 196 | { |
197 | int i, rc; | 197 | int i, rc; |
198 | int iobase = dev->link.io.BasePort1; | 198 | int iobase = dev->p_dev->io.BasePort1; |
199 | 199 | ||
200 | for (i = 0; i < POLL_LOOP_COUNT; i++) { | 200 | for (i = 0; i < POLL_LOOP_COUNT; i++) { |
201 | if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS) | 201 | if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS) |
@@ -225,7 +225,7 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf, | |||
225 | size_t count, loff_t *ppos) | 225 | size_t count, loff_t *ppos) |
226 | { | 226 | { |
227 | struct reader_dev *dev = filp->private_data; | 227 | struct reader_dev *dev = filp->private_data; |
228 | int iobase = dev->link.io.BasePort1; | 228 | int iobase = dev->p_dev->io.BasePort1; |
229 | size_t bytes_to_read; | 229 | size_t bytes_to_read; |
230 | unsigned long i; | 230 | unsigned long i; |
231 | size_t min_bytes_to_read; | 231 | size_t min_bytes_to_read; |
@@ -246,7 +246,7 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf, | |||
246 | return -EAGAIN; | 246 | return -EAGAIN; |
247 | } | 247 | } |
248 | 248 | ||
249 | if ((dev->link.state & DEV_PRESENT)==0) | 249 | if (!pcmcia_dev_present(dev->p_dev)) |
250 | return -ENODEV; | 250 | return -ENODEV; |
251 | 251 | ||
252 | for (i = 0; i < 5; i++) { | 252 | for (i = 0; i < 5; i++) { |
@@ -328,7 +328,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf, | |||
328 | size_t count, loff_t *ppos) | 328 | size_t count, loff_t *ppos) |
329 | { | 329 | { |
330 | struct reader_dev *dev = filp->private_data; | 330 | struct reader_dev *dev = filp->private_data; |
331 | int iobase = dev->link.io.BasePort1; | 331 | int iobase = dev->p_dev->io.BasePort1; |
332 | ssize_t rc; | 332 | ssize_t rc; |
333 | int i; | 333 | int i; |
334 | unsigned int bytes_to_write; | 334 | unsigned int bytes_to_write; |
@@ -351,7 +351,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf, | |||
351 | return -EAGAIN; | 351 | return -EAGAIN; |
352 | } | 352 | } |
353 | 353 | ||
354 | if ((dev->link.state & DEV_PRESENT) == 0) | 354 | if (!pcmcia_dev_present(dev->p_dev)) |
355 | return -ENODEV; | 355 | return -ENODEV; |
356 | 356 | ||
357 | bytes_to_write = count; | 357 | bytes_to_write = count; |
@@ -445,14 +445,14 @@ static unsigned int cm4040_poll(struct file *filp, poll_table *wait) | |||
445 | static int cm4040_open(struct inode *inode, struct file *filp) | 445 | static int cm4040_open(struct inode *inode, struct file *filp) |
446 | { | 446 | { |
447 | struct reader_dev *dev; | 447 | struct reader_dev *dev; |
448 | dev_link_t *link; | 448 | struct pcmcia_device *link; |
449 | int minor = iminor(inode); | 449 | int minor = iminor(inode); |
450 | 450 | ||
451 | if (minor >= CM_MAX_DEV) | 451 | if (minor >= CM_MAX_DEV) |
452 | return -ENODEV; | 452 | return -ENODEV; |
453 | 453 | ||
454 | link = dev_table[minor]; | 454 | link = dev_table[minor]; |
455 | if (link == NULL || !(DEV_OK(link))) | 455 | if (link == NULL || !pcmcia_dev_present(link)) |
456 | return -ENODEV; | 456 | return -ENODEV; |
457 | 457 | ||
458 | if (link->open) | 458 | if (link->open) |
@@ -478,7 +478,7 @@ static int cm4040_open(struct inode *inode, struct file *filp) | |||
478 | static int cm4040_close(struct inode *inode, struct file *filp) | 478 | static int cm4040_close(struct inode *inode, struct file *filp) |
479 | { | 479 | { |
480 | struct reader_dev *dev = filp->private_data; | 480 | struct reader_dev *dev = filp->private_data; |
481 | dev_link_t *link; | 481 | struct pcmcia_device *link; |
482 | int minor = iminor(inode); | 482 | int minor = iminor(inode); |
483 | 483 | ||
484 | DEBUGP(2, dev, "-> cm4040_close(maj/min=%d.%d)\n", imajor(inode), | 484 | DEBUGP(2, dev, "-> cm4040_close(maj/min=%d.%d)\n", imajor(inode), |
@@ -500,7 +500,7 @@ static int cm4040_close(struct inode *inode, struct file *filp) | |||
500 | return 0; | 500 | return 0; |
501 | } | 501 | } |
502 | 502 | ||
503 | static void cm4040_reader_release(dev_link_t *link) | 503 | static void cm4040_reader_release(struct pcmcia_device *link) |
504 | { | 504 | { |
505 | struct reader_dev *dev = link->priv; | 505 | struct reader_dev *dev = link->priv; |
506 | 506 | ||
@@ -514,60 +514,49 @@ static void cm4040_reader_release(dev_link_t *link) | |||
514 | return; | 514 | return; |
515 | } | 515 | } |
516 | 516 | ||
517 | static void reader_config(dev_link_t *link, int devno) | 517 | static int reader_config(struct pcmcia_device *link, int devno) |
518 | { | 518 | { |
519 | client_handle_t handle; | ||
520 | struct reader_dev *dev; | 519 | struct reader_dev *dev; |
521 | tuple_t tuple; | 520 | tuple_t tuple; |
522 | cisparse_t parse; | 521 | cisparse_t parse; |
523 | config_info_t conf; | ||
524 | u_char buf[64]; | 522 | u_char buf[64]; |
525 | int fail_fn, fail_rc; | 523 | int fail_fn, fail_rc; |
526 | int rc; | 524 | int rc; |
527 | 525 | ||
528 | handle = link->handle; | ||
529 | |||
530 | tuple.DesiredTuple = CISTPL_CONFIG; | 526 | tuple.DesiredTuple = CISTPL_CONFIG; |
531 | tuple.Attributes = 0; | 527 | tuple.Attributes = 0; |
532 | tuple.TupleData = buf; | 528 | tuple.TupleData = buf; |
533 | tuple.TupleDataMax = sizeof(buf); | 529 | tuple.TupleDataMax = sizeof(buf); |
534 | tuple.TupleOffset = 0; | 530 | tuple.TupleOffset = 0; |
535 | 531 | ||
536 | if ((fail_rc = pcmcia_get_first_tuple(handle, &tuple)) != CS_SUCCESS) { | 532 | if ((fail_rc = pcmcia_get_first_tuple(link, &tuple)) != CS_SUCCESS) { |
537 | fail_fn = GetFirstTuple; | 533 | fail_fn = GetFirstTuple; |
538 | goto cs_failed; | 534 | goto cs_failed; |
539 | } | 535 | } |
540 | if ((fail_rc = pcmcia_get_tuple_data(handle, &tuple)) != CS_SUCCESS) { | 536 | if ((fail_rc = pcmcia_get_tuple_data(link, &tuple)) != CS_SUCCESS) { |
541 | fail_fn = GetTupleData; | 537 | fail_fn = GetTupleData; |
542 | goto cs_failed; | 538 | goto cs_failed; |
543 | } | 539 | } |
544 | if ((fail_rc = pcmcia_parse_tuple(handle, &tuple, &parse)) | 540 | if ((fail_rc = pcmcia_parse_tuple(link, &tuple, &parse)) |
545 | != CS_SUCCESS) { | 541 | != CS_SUCCESS) { |
546 | fail_fn = ParseTuple; | 542 | fail_fn = ParseTuple; |
547 | goto cs_failed; | 543 | goto cs_failed; |
548 | } | 544 | } |
549 | if ((fail_rc = pcmcia_get_configuration_info(handle, &conf)) | ||
550 | != CS_SUCCESS) { | ||
551 | fail_fn = GetConfigurationInfo; | ||
552 | goto cs_failed; | ||
553 | } | ||
554 | 545 | ||
555 | link->state |= DEV_CONFIG; | ||
556 | link->conf.ConfigBase = parse.config.base; | 546 | link->conf.ConfigBase = parse.config.base; |
557 | link->conf.Present = parse.config.rmask[0]; | 547 | link->conf.Present = parse.config.rmask[0]; |
558 | link->conf.Vcc = conf.Vcc; | ||
559 | 548 | ||
560 | link->io.BasePort2 = 0; | 549 | link->io.BasePort2 = 0; |
561 | link->io.NumPorts2 = 0; | 550 | link->io.NumPorts2 = 0; |
562 | link->io.Attributes2 = 0; | 551 | link->io.Attributes2 = 0; |
563 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 552 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
564 | for (rc = pcmcia_get_first_tuple(handle, &tuple); | 553 | for (rc = pcmcia_get_first_tuple(link, &tuple); |
565 | rc == CS_SUCCESS; | 554 | rc == CS_SUCCESS; |
566 | rc = pcmcia_get_next_tuple(handle, &tuple)) { | 555 | rc = pcmcia_get_next_tuple(link, &tuple)) { |
567 | rc = pcmcia_get_tuple_data(handle, &tuple); | 556 | rc = pcmcia_get_tuple_data(link, &tuple); |
568 | if (rc != CS_SUCCESS) | 557 | if (rc != CS_SUCCESS) |
569 | continue; | 558 | continue; |
570 | rc = pcmcia_parse_tuple(handle, &tuple, &parse); | 559 | rc = pcmcia_parse_tuple(link, &tuple, &parse); |
571 | if (rc != CS_SUCCESS) | 560 | if (rc != CS_SUCCESS) |
572 | continue; | 561 | continue; |
573 | 562 | ||
@@ -585,13 +574,13 @@ static void reader_config(dev_link_t *link, int devno) | |||
585 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | 574 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; |
586 | link->io.IOAddrLines = parse.cftable_entry.io.flags | 575 | link->io.IOAddrLines = parse.cftable_entry.io.flags |
587 | & CISTPL_IO_LINES_MASK; | 576 | & CISTPL_IO_LINES_MASK; |
588 | rc = pcmcia_request_io(handle, &link->io); | 577 | rc = pcmcia_request_io(link, &link->io); |
589 | 578 | ||
590 | dev_printk(KERN_INFO, &handle_to_dev(handle), "foo"); | 579 | dev_printk(KERN_INFO, &handle_to_dev(link), "foo"); |
591 | if (rc == CS_SUCCESS) | 580 | if (rc == CS_SUCCESS) |
592 | break; | 581 | break; |
593 | else | 582 | else |
594 | dev_printk(KERN_INFO, &handle_to_dev(handle), | 583 | dev_printk(KERN_INFO, &handle_to_dev(link), |
595 | "pcmcia_request_io failed 0x%x\n", rc); | 584 | "pcmcia_request_io failed 0x%x\n", rc); |
596 | } | 585 | } |
597 | if (rc != CS_SUCCESS) | 586 | if (rc != CS_SUCCESS) |
@@ -599,10 +588,10 @@ static void reader_config(dev_link_t *link, int devno) | |||
599 | 588 | ||
600 | link->conf.IntType = 00000002; | 589 | link->conf.IntType = 00000002; |
601 | 590 | ||
602 | if ((fail_rc = pcmcia_request_configuration(handle,&link->conf)) | 591 | if ((fail_rc = pcmcia_request_configuration(link,&link->conf)) |
603 | !=CS_SUCCESS) { | 592 | !=CS_SUCCESS) { |
604 | fail_fn = RequestConfiguration; | 593 | fail_fn = RequestConfiguration; |
605 | dev_printk(KERN_INFO, &handle_to_dev(handle), | 594 | dev_printk(KERN_INFO, &handle_to_dev(link), |
606 | "pcmcia_request_configuration failed 0x%x\n", | 595 | "pcmcia_request_configuration failed 0x%x\n", |
607 | fail_rc); | 596 | fail_rc); |
608 | goto cs_release; | 597 | goto cs_release; |
@@ -612,57 +601,31 @@ static void reader_config(dev_link_t *link, int devno) | |||
612 | sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno); | 601 | sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno); |
613 | dev->node.major = major; | 602 | dev->node.major = major; |
614 | dev->node.minor = devno; | 603 | dev->node.minor = devno; |
615 | dev->node.next = NULL; | 604 | dev->node.next = &dev->node; |
616 | link->dev = &dev->node; | ||
617 | link->state &= ~DEV_CONFIG_PENDING; | ||
618 | 605 | ||
619 | DEBUGP(2, dev, "device " DEVICE_NAME "%d at 0x%.4x-0x%.4x\n", devno, | 606 | DEBUGP(2, dev, "device " DEVICE_NAME "%d at 0x%.4x-0x%.4x\n", devno, |
620 | link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1); | 607 | link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1); |
621 | DEBUGP(2, dev, "<- reader_config (succ)\n"); | 608 | DEBUGP(2, dev, "<- reader_config (succ)\n"); |
622 | 609 | ||
623 | return; | 610 | return 0; |
624 | 611 | ||
625 | cs_failed: | 612 | cs_failed: |
626 | cs_error(handle, fail_fn, fail_rc); | 613 | cs_error(link, fail_fn, fail_rc); |
627 | cs_release: | 614 | cs_release: |
628 | reader_release(link); | 615 | reader_release(link); |
629 | link->state &= ~DEV_CONFIG_PENDING; | 616 | return -ENODEV; |
630 | } | ||
631 | |||
632 | static int reader_suspend(struct pcmcia_device *p_dev) | ||
633 | { | ||
634 | dev_link_t *link = dev_to_instance(p_dev); | ||
635 | |||
636 | link->state |= DEV_SUSPEND; | ||
637 | if (link->state & DEV_CONFIG) | ||
638 | pcmcia_release_configuration(link->handle); | ||
639 | |||
640 | return 0; | ||
641 | } | ||
642 | |||
643 | static int reader_resume(struct pcmcia_device *p_dev) | ||
644 | { | ||
645 | dev_link_t *link = dev_to_instance(p_dev); | ||
646 | |||
647 | link->state &= ~DEV_SUSPEND; | ||
648 | if (link->state & DEV_CONFIG) | ||
649 | pcmcia_request_configuration(link->handle, &link->conf); | ||
650 | |||
651 | return 0; | ||
652 | } | 617 | } |
653 | 618 | ||
654 | static void reader_release(dev_link_t *link) | 619 | static void reader_release(struct pcmcia_device *link) |
655 | { | 620 | { |
656 | cm4040_reader_release(link->priv); | 621 | cm4040_reader_release(link->priv); |
657 | pcmcia_release_configuration(link->handle); | 622 | pcmcia_disable_device(link); |
658 | pcmcia_release_io(link->handle, &link->io); | ||
659 | } | 623 | } |
660 | 624 | ||
661 | static int reader_attach(struct pcmcia_device *p_dev) | 625 | static int reader_probe(struct pcmcia_device *link) |
662 | { | 626 | { |
663 | struct reader_dev *dev; | 627 | struct reader_dev *dev; |
664 | dev_link_t *link; | 628 | int i, ret; |
665 | int i; | ||
666 | 629 | ||
667 | for (i = 0; i < CM_MAX_DEV; i++) { | 630 | for (i = 0; i < CM_MAX_DEV; i++) { |
668 | if (dev_table[i] == NULL) | 631 | if (dev_table[i] == NULL) |
@@ -679,8 +642,8 @@ static int reader_attach(struct pcmcia_device *p_dev) | |||
679 | dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT; | 642 | dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT; |
680 | dev->buffer_status = 0; | 643 | dev->buffer_status = 0; |
681 | 644 | ||
682 | link = &dev->link; | ||
683 | link->priv = dev; | 645 | link->priv = dev; |
646 | dev->p_dev = link; | ||
684 | 647 | ||
685 | link->conf.IntType = INT_MEMORY_AND_IO; | 648 | link->conf.IntType = INT_MEMORY_AND_IO; |
686 | dev_table[i] = link; | 649 | dev_table[i] = link; |
@@ -692,11 +655,9 @@ static int reader_attach(struct pcmcia_device *p_dev) | |||
692 | init_timer(&dev->poll_timer); | 655 | init_timer(&dev->poll_timer); |
693 | dev->poll_timer.function = &cm4040_do_poll; | 656 | dev->poll_timer.function = &cm4040_do_poll; |
694 | 657 | ||
695 | link->handle = p_dev; | 658 | ret = reader_config(link, i); |
696 | p_dev->instance = link; | 659 | if (ret) |
697 | 660 | return ret; | |
698 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
699 | reader_config(link, i); | ||
700 | 661 | ||
701 | class_device_create(cmx_class, NULL, MKDEV(major, i), NULL, | 662 | class_device_create(cmx_class, NULL, MKDEV(major, i), NULL, |
702 | "cmx%d", i); | 663 | "cmx%d", i); |
@@ -704,9 +665,8 @@ static int reader_attach(struct pcmcia_device *p_dev) | |||
704 | return 0; | 665 | return 0; |
705 | } | 666 | } |
706 | 667 | ||
707 | static void reader_detach(struct pcmcia_device *p_dev) | 668 | static void reader_detach(struct pcmcia_device *link) |
708 | { | 669 | { |
709 | dev_link_t *link = dev_to_instance(p_dev); | ||
710 | struct reader_dev *dev = link->priv; | 670 | struct reader_dev *dev = link->priv; |
711 | int devno; | 671 | int devno; |
712 | 672 | ||
@@ -718,10 +678,7 @@ static void reader_detach(struct pcmcia_device *p_dev) | |||
718 | if (devno == CM_MAX_DEV) | 678 | if (devno == CM_MAX_DEV) |
719 | return; | 679 | return; |
720 | 680 | ||
721 | link->state &= ~DEV_PRESENT; | 681 | reader_release(link); |
722 | |||
723 | if (link->state & DEV_CONFIG) | ||
724 | reader_release(link); | ||
725 | 682 | ||
726 | dev_table[devno] = NULL; | 683 | dev_table[devno] = NULL; |
727 | kfree(dev); | 684 | kfree(dev); |
@@ -753,10 +710,8 @@ static struct pcmcia_driver reader_driver = { | |||
753 | .drv = { | 710 | .drv = { |
754 | .name = "cm4040_cs", | 711 | .name = "cm4040_cs", |
755 | }, | 712 | }, |
756 | .probe = reader_attach, | 713 | .probe = reader_probe, |
757 | .remove = reader_detach, | 714 | .remove = reader_detach, |
758 | .suspend = reader_suspend, | ||
759 | .resume = reader_resume, | ||
760 | .id_table = cm4040_ids, | 715 | .id_table = cm4040_ids, |
761 | }; | 716 | }; |
762 | 717 | ||
@@ -769,16 +724,19 @@ static int __init cm4040_init(void) | |||
769 | if (!cmx_class) | 724 | if (!cmx_class) |
770 | return -1; | 725 | return -1; |
771 | 726 | ||
772 | rc = pcmcia_register_driver(&reader_driver); | ||
773 | if (rc < 0) | ||
774 | return rc; | ||
775 | |||
776 | major = register_chrdev(0, DEVICE_NAME, &reader_fops); | 727 | major = register_chrdev(0, DEVICE_NAME, &reader_fops); |
777 | if (major < 0) { | 728 | if (major < 0) { |
778 | printk(KERN_WARNING MODULE_NAME | 729 | printk(KERN_WARNING MODULE_NAME |
779 | ": could not get major number\n"); | 730 | ": could not get major number\n"); |
780 | return -1; | 731 | return -1; |
781 | } | 732 | } |
733 | |||
734 | rc = pcmcia_register_driver(&reader_driver); | ||
735 | if (rc < 0) { | ||
736 | unregister_chrdev(major, DEVICE_NAME); | ||
737 | return rc; | ||
738 | } | ||
739 | |||
782 | return 0; | 740 | return 0; |
783 | } | 741 | } |
784 | 742 | ||
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index e6b714b6390d..07213454c458 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -228,7 +228,7 @@ typedef struct _mgslpc_info { | |||
228 | struct _input_signal_events input_signal_events; | 228 | struct _input_signal_events input_signal_events; |
229 | 229 | ||
230 | /* PCMCIA support */ | 230 | /* PCMCIA support */ |
231 | dev_link_t link; | 231 | struct pcmcia_device *p_dev; |
232 | dev_node_t node; | 232 | dev_node_t node; |
233 | int stop; | 233 | int stop; |
234 | 234 | ||
@@ -484,7 +484,7 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout); | |||
484 | 484 | ||
485 | /* PCMCIA prototypes */ | 485 | /* PCMCIA prototypes */ |
486 | 486 | ||
487 | static void mgslpc_config(dev_link_t *link); | 487 | static int mgslpc_config(struct pcmcia_device *link); |
488 | static void mgslpc_release(u_long arg); | 488 | static void mgslpc_release(u_long arg); |
489 | static void mgslpc_detach(struct pcmcia_device *p_dev); | 489 | static void mgslpc_detach(struct pcmcia_device *p_dev); |
490 | 490 | ||
@@ -533,14 +533,14 @@ static void ldisc_receive_buf(struct tty_struct *tty, | |||
533 | } | 533 | } |
534 | } | 534 | } |
535 | 535 | ||
536 | static int mgslpc_attach(struct pcmcia_device *p_dev) | 536 | static int mgslpc_probe(struct pcmcia_device *link) |
537 | { | 537 | { |
538 | MGSLPC_INFO *info; | 538 | MGSLPC_INFO *info; |
539 | dev_link_t *link; | 539 | int ret; |
540 | 540 | ||
541 | if (debug_level >= DEBUG_LEVEL_INFO) | 541 | if (debug_level >= DEBUG_LEVEL_INFO) |
542 | printk("mgslpc_attach\n"); | 542 | printk("mgslpc_attach\n"); |
543 | 543 | ||
544 | info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL); | 544 | info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL); |
545 | if (!info) { | 545 | if (!info) { |
546 | printk("Error can't allocate device instance data\n"); | 546 | printk("Error can't allocate device instance data\n"); |
@@ -565,25 +565,22 @@ static int mgslpc_attach(struct pcmcia_device *p_dev) | |||
565 | info->imrb_value = 0xffff; | 565 | info->imrb_value = 0xffff; |
566 | info->pim_value = 0xff; | 566 | info->pim_value = 0xff; |
567 | 567 | ||
568 | link = &info->link; | 568 | info->p_dev = link; |
569 | link->priv = info; | 569 | link->priv = info; |
570 | 570 | ||
571 | /* Initialize the dev_link_t structure */ | 571 | /* Initialize the struct pcmcia_device structure */ |
572 | 572 | ||
573 | /* Interrupt setup */ | 573 | /* Interrupt setup */ |
574 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 574 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; |
575 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 575 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; |
576 | link->irq.Handler = NULL; | 576 | link->irq.Handler = NULL; |
577 | 577 | ||
578 | link->conf.Attributes = 0; | 578 | link->conf.Attributes = 0; |
579 | link->conf.Vcc = 50; | ||
580 | link->conf.IntType = INT_MEMORY_AND_IO; | 579 | link->conf.IntType = INT_MEMORY_AND_IO; |
581 | 580 | ||
582 | link->handle = p_dev; | 581 | ret = mgslpc_config(link); |
583 | p_dev->instance = link; | 582 | if (ret) |
584 | 583 | return ret; | |
585 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
586 | mgslpc_config(link); | ||
587 | 584 | ||
588 | mgslpc_add_device(info); | 585 | mgslpc_add_device(info); |
589 | 586 | ||
@@ -596,15 +593,13 @@ static int mgslpc_attach(struct pcmcia_device *p_dev) | |||
596 | #define CS_CHECK(fn, ret) \ | 593 | #define CS_CHECK(fn, ret) \ |
597 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 594 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
598 | 595 | ||
599 | static void mgslpc_config(dev_link_t *link) | 596 | static int mgslpc_config(struct pcmcia_device *link) |
600 | { | 597 | { |
601 | client_handle_t handle = link->handle; | ||
602 | MGSLPC_INFO *info = link->priv; | 598 | MGSLPC_INFO *info = link->priv; |
603 | tuple_t tuple; | 599 | tuple_t tuple; |
604 | cisparse_t parse; | 600 | cisparse_t parse; |
605 | int last_fn, last_ret; | 601 | int last_fn, last_ret; |
606 | u_char buf[64]; | 602 | u_char buf[64]; |
607 | config_info_t conf; | ||
608 | cistpl_cftable_entry_t dflt = { 0 }; | 603 | cistpl_cftable_entry_t dflt = { 0 }; |
609 | cistpl_cftable_entry_t *cfg; | 604 | cistpl_cftable_entry_t *cfg; |
610 | 605 | ||
@@ -617,27 +612,20 @@ static void mgslpc_config(dev_link_t *link) | |||
617 | tuple.TupleData = buf; | 612 | tuple.TupleData = buf; |
618 | tuple.TupleDataMax = sizeof(buf); | 613 | tuple.TupleDataMax = sizeof(buf); |
619 | tuple.TupleOffset = 0; | 614 | tuple.TupleOffset = 0; |
620 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 615 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
621 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 616 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
622 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 617 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
623 | link->conf.ConfigBase = parse.config.base; | 618 | link->conf.ConfigBase = parse.config.base; |
624 | link->conf.Present = parse.config.rmask[0]; | 619 | link->conf.Present = parse.config.rmask[0]; |
625 | |||
626 | /* Configure card */ | ||
627 | link->state |= DEV_CONFIG; | ||
628 | |||
629 | /* Look up the current Vcc */ | ||
630 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); | ||
631 | link->conf.Vcc = conf.Vcc; | ||
632 | 620 | ||
633 | /* get CIS configuration entry */ | 621 | /* get CIS configuration entry */ |
634 | 622 | ||
635 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 623 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
636 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 624 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
637 | 625 | ||
638 | cfg = &(parse.cftable_entry); | 626 | cfg = &(parse.cftable_entry); |
639 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 627 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
640 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 628 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
641 | 629 | ||
642 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; | 630 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; |
643 | if (cfg->index == 0) | 631 | if (cfg->index == 0) |
@@ -658,11 +646,10 @@ static void mgslpc_config(dev_link_t *link) | |||
658 | link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; | 646 | link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; |
659 | link->io.BasePort1 = io->win[0].base; | 647 | link->io.BasePort1 = io->win[0].base; |
660 | link->io.NumPorts1 = io->win[0].len; | 648 | link->io.NumPorts1 = io->win[0].len; |
661 | CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io)); | 649 | CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); |
662 | } | 650 | } |
663 | 651 | ||
664 | link->conf.Attributes = CONF_ENABLE_IRQ; | 652 | link->conf.Attributes = CONF_ENABLE_IRQ; |
665 | link->conf.Vcc = 50; | ||
666 | link->conf.IntType = INT_MEMORY_AND_IO; | 653 | link->conf.IntType = INT_MEMORY_AND_IO; |
667 | link->conf.ConfigIndex = 8; | 654 | link->conf.ConfigIndex = 8; |
668 | link->conf.Present = PRESENT_OPTION; | 655 | link->conf.Present = PRESENT_OPTION; |
@@ -670,9 +657,9 @@ static void mgslpc_config(dev_link_t *link) | |||
670 | link->irq.Attributes |= IRQ_HANDLE_PRESENT; | 657 | link->irq.Attributes |= IRQ_HANDLE_PRESENT; |
671 | link->irq.Handler = mgslpc_isr; | 658 | link->irq.Handler = mgslpc_isr; |
672 | link->irq.Instance = info; | 659 | link->irq.Instance = info; |
673 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | 660 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
674 | 661 | ||
675 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | 662 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
676 | 663 | ||
677 | info->io_base = link->io.BasePort1; | 664 | info->io_base = link->io.BasePort1; |
678 | info->irq_level = link->irq.AssignedIRQ; | 665 | info->irq_level = link->irq.AssignedIRQ; |
@@ -680,7 +667,7 @@ static void mgslpc_config(dev_link_t *link) | |||
680 | /* add to linked list of devices */ | 667 | /* add to linked list of devices */ |
681 | sprintf(info->node.dev_name, "mgslpc0"); | 668 | sprintf(info->node.dev_name, "mgslpc0"); |
682 | info->node.major = info->node.minor = 0; | 669 | info->node.major = info->node.minor = 0; |
683 | link->dev = &info->node; | 670 | link->dev_node = &info->node; |
684 | 671 | ||
685 | printk(KERN_INFO "%s: index 0x%02x:", | 672 | printk(KERN_INFO "%s: index 0x%02x:", |
686 | info->node.dev_name, link->conf.ConfigIndex); | 673 | info->node.dev_name, link->conf.ConfigIndex); |
@@ -690,13 +677,12 @@ static void mgslpc_config(dev_link_t *link) | |||
690 | printk(", io 0x%04x-0x%04x", link->io.BasePort1, | 677 | printk(", io 0x%04x-0x%04x", link->io.BasePort1, |
691 | link->io.BasePort1+link->io.NumPorts1-1); | 678 | link->io.BasePort1+link->io.NumPorts1-1); |
692 | printk("\n"); | 679 | printk("\n"); |
693 | 680 | return 0; | |
694 | link->state &= ~DEV_CONFIG_PENDING; | ||
695 | return; | ||
696 | 681 | ||
697 | cs_failed: | 682 | cs_failed: |
698 | cs_error(link->handle, last_fn, last_ret); | 683 | cs_error(link, last_fn, last_ret); |
699 | mgslpc_release((u_long)link); | 684 | mgslpc_release((u_long)link); |
685 | return -ENODEV; | ||
700 | } | 686 | } |
701 | 687 | ||
702 | /* Card has been removed. | 688 | /* Card has been removed. |
@@ -705,58 +691,38 @@ cs_failed: | |||
705 | */ | 691 | */ |
706 | static void mgslpc_release(u_long arg) | 692 | static void mgslpc_release(u_long arg) |
707 | { | 693 | { |
708 | dev_link_t *link = (dev_link_t *)arg; | 694 | struct pcmcia_device *link = (struct pcmcia_device *)arg; |
709 | 695 | ||
710 | if (debug_level >= DEBUG_LEVEL_INFO) | 696 | if (debug_level >= DEBUG_LEVEL_INFO) |
711 | printk("mgslpc_release(0x%p)\n", link); | 697 | printk("mgslpc_release(0x%p)\n", link); |
712 | |||
713 | /* Unlink the device chain */ | ||
714 | link->dev = NULL; | ||
715 | link->state &= ~DEV_CONFIG; | ||
716 | 698 | ||
717 | pcmcia_release_configuration(link->handle); | 699 | pcmcia_disable_device(link); |
718 | if (link->io.NumPorts1) | ||
719 | pcmcia_release_io(link->handle, &link->io); | ||
720 | if (link->irq.AssignedIRQ) | ||
721 | pcmcia_release_irq(link->handle, &link->irq); | ||
722 | } | 700 | } |
723 | 701 | ||
724 | static void mgslpc_detach(struct pcmcia_device *p_dev) | 702 | static void mgslpc_detach(struct pcmcia_device *link) |
725 | { | 703 | { |
726 | dev_link_t *link = dev_to_instance(p_dev); | 704 | if (debug_level >= DEBUG_LEVEL_INFO) |
727 | 705 | printk("mgslpc_detach(0x%p)\n", link); | |
728 | if (debug_level >= DEBUG_LEVEL_INFO) | ||
729 | printk("mgslpc_detach(0x%p)\n", link); | ||
730 | 706 | ||
731 | if (link->state & DEV_CONFIG) { | 707 | ((MGSLPC_INFO *)link->priv)->stop = 1; |
732 | ((MGSLPC_INFO *)link->priv)->stop = 1; | 708 | mgslpc_release((u_long)link); |
733 | mgslpc_release((u_long)link); | ||
734 | } | ||
735 | 709 | ||
736 | mgslpc_remove_device((MGSLPC_INFO *)link->priv); | 710 | mgslpc_remove_device((MGSLPC_INFO *)link->priv); |
737 | } | 711 | } |
738 | 712 | ||
739 | static int mgslpc_suspend(struct pcmcia_device *dev) | 713 | static int mgslpc_suspend(struct pcmcia_device *link) |
740 | { | 714 | { |
741 | dev_link_t *link = dev_to_instance(dev); | ||
742 | MGSLPC_INFO *info = link->priv; | 715 | MGSLPC_INFO *info = link->priv; |
743 | 716 | ||
744 | link->state |= DEV_SUSPEND; | ||
745 | info->stop = 1; | 717 | info->stop = 1; |
746 | if (link->state & DEV_CONFIG) | ||
747 | pcmcia_release_configuration(link->handle); | ||
748 | 718 | ||
749 | return 0; | 719 | return 0; |
750 | } | 720 | } |
751 | 721 | ||
752 | static int mgslpc_resume(struct pcmcia_device *dev) | 722 | static int mgslpc_resume(struct pcmcia_device *link) |
753 | { | 723 | { |
754 | dev_link_t *link = dev_to_instance(dev); | ||
755 | MGSLPC_INFO *info = link->priv; | 724 | MGSLPC_INFO *info = link->priv; |
756 | 725 | ||
757 | link->state &= ~DEV_SUSPEND; | ||
758 | if (link->state & DEV_CONFIG) | ||
759 | pcmcia_request_configuration(link->handle, &link->conf); | ||
760 | info->stop = 0; | 726 | info->stop = 0; |
761 | 727 | ||
762 | return 0; | 728 | return 0; |
@@ -1280,7 +1246,7 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id, struct pt_regs * regs) | |||
1280 | if (!info) | 1246 | if (!info) |
1281 | return IRQ_NONE; | 1247 | return IRQ_NONE; |
1282 | 1248 | ||
1283 | if (!(info->link.state & DEV_CONFIG)) | 1249 | if (!(info->p_dev->_locked)) |
1284 | return IRQ_HANDLED; | 1250 | return IRQ_HANDLED; |
1285 | 1251 | ||
1286 | spin_lock(&info->lock); | 1252 | spin_lock(&info->lock); |
@@ -3033,7 +2999,7 @@ static struct pcmcia_driver mgslpc_driver = { | |||
3033 | .drv = { | 2999 | .drv = { |
3034 | .name = "synclink_cs", | 3000 | .name = "synclink_cs", |
3035 | }, | 3001 | }, |
3036 | .probe = mgslpc_attach, | 3002 | .probe = mgslpc_probe, |
3037 | .remove = mgslpc_detach, | 3003 | .remove = mgslpc_detach, |
3038 | .id_table = mgslpc_ids, | 3004 | .id_table = mgslpc_ids, |
3039 | .suspend = mgslpc_suspend, | 3005 | .suspend = mgslpc_suspend, |
diff --git a/drivers/char/random.c b/drivers/char/random.c index 86be04b241e1..58f3512c52e1 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -1584,7 +1584,6 @@ u32 secure_ipv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dpo | |||
1584 | 1584 | ||
1585 | return twothirdsMD4Transform(daddr, hash); | 1585 | return twothirdsMD4Transform(daddr, hash); |
1586 | } | 1586 | } |
1587 | EXPORT_SYMBOL(secure_ipv6_port_ephemeral); | ||
1588 | #endif | 1587 | #endif |
1589 | 1588 | ||
1590 | #if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE) | 1589 | #if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE) |
diff --git a/drivers/char/rio/host.h b/drivers/char/rio/host.h index 3ec73d1a279a..179cdbea712b 100644 --- a/drivers/char/rio/host.h +++ b/drivers/char/rio/host.h | |||
@@ -33,12 +33,6 @@ | |||
33 | #ifndef __rio_host_h__ | 33 | #ifndef __rio_host_h__ |
34 | #define __rio_host_h__ | 34 | #define __rio_host_h__ |
35 | 35 | ||
36 | #ifdef SCCS_LABELS | ||
37 | #ifndef lint | ||
38 | static char *_host_h_sccs_ = "@(#)host.h 1.2"; | ||
39 | #endif | ||
40 | #endif | ||
41 | |||
42 | /* | 36 | /* |
43 | ** the host structure - one per host card in the system. | 37 | ** the host structure - one per host card in the system. |
44 | */ | 38 | */ |
@@ -77,9 +71,6 @@ struct Host { | |||
77 | #define RC_STARTUP 1 | 71 | #define RC_STARTUP 1 |
78 | #define RC_RUNNING 2 | 72 | #define RC_RUNNING 2 |
79 | #define RC_STUFFED 3 | 73 | #define RC_STUFFED 3 |
80 | #define RC_SOMETHING 4 | ||
81 | #define RC_SOMETHING_NEW 5 | ||
82 | #define RC_SOMETHING_ELSE 6 | ||
83 | #define RC_READY 7 | 74 | #define RC_READY 7 |
84 | #define RUN_STATE 7 | 75 | #define RUN_STATE 7 |
85 | /* | 76 | /* |
diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c index acda9326c2ef..290143addd34 100644 --- a/drivers/char/rio/rioboot.c +++ b/drivers/char/rio/rioboot.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | #include <linux/termios.h> | 35 | #include <linux/termios.h> |
36 | #include <linux/serial.h> | 36 | #include <linux/serial.h> |
37 | #include <linux/vmalloc.h> | ||
37 | #include <asm/semaphore.h> | 38 | #include <asm/semaphore.h> |
38 | #include <linux/generic_serial.h> | 39 | #include <linux/generic_serial.h> |
39 | #include <linux/errno.h> | 40 | #include <linux/errno.h> |
diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c index d31aba62bb7f..75b2557c37ec 100644 --- a/drivers/char/rio/rioctrl.c +++ b/drivers/char/rio/rioctrl.c | |||
@@ -1394,14 +1394,17 @@ int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd) | |||
1394 | return RIO_FAIL; | 1394 | return RIO_FAIL; |
1395 | } | 1395 | } |
1396 | 1396 | ||
1397 | if (((int) ((char) PortP->InUse) == -1) || !(CmdBlkP = RIOGetCmdBlk())) { | 1397 | if ((PortP->InUse == (typeof(PortP->InUse))-1) || |
1398 | rio_dprintk(RIO_DEBUG_CTRL, "Cannot allocate command block for command %d on port %d\n", Cmd, PortP->PortNum); | 1398 | !(CmdBlkP = RIOGetCmdBlk())) { |
1399 | rio_dprintk(RIO_DEBUG_CTRL, "Cannot allocate command block " | ||
1400 | "for command %d on port %d\n", Cmd, PortP->PortNum); | ||
1399 | return RIO_FAIL; | 1401 | return RIO_FAIL; |
1400 | } | 1402 | } |
1401 | 1403 | ||
1402 | rio_dprintk(RIO_DEBUG_CTRL, "Command blk %p - InUse now %d\n", CmdBlkP, PortP->InUse); | 1404 | rio_dprintk(RIO_DEBUG_CTRL, "Command blk %p - InUse now %d\n", |
1405 | CmdBlkP, PortP->InUse); | ||
1403 | 1406 | ||
1404 | PktCmdP = (struct PktCmd_M *) &CmdBlkP->Packet.data[0]; | 1407 | PktCmdP = (struct PktCmd_M *)&CmdBlkP->Packet.data[0]; |
1405 | 1408 | ||
1406 | CmdBlkP->Packet.src_unit = 0; | 1409 | CmdBlkP->Packet.src_unit = 0; |
1407 | if (PortP->SecondBlock) | 1410 | if (PortP->SecondBlock) |
@@ -1425,38 +1428,46 @@ int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd) | |||
1425 | 1428 | ||
1426 | switch (Cmd) { | 1429 | switch (Cmd) { |
1427 | case MEMDUMP: | 1430 | case MEMDUMP: |
1428 | rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk %p (addr 0x%x)\n", CmdBlkP, (int) SubCmd.Addr); | 1431 | rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk %p " |
1432 | "(addr 0x%x)\n", CmdBlkP, (int) SubCmd.Addr); | ||
1429 | PktCmdP->SubCommand = MEMDUMP; | 1433 | PktCmdP->SubCommand = MEMDUMP; |
1430 | PktCmdP->SubAddr = SubCmd.Addr; | 1434 | PktCmdP->SubAddr = SubCmd.Addr; |
1431 | break; | 1435 | break; |
1432 | case FCLOSE: | 1436 | case FCLOSE: |
1433 | rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk %p\n", CmdBlkP); | 1437 | rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk %p\n", |
1438 | CmdBlkP); | ||
1434 | break; | 1439 | break; |
1435 | case READ_REGISTER: | 1440 | case READ_REGISTER: |
1436 | rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) command blk %p\n", (int) SubCmd.Addr, CmdBlkP); | 1441 | rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) " |
1442 | "command blk %p\n", (int) SubCmd.Addr, CmdBlkP); | ||
1437 | PktCmdP->SubCommand = READ_REGISTER; | 1443 | PktCmdP->SubCommand = READ_REGISTER; |
1438 | PktCmdP->SubAddr = SubCmd.Addr; | 1444 | PktCmdP->SubAddr = SubCmd.Addr; |
1439 | break; | 1445 | break; |
1440 | case RESUME: | 1446 | case RESUME: |
1441 | rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk %p\n", CmdBlkP); | 1447 | rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk %p\n", |
1448 | CmdBlkP); | ||
1442 | break; | 1449 | break; |
1443 | case RFLUSH: | 1450 | case RFLUSH: |
1444 | rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk %p\n", CmdBlkP); | 1451 | rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk %p\n", |
1452 | CmdBlkP); | ||
1445 | CmdBlkP->PostFuncP = RIORFlushEnable; | 1453 | CmdBlkP->PostFuncP = RIORFlushEnable; |
1446 | break; | 1454 | break; |
1447 | case SUSPEND: | 1455 | case SUSPEND: |
1448 | rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk %p\n", CmdBlkP); | 1456 | rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk %p\n", |
1457 | CmdBlkP); | ||
1449 | break; | 1458 | break; |
1450 | 1459 | ||
1451 | case MGET: | 1460 | case MGET: |
1452 | rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk %p\n", CmdBlkP); | 1461 | rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk %p\n", |
1462 | CmdBlkP); | ||
1453 | break; | 1463 | break; |
1454 | 1464 | ||
1455 | case MSET: | 1465 | case MSET: |
1456 | case MBIC: | 1466 | case MBIC: |
1457 | case MBIS: | 1467 | case MBIS: |
1458 | CmdBlkP->Packet.data[4] = (char) PortP->ModemLines; | 1468 | CmdBlkP->Packet.data[4] = (char) PortP->ModemLines; |
1459 | rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command blk %p\n", CmdBlkP); | 1469 | rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command " |
1470 | "blk %p\n", CmdBlkP); | ||
1460 | break; | 1471 | break; |
1461 | 1472 | ||
1462 | case WFLUSH: | 1473 | case WFLUSH: |
@@ -1465,12 +1476,14 @@ int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd) | |||
1465 | ** allowed then we should not bother sending any more to the | 1476 | ** allowed then we should not bother sending any more to the |
1466 | ** RTA. | 1477 | ** RTA. |
1467 | */ | 1478 | */ |
1468 | if ((int) ((char) PortP->WflushFlag) == (int) -1) { | 1479 | if (PortP->WflushFlag == (typeof(PortP->WflushFlag))-1) { |
1469 | rio_dprintk(RIO_DEBUG_CTRL, "Trashed WFLUSH, WflushFlag about to wrap!"); | 1480 | rio_dprintk(RIO_DEBUG_CTRL, "Trashed WFLUSH, " |
1481 | "WflushFlag about to wrap!"); | ||
1470 | RIOFreeCmdBlk(CmdBlkP); | 1482 | RIOFreeCmdBlk(CmdBlkP); |
1471 | return (RIO_FAIL); | 1483 | return (RIO_FAIL); |
1472 | } else { | 1484 | } else { |
1473 | rio_dprintk(RIO_DEBUG_CTRL, "Queue WFLUSH command blk %p\n", CmdBlkP); | 1485 | rio_dprintk(RIO_DEBUG_CTRL, "Queue WFLUSH command " |
1486 | "blk %p\n", CmdBlkP); | ||
1474 | CmdBlkP->PostFuncP = RIOWFlushMark; | 1487 | CmdBlkP->PostFuncP = RIOWFlushMark; |
1475 | } | 1488 | } |
1476 | break; | 1489 | break; |
diff --git a/drivers/char/rio/rioioctl.h b/drivers/char/rio/rioioctl.h index 14b83fae75c8..e8af5b30519e 100644 --- a/drivers/char/rio/rioioctl.h +++ b/drivers/char/rio/rioioctl.h | |||
@@ -33,10 +33,6 @@ | |||
33 | #ifndef __rioioctl_h__ | 33 | #ifndef __rioioctl_h__ |
34 | #define __rioioctl_h__ | 34 | #define __rioioctl_h__ |
35 | 35 | ||
36 | #ifdef SCCS_LABELS | ||
37 | static char *_rioioctl_h_sccs_ = "@(#)rioioctl.h 1.2"; | ||
38 | #endif | ||
39 | |||
40 | /* | 36 | /* |
41 | ** RIO device driver - user ioctls and associated structures. | 37 | ** RIO device driver - user ioctls and associated structures. |
42 | */ | 38 | */ |
@@ -44,55 +40,13 @@ static char *_rioioctl_h_sccs_ = "@(#)rioioctl.h 1.2"; | |||
44 | struct portStats { | 40 | struct portStats { |
45 | int port; | 41 | int port; |
46 | int gather; | 42 | int gather; |
47 | ulong txchars; | 43 | unsigned long txchars; |
48 | ulong rxchars; | 44 | unsigned long rxchars; |
49 | ulong opens; | 45 | unsigned long opens; |
50 | ulong closes; | 46 | unsigned long closes; |
51 | ulong ioctls; | 47 | unsigned long ioctls; |
52 | }; | 48 | }; |
53 | 49 | ||
54 | |||
55 | #define rIOC ('r'<<8) | ||
56 | #define TCRIOSTATE (rIOC | 1) | ||
57 | #define TCRIOXPON (rIOC | 2) | ||
58 | #define TCRIOXPOFF (rIOC | 3) | ||
59 | #define TCRIOXPCPS (rIOC | 4) | ||
60 | #define TCRIOXPRINT (rIOC | 5) | ||
61 | #define TCRIOIXANYON (rIOC | 6) | ||
62 | #define TCRIOIXANYOFF (rIOC | 7) | ||
63 | #define TCRIOIXONON (rIOC | 8) | ||
64 | #define TCRIOIXONOFF (rIOC | 9) | ||
65 | #define TCRIOMBIS (rIOC | 10) | ||
66 | #define TCRIOMBIC (rIOC | 11) | ||
67 | #define TCRIOTRIAD (rIOC | 12) | ||
68 | #define TCRIOTSTATE (rIOC | 13) | ||
69 | |||
70 | /* | ||
71 | ** 15.10.1998 ARG - ESIL 0761 part fix | ||
72 | ** Add RIO ioctls for manipulating RTS and CTS flow control, (as LynxOS | ||
73 | ** appears to not support hardware flow control). | ||
74 | */ | ||
75 | #define TCRIOCTSFLOWEN (rIOC | 14) /* enable CTS flow control */ | ||
76 | #define TCRIOCTSFLOWDIS (rIOC | 15) /* disable CTS flow control */ | ||
77 | #define TCRIORTSFLOWEN (rIOC | 16) /* enable RTS flow control */ | ||
78 | #define TCRIORTSFLOWDIS (rIOC | 17) /* disable RTS flow control */ | ||
79 | |||
80 | /* | ||
81 | ** 09.12.1998 ARG - ESIL 0776 part fix | ||
82 | ** Definition for 'RIOC' also appears in daemon.h, so we'd better do a | ||
83 | ** #ifndef here first. | ||
84 | ** 'RIO_QUICK_CHECK' also #define'd here as this ioctl is now | ||
85 | ** allowed to be used by customers. | ||
86 | ** | ||
87 | ** 05.02.1999 ARG - | ||
88 | ** This is what I've decied to do with ioctls etc., which are intended to be | ||
89 | ** invoked from users applications : | ||
90 | ** Anything that needs to be defined here will be removed from daemon.h, that | ||
91 | ** way it won't end up having to be defined/maintained in two places. The only | ||
92 | ** consequence of this is that this file should now be #include'd by daemon.h | ||
93 | ** | ||
94 | ** 'stats' ioctls now #define'd here as they are to be used by customers. | ||
95 | */ | ||
96 | #define RIOC ('R'<<8)|('i'<<16)|('o'<<24) | 50 | #define RIOC ('R'<<8)|('i'<<16)|('o'<<24) |
97 | 51 | ||
98 | #define RIO_QUICK_CHECK (RIOC | 105) | 52 | #define RIO_QUICK_CHECK (RIOC | 105) |
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c index b543821d8cb4..56c8243cdb73 100644 --- a/drivers/char/snsc.c +++ b/drivers/char/snsc.c | |||
@@ -390,7 +390,8 @@ scdrv_init(void) | |||
390 | format_module_id(devnamep, geo_module(geoid), | 390 | format_module_id(devnamep, geo_module(geoid), |
391 | MODULE_FORMAT_BRIEF); | 391 | MODULE_FORMAT_BRIEF); |
392 | devnamep = devname + strlen(devname); | 392 | devnamep = devname + strlen(devname); |
393 | sprintf(devnamep, "#%d", geo_slab(geoid)); | 393 | sprintf(devnamep, "^%d#%d", geo_slot(geoid), |
394 | geo_slab(geoid)); | ||
394 | 395 | ||
395 | /* allocate sysctl device data */ | 396 | /* allocate sysctl device data */ |
396 | scd = kzalloc(sizeof (struct sysctl_data_s), | 397 | scd = kzalloc(sizeof (struct sysctl_data_s), |
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index f8dd8527c6aa..a90f5d97df35 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c | |||
@@ -1341,6 +1341,9 @@ static int __devinit sonypi_probe(struct platform_device *dev) | |||
1341 | else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | 1341 | else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, |
1342 | PCI_DEVICE_ID_INTEL_ICH6_1, NULL))) | 1342 | PCI_DEVICE_ID_INTEL_ICH6_1, NULL))) |
1343 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3; | 1343 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3; |
1344 | else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
1345 | PCI_DEVICE_ID_INTEL_ICH7_1, NULL))) | ||
1346 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3; | ||
1344 | else | 1347 | else |
1345 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2; | 1348 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2; |
1346 | 1349 | ||
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 3f5d6077f39c..a9c5a7230f89 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
@@ -504,7 +504,6 @@ static int stl_echmcaintr(stlbrd_t *brdp); | |||
504 | static int stl_echpciintr(stlbrd_t *brdp); | 504 | static int stl_echpciintr(stlbrd_t *brdp); |
505 | static int stl_echpci64intr(stlbrd_t *brdp); | 505 | static int stl_echpci64intr(stlbrd_t *brdp); |
506 | static void stl_offintr(void *private); | 506 | static void stl_offintr(void *private); |
507 | static void *stl_memalloc(int len); | ||
508 | static stlbrd_t *stl_allocbrd(void); | 507 | static stlbrd_t *stl_allocbrd(void); |
509 | static stlport_t *stl_getport(int brdnr, int panelnr, int portnr); | 508 | static stlport_t *stl_getport(int brdnr, int panelnr, int portnr); |
510 | 509 | ||
@@ -940,17 +939,6 @@ static int stl_parsebrd(stlconf_t *confp, char **argp) | |||
940 | /*****************************************************************************/ | 939 | /*****************************************************************************/ |
941 | 940 | ||
942 | /* | 941 | /* |
943 | * Local driver kernel memory allocation routine. | ||
944 | */ | ||
945 | |||
946 | static void *stl_memalloc(int len) | ||
947 | { | ||
948 | return (void *) kmalloc(len, GFP_KERNEL); | ||
949 | } | ||
950 | |||
951 | /*****************************************************************************/ | ||
952 | |||
953 | /* | ||
954 | * Allocate a new board structure. Fill out the basic info in it. | 942 | * Allocate a new board structure. Fill out the basic info in it. |
955 | */ | 943 | */ |
956 | 944 | ||
@@ -958,14 +946,13 @@ static stlbrd_t *stl_allocbrd(void) | |||
958 | { | 946 | { |
959 | stlbrd_t *brdp; | 947 | stlbrd_t *brdp; |
960 | 948 | ||
961 | brdp = (stlbrd_t *) stl_memalloc(sizeof(stlbrd_t)); | 949 | brdp = kzalloc(sizeof(stlbrd_t), GFP_KERNEL); |
962 | if (brdp == (stlbrd_t *) NULL) { | 950 | if (!brdp) { |
963 | printk("STALLION: failed to allocate memory (size=%d)\n", | 951 | printk("STALLION: failed to allocate memory (size=%d)\n", |
964 | sizeof(stlbrd_t)); | 952 | sizeof(stlbrd_t)); |
965 | return (stlbrd_t *) NULL; | 953 | return NULL; |
966 | } | 954 | } |
967 | 955 | ||
968 | memset(brdp, 0, sizeof(stlbrd_t)); | ||
969 | brdp->magic = STL_BOARDMAGIC; | 956 | brdp->magic = STL_BOARDMAGIC; |
970 | return brdp; | 957 | return brdp; |
971 | } | 958 | } |
@@ -1017,9 +1004,9 @@ static int stl_open(struct tty_struct *tty, struct file *filp) | |||
1017 | portp->refcount++; | 1004 | portp->refcount++; |
1018 | 1005 | ||
1019 | if ((portp->flags & ASYNC_INITIALIZED) == 0) { | 1006 | if ((portp->flags & ASYNC_INITIALIZED) == 0) { |
1020 | if (portp->tx.buf == (char *) NULL) { | 1007 | if (!portp->tx.buf) { |
1021 | portp->tx.buf = (char *) stl_memalloc(STL_TXBUFSIZE); | 1008 | portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); |
1022 | if (portp->tx.buf == (char *) NULL) | 1009 | if (!portp->tx.buf) |
1023 | return -ENOMEM; | 1010 | return -ENOMEM; |
1024 | portp->tx.head = portp->tx.buf; | 1011 | portp->tx.head = portp->tx.buf; |
1025 | portp->tx.tail = portp->tx.buf; | 1012 | portp->tx.tail = portp->tx.buf; |
@@ -2178,13 +2165,12 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp) | |||
2178 | * each ports data structures. | 2165 | * each ports data structures. |
2179 | */ | 2166 | */ |
2180 | for (i = 0; (i < panelp->nrports); i++) { | 2167 | for (i = 0; (i < panelp->nrports); i++) { |
2181 | portp = (stlport_t *) stl_memalloc(sizeof(stlport_t)); | 2168 | portp = kzalloc(sizeof(stlport_t), GFP_KERNEL); |
2182 | if (portp == (stlport_t *) NULL) { | 2169 | if (!portp) { |
2183 | printk("STALLION: failed to allocate memory " | 2170 | printk("STALLION: failed to allocate memory " |
2184 | "(size=%d)\n", sizeof(stlport_t)); | 2171 | "(size=%d)\n", sizeof(stlport_t)); |
2185 | break; | 2172 | break; |
2186 | } | 2173 | } |
2187 | memset(portp, 0, sizeof(stlport_t)); | ||
2188 | 2174 | ||
2189 | portp->magic = STL_PORTMAGIC; | 2175 | portp->magic = STL_PORTMAGIC; |
2190 | portp->portnr = i; | 2176 | portp->portnr = i; |
@@ -2315,13 +2301,12 @@ static inline int stl_initeio(stlbrd_t *brdp) | |||
2315 | * can complete the setup. | 2301 | * can complete the setup. |
2316 | */ | 2302 | */ |
2317 | 2303 | ||
2318 | panelp = (stlpanel_t *) stl_memalloc(sizeof(stlpanel_t)); | 2304 | panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL); |
2319 | if (panelp == (stlpanel_t *) NULL) { | 2305 | if (!panelp) { |
2320 | printk(KERN_WARNING "STALLION: failed to allocate memory " | 2306 | printk(KERN_WARNING "STALLION: failed to allocate memory " |
2321 | "(size=%d)\n", sizeof(stlpanel_t)); | 2307 | "(size=%d)\n", sizeof(stlpanel_t)); |
2322 | return(-ENOMEM); | 2308 | return -ENOMEM; |
2323 | } | 2309 | } |
2324 | memset(panelp, 0, sizeof(stlpanel_t)); | ||
2325 | 2310 | ||
2326 | panelp->magic = STL_PANELMAGIC; | 2311 | panelp->magic = STL_PANELMAGIC; |
2327 | panelp->brdnr = brdp->brdnr; | 2312 | panelp->brdnr = brdp->brdnr; |
@@ -2490,13 +2475,12 @@ static inline int stl_initech(stlbrd_t *brdp) | |||
2490 | status = inb(ioaddr + ECH_PNLSTATUS); | 2475 | status = inb(ioaddr + ECH_PNLSTATUS); |
2491 | if ((status & ECH_PNLIDMASK) != nxtid) | 2476 | if ((status & ECH_PNLIDMASK) != nxtid) |
2492 | break; | 2477 | break; |
2493 | panelp = (stlpanel_t *) stl_memalloc(sizeof(stlpanel_t)); | 2478 | panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL); |
2494 | if (panelp == (stlpanel_t *) NULL) { | 2479 | if (!panelp) { |
2495 | printk("STALLION: failed to allocate memory " | 2480 | printk("STALLION: failed to allocate memory " |
2496 | "(size=%d)\n", sizeof(stlpanel_t)); | 2481 | "(size=%d)\n", sizeof(stlpanel_t)); |
2497 | break; | 2482 | break; |
2498 | } | 2483 | } |
2499 | memset(panelp, 0, sizeof(stlpanel_t)); | ||
2500 | panelp->magic = STL_PANELMAGIC; | 2484 | panelp->magic = STL_PANELMAGIC; |
2501 | panelp->brdnr = brdp->brdnr; | 2485 | panelp->brdnr = brdp->brdnr; |
2502 | panelp->panelnr = panelnr; | 2486 | panelp->panelnr = panelnr; |
@@ -3074,8 +3058,8 @@ static int __init stl_init(void) | |||
3074 | /* | 3058 | /* |
3075 | * Allocate a temporary write buffer. | 3059 | * Allocate a temporary write buffer. |
3076 | */ | 3060 | */ |
3077 | stl_tmpwritebuf = (char *) stl_memalloc(STL_TXBUFSIZE); | 3061 | stl_tmpwritebuf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); |
3078 | if (stl_tmpwritebuf == (char *) NULL) | 3062 | if (!stl_tmpwritebuf) |
3079 | printk("STALLION: failed to allocate memory (size=%d)\n", | 3063 | printk("STALLION: failed to allocate memory (size=%d)\n", |
3080 | STL_TXBUFSIZE); | 3064 | STL_TXBUFSIZE); |
3081 | 3065 | ||
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c index eb2eb3e12d6a..079db5a935a1 100644 --- a/drivers/char/tipar.c +++ b/drivers/char/tipar.c | |||
@@ -515,7 +515,7 @@ tipar_init_module(void) | |||
515 | err = PTR_ERR(tipar_class); | 515 | err = PTR_ERR(tipar_class); |
516 | goto out_chrdev; | 516 | goto out_chrdev; |
517 | } | 517 | } |
518 | if (parport_register_driver(&tipar_driver) || tp_count == 0) { | 518 | if (parport_register_driver(&tipar_driver)) { |
519 | printk(KERN_ERR "tipar: unable to register with parport\n"); | 519 | printk(KERN_ERR "tipar: unable to register with parport\n"); |
520 | err = -EIO; | 520 | err = -EIO; |
521 | goto out_class; | 521 | goto out_class; |
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c index 2546637a55c0..f58ad7f68267 100644 --- a/drivers/char/tlclk.c +++ b/drivers/char/tlclk.c | |||
@@ -327,7 +327,7 @@ static ssize_t store_received_ref_clk3a(struct device *d, | |||
327 | return strnlen(buf, count); | 327 | return strnlen(buf, count); |
328 | } | 328 | } |
329 | 329 | ||
330 | static DEVICE_ATTR(received_ref_clk3a, S_IWUGO, NULL, | 330 | static DEVICE_ATTR(received_ref_clk3a, (S_IWUSR|S_IWGRP), NULL, |
331 | store_received_ref_clk3a); | 331 | store_received_ref_clk3a); |
332 | 332 | ||
333 | 333 | ||
@@ -349,7 +349,7 @@ static ssize_t store_received_ref_clk3b(struct device *d, | |||
349 | return strnlen(buf, count); | 349 | return strnlen(buf, count); |
350 | } | 350 | } |
351 | 351 | ||
352 | static DEVICE_ATTR(received_ref_clk3b, S_IWUGO, NULL, | 352 | static DEVICE_ATTR(received_ref_clk3b, (S_IWUSR|S_IWGRP), NULL, |
353 | store_received_ref_clk3b); | 353 | store_received_ref_clk3b); |
354 | 354 | ||
355 | 355 | ||
@@ -371,7 +371,7 @@ static ssize_t store_enable_clk3b_output(struct device *d, | |||
371 | return strnlen(buf, count); | 371 | return strnlen(buf, count); |
372 | } | 372 | } |
373 | 373 | ||
374 | static DEVICE_ATTR(enable_clk3b_output, S_IWUGO, NULL, | 374 | static DEVICE_ATTR(enable_clk3b_output, (S_IWUSR|S_IWGRP), NULL, |
375 | store_enable_clk3b_output); | 375 | store_enable_clk3b_output); |
376 | 376 | ||
377 | static ssize_t store_enable_clk3a_output(struct device *d, | 377 | static ssize_t store_enable_clk3a_output(struct device *d, |
@@ -392,7 +392,7 @@ static ssize_t store_enable_clk3a_output(struct device *d, | |||
392 | return strnlen(buf, count); | 392 | return strnlen(buf, count); |
393 | } | 393 | } |
394 | 394 | ||
395 | static DEVICE_ATTR(enable_clk3a_output, S_IWUGO, NULL, | 395 | static DEVICE_ATTR(enable_clk3a_output, (S_IWUSR|S_IWGRP), NULL, |
396 | store_enable_clk3a_output); | 396 | store_enable_clk3a_output); |
397 | 397 | ||
398 | static ssize_t store_enable_clkb1_output(struct device *d, | 398 | static ssize_t store_enable_clkb1_output(struct device *d, |
@@ -413,7 +413,7 @@ static ssize_t store_enable_clkb1_output(struct device *d, | |||
413 | return strnlen(buf, count); | 413 | return strnlen(buf, count); |
414 | } | 414 | } |
415 | 415 | ||
416 | static DEVICE_ATTR(enable_clkb1_output, S_IWUGO, NULL, | 416 | static DEVICE_ATTR(enable_clkb1_output, (S_IWUSR|S_IWGRP), NULL, |
417 | store_enable_clkb1_output); | 417 | store_enable_clkb1_output); |
418 | 418 | ||
419 | 419 | ||
@@ -435,7 +435,7 @@ static ssize_t store_enable_clka1_output(struct device *d, | |||
435 | return strnlen(buf, count); | 435 | return strnlen(buf, count); |
436 | } | 436 | } |
437 | 437 | ||
438 | static DEVICE_ATTR(enable_clka1_output, S_IWUGO, NULL, | 438 | static DEVICE_ATTR(enable_clka1_output, (S_IWUSR|S_IWGRP), NULL, |
439 | store_enable_clka1_output); | 439 | store_enable_clka1_output); |
440 | 440 | ||
441 | static ssize_t store_enable_clkb0_output(struct device *d, | 441 | static ssize_t store_enable_clkb0_output(struct device *d, |
@@ -456,7 +456,7 @@ static ssize_t store_enable_clkb0_output(struct device *d, | |||
456 | return strnlen(buf, count); | 456 | return strnlen(buf, count); |
457 | } | 457 | } |
458 | 458 | ||
459 | static DEVICE_ATTR(enable_clkb0_output, S_IWUGO, NULL, | 459 | static DEVICE_ATTR(enable_clkb0_output, (S_IWUSR|S_IWGRP), NULL, |
460 | store_enable_clkb0_output); | 460 | store_enable_clkb0_output); |
461 | 461 | ||
462 | static ssize_t store_enable_clka0_output(struct device *d, | 462 | static ssize_t store_enable_clka0_output(struct device *d, |
@@ -477,7 +477,7 @@ static ssize_t store_enable_clka0_output(struct device *d, | |||
477 | return strnlen(buf, count); | 477 | return strnlen(buf, count); |
478 | } | 478 | } |
479 | 479 | ||
480 | static DEVICE_ATTR(enable_clka0_output, S_IWUGO, NULL, | 480 | static DEVICE_ATTR(enable_clka0_output, (S_IWUSR|S_IWGRP), NULL, |
481 | store_enable_clka0_output); | 481 | store_enable_clka0_output); |
482 | 482 | ||
483 | static ssize_t store_select_amcb2_transmit_clock(struct device *d, | 483 | static ssize_t store_select_amcb2_transmit_clock(struct device *d, |
@@ -519,7 +519,7 @@ static ssize_t store_select_amcb2_transmit_clock(struct device *d, | |||
519 | return strnlen(buf, count); | 519 | return strnlen(buf, count); |
520 | } | 520 | } |
521 | 521 | ||
522 | static DEVICE_ATTR(select_amcb2_transmit_clock, S_IWUGO, NULL, | 522 | static DEVICE_ATTR(select_amcb2_transmit_clock, (S_IWUSR|S_IWGRP), NULL, |
523 | store_select_amcb2_transmit_clock); | 523 | store_select_amcb2_transmit_clock); |
524 | 524 | ||
525 | static ssize_t store_select_amcb1_transmit_clock(struct device *d, | 525 | static ssize_t store_select_amcb1_transmit_clock(struct device *d, |
@@ -560,7 +560,7 @@ static ssize_t store_select_amcb1_transmit_clock(struct device *d, | |||
560 | return strnlen(buf, count); | 560 | return strnlen(buf, count); |
561 | } | 561 | } |
562 | 562 | ||
563 | static DEVICE_ATTR(select_amcb1_transmit_clock, S_IWUGO, NULL, | 563 | static DEVICE_ATTR(select_amcb1_transmit_clock, (S_IWUSR|S_IWGRP), NULL, |
564 | store_select_amcb1_transmit_clock); | 564 | store_select_amcb1_transmit_clock); |
565 | 565 | ||
566 | static ssize_t store_select_redundant_clock(struct device *d, | 566 | static ssize_t store_select_redundant_clock(struct device *d, |
@@ -581,7 +581,7 @@ static ssize_t store_select_redundant_clock(struct device *d, | |||
581 | return strnlen(buf, count); | 581 | return strnlen(buf, count); |
582 | } | 582 | } |
583 | 583 | ||
584 | static DEVICE_ATTR(select_redundant_clock, S_IWUGO, NULL, | 584 | static DEVICE_ATTR(select_redundant_clock, (S_IWUSR|S_IWGRP), NULL, |
585 | store_select_redundant_clock); | 585 | store_select_redundant_clock); |
586 | 586 | ||
587 | static ssize_t store_select_ref_frequency(struct device *d, | 587 | static ssize_t store_select_ref_frequency(struct device *d, |
@@ -602,7 +602,7 @@ static ssize_t store_select_ref_frequency(struct device *d, | |||
602 | return strnlen(buf, count); | 602 | return strnlen(buf, count); |
603 | } | 603 | } |
604 | 604 | ||
605 | static DEVICE_ATTR(select_ref_frequency, S_IWUGO, NULL, | 605 | static DEVICE_ATTR(select_ref_frequency, (S_IWUSR|S_IWGRP), NULL, |
606 | store_select_ref_frequency); | 606 | store_select_ref_frequency); |
607 | 607 | ||
608 | static ssize_t store_filter_select(struct device *d, | 608 | static ssize_t store_filter_select(struct device *d, |
@@ -623,7 +623,7 @@ static ssize_t store_filter_select(struct device *d, | |||
623 | return strnlen(buf, count); | 623 | return strnlen(buf, count); |
624 | } | 624 | } |
625 | 625 | ||
626 | static DEVICE_ATTR(filter_select, S_IWUGO, NULL, store_filter_select); | 626 | static DEVICE_ATTR(filter_select, (S_IWUSR|S_IWGRP), NULL, store_filter_select); |
627 | 627 | ||
628 | static ssize_t store_hardware_switching_mode(struct device *d, | 628 | static ssize_t store_hardware_switching_mode(struct device *d, |
629 | struct device_attribute *attr, const char *buf, size_t count) | 629 | struct device_attribute *attr, const char *buf, size_t count) |
@@ -643,7 +643,7 @@ static ssize_t store_hardware_switching_mode(struct device *d, | |||
643 | return strnlen(buf, count); | 643 | return strnlen(buf, count); |
644 | } | 644 | } |
645 | 645 | ||
646 | static DEVICE_ATTR(hardware_switching_mode, S_IWUGO, NULL, | 646 | static DEVICE_ATTR(hardware_switching_mode, (S_IWUSR|S_IWGRP), NULL, |
647 | store_hardware_switching_mode); | 647 | store_hardware_switching_mode); |
648 | 648 | ||
649 | static ssize_t store_hardware_switching(struct device *d, | 649 | static ssize_t store_hardware_switching(struct device *d, |
@@ -664,7 +664,7 @@ static ssize_t store_hardware_switching(struct device *d, | |||
664 | return strnlen(buf, count); | 664 | return strnlen(buf, count); |
665 | } | 665 | } |
666 | 666 | ||
667 | static DEVICE_ATTR(hardware_switching, S_IWUGO, NULL, | 667 | static DEVICE_ATTR(hardware_switching, (S_IWUSR|S_IWGRP), NULL, |
668 | store_hardware_switching); | 668 | store_hardware_switching); |
669 | 669 | ||
670 | static ssize_t store_refalign (struct device *d, | 670 | static ssize_t store_refalign (struct device *d, |
@@ -684,7 +684,7 @@ static ssize_t store_refalign (struct device *d, | |||
684 | return strnlen(buf, count); | 684 | return strnlen(buf, count); |
685 | } | 685 | } |
686 | 686 | ||
687 | static DEVICE_ATTR(refalign, S_IWUGO, NULL, store_refalign); | 687 | static DEVICE_ATTR(refalign, (S_IWUSR|S_IWGRP), NULL, store_refalign); |
688 | 688 | ||
689 | static ssize_t store_mode_select (struct device *d, | 689 | static ssize_t store_mode_select (struct device *d, |
690 | struct device_attribute *attr, const char *buf, size_t count) | 690 | struct device_attribute *attr, const char *buf, size_t count) |
@@ -704,7 +704,7 @@ static ssize_t store_mode_select (struct device *d, | |||
704 | return strnlen(buf, count); | 704 | return strnlen(buf, count); |
705 | } | 705 | } |
706 | 706 | ||
707 | static DEVICE_ATTR(mode_select, S_IWUGO, NULL, store_mode_select); | 707 | static DEVICE_ATTR(mode_select, (S_IWUSR|S_IWGRP), NULL, store_mode_select); |
708 | 708 | ||
709 | static ssize_t store_reset (struct device *d, | 709 | static ssize_t store_reset (struct device *d, |
710 | struct device_attribute *attr, const char *buf, size_t count) | 710 | struct device_attribute *attr, const char *buf, size_t count) |
@@ -724,7 +724,7 @@ static ssize_t store_reset (struct device *d, | |||
724 | return strnlen(buf, count); | 724 | return strnlen(buf, count); |
725 | } | 725 | } |
726 | 726 | ||
727 | static DEVICE_ATTR(reset, S_IWUGO, NULL, store_reset); | 727 | static DEVICE_ATTR(reset, (S_IWUSR|S_IWGRP), NULL, store_reset); |
728 | 728 | ||
729 | static struct attribute *tlclk_sysfs_entries[] = { | 729 | static struct attribute *tlclk_sysfs_entries[] = { |
730 | &dev_attr_current_ref.attr, | 730 | &dev_attr_current_ref.attr, |
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index a6873bf89ffa..fe00c7dfb649 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig | |||
@@ -20,9 +20,18 @@ config TCG_TPM | |||
20 | Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI | 20 | Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI |
21 | and CONFIG_PNPACPI. | 21 | and CONFIG_PNPACPI. |
22 | 22 | ||
23 | config TCG_TIS | ||
24 | tristate "TPM Interface Specification 1.2 Interface" | ||
25 | depends on TCG_TPM && PNPACPI | ||
26 | ---help--- | ||
27 | If you have a TPM security chip that is compliant with the | ||
28 | TCG TIS 1.2 TPM specification say Yes and it will be accessible | ||
29 | from within Linux. To compile this driver as a module, choose | ||
30 | M here; the module will be called tpm_tis. | ||
31 | |||
23 | config TCG_NSC | 32 | config TCG_NSC |
24 | tristate "National Semiconductor TPM Interface" | 33 | tristate "National Semiconductor TPM Interface" |
25 | depends on TCG_TPM | 34 | depends on TCG_TPM && PNPACPI |
26 | ---help--- | 35 | ---help--- |
27 | If you have a TPM security chip from National Semicondutor | 36 | If you have a TPM security chip from National Semicondutor |
28 | say Yes and it will be accessible from within Linux. To | 37 | say Yes and it will be accessible from within Linux. To |
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index ba4582d160fd..ea3a1e02a824 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile | |||
@@ -5,6 +5,7 @@ obj-$(CONFIG_TCG_TPM) += tpm.o | |||
5 | ifdef CONFIG_ACPI | 5 | ifdef CONFIG_ACPI |
6 | obj-$(CONFIG_TCG_TPM) += tpm_bios.o | 6 | obj-$(CONFIG_TCG_TPM) += tpm_bios.o |
7 | endif | 7 | endif |
8 | obj-$(CONFIG_TCG_TIS) += tpm_tis.o | ||
8 | obj-$(CONFIG_TCG_NSC) += tpm_nsc.o | 9 | obj-$(CONFIG_TCG_NSC) += tpm_nsc.o |
9 | obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o | 10 | obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o |
10 | obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o | 11 | obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 5a3870477ef1..6889e7db3aff 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -32,12 +32,291 @@ enum tpm_const { | |||
32 | TPM_MINOR = 224, /* officially assigned */ | 32 | TPM_MINOR = 224, /* officially assigned */ |
33 | TPM_BUFSIZE = 2048, | 33 | TPM_BUFSIZE = 2048, |
34 | TPM_NUM_DEVICES = 256, | 34 | TPM_NUM_DEVICES = 256, |
35 | TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int)) | ||
36 | }; | 35 | }; |
37 | 36 | ||
37 | enum tpm_duration { | ||
38 | TPM_SHORT = 0, | ||
39 | TPM_MEDIUM = 1, | ||
40 | TPM_LONG = 2, | ||
41 | TPM_UNDEFINED, | ||
42 | }; | ||
43 | |||
44 | #define TPM_MAX_ORDINAL 243 | ||
45 | #define TPM_MAX_PROTECTED_ORDINAL 12 | ||
46 | #define TPM_PROTECTED_ORDINAL_MASK 0xFF | ||
47 | |||
38 | static LIST_HEAD(tpm_chip_list); | 48 | static LIST_HEAD(tpm_chip_list); |
39 | static DEFINE_SPINLOCK(driver_lock); | 49 | static DEFINE_SPINLOCK(driver_lock); |
40 | static int dev_mask[TPM_NUM_MASK_ENTRIES]; | 50 | static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); |
51 | |||
52 | /* | ||
53 | * Array with one entry per ordinal defining the maximum amount | ||
54 | * of time the chip could take to return the result. The ordinal | ||
55 | * designation of short, medium or long is defined in a table in | ||
56 | * TCG Specification TPM Main Part 2 TPM Structures Section 17. The | ||
57 | * values of the SHORT, MEDIUM, and LONG durations are retrieved | ||
58 | * from the chip during initialization with a call to tpm_get_timeouts. | ||
59 | */ | ||
60 | static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = { | ||
61 | TPM_UNDEFINED, /* 0 */ | ||
62 | TPM_UNDEFINED, | ||
63 | TPM_UNDEFINED, | ||
64 | TPM_UNDEFINED, | ||
65 | TPM_UNDEFINED, | ||
66 | TPM_UNDEFINED, /* 5 */ | ||
67 | TPM_UNDEFINED, | ||
68 | TPM_UNDEFINED, | ||
69 | TPM_UNDEFINED, | ||
70 | TPM_UNDEFINED, | ||
71 | TPM_SHORT, /* 10 */ | ||
72 | TPM_SHORT, | ||
73 | }; | ||
74 | |||
75 | static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = { | ||
76 | TPM_UNDEFINED, /* 0 */ | ||
77 | TPM_UNDEFINED, | ||
78 | TPM_UNDEFINED, | ||
79 | TPM_UNDEFINED, | ||
80 | TPM_UNDEFINED, | ||
81 | TPM_UNDEFINED, /* 5 */ | ||
82 | TPM_UNDEFINED, | ||
83 | TPM_UNDEFINED, | ||
84 | TPM_UNDEFINED, | ||
85 | TPM_UNDEFINED, | ||
86 | TPM_SHORT, /* 10 */ | ||
87 | TPM_SHORT, | ||
88 | TPM_MEDIUM, | ||
89 | TPM_LONG, | ||
90 | TPM_LONG, | ||
91 | TPM_MEDIUM, /* 15 */ | ||
92 | TPM_SHORT, | ||
93 | TPM_SHORT, | ||
94 | TPM_MEDIUM, | ||
95 | TPM_LONG, | ||
96 | TPM_SHORT, /* 20 */ | ||
97 | TPM_SHORT, | ||
98 | TPM_MEDIUM, | ||
99 | TPM_MEDIUM, | ||
100 | TPM_MEDIUM, | ||
101 | TPM_SHORT, /* 25 */ | ||
102 | TPM_SHORT, | ||
103 | TPM_MEDIUM, | ||
104 | TPM_SHORT, | ||
105 | TPM_SHORT, | ||
106 | TPM_MEDIUM, /* 30 */ | ||
107 | TPM_LONG, | ||
108 | TPM_MEDIUM, | ||
109 | TPM_SHORT, | ||
110 | TPM_SHORT, | ||
111 | TPM_SHORT, /* 35 */ | ||
112 | TPM_MEDIUM, | ||
113 | TPM_MEDIUM, | ||
114 | TPM_UNDEFINED, | ||
115 | TPM_UNDEFINED, | ||
116 | TPM_MEDIUM, /* 40 */ | ||
117 | TPM_LONG, | ||
118 | TPM_MEDIUM, | ||
119 | TPM_SHORT, | ||
120 | TPM_SHORT, | ||
121 | TPM_SHORT, /* 45 */ | ||
122 | TPM_SHORT, | ||
123 | TPM_SHORT, | ||
124 | TPM_SHORT, | ||
125 | TPM_LONG, | ||
126 | TPM_MEDIUM, /* 50 */ | ||
127 | TPM_MEDIUM, | ||
128 | TPM_UNDEFINED, | ||
129 | TPM_UNDEFINED, | ||
130 | TPM_UNDEFINED, | ||
131 | TPM_UNDEFINED, /* 55 */ | ||
132 | TPM_UNDEFINED, | ||
133 | TPM_UNDEFINED, | ||
134 | TPM_UNDEFINED, | ||
135 | TPM_UNDEFINED, | ||
136 | TPM_MEDIUM, /* 60 */ | ||
137 | TPM_MEDIUM, | ||
138 | TPM_MEDIUM, | ||
139 | TPM_SHORT, | ||
140 | TPM_SHORT, | ||
141 | TPM_MEDIUM, /* 65 */ | ||
142 | TPM_UNDEFINED, | ||
143 | TPM_UNDEFINED, | ||
144 | TPM_UNDEFINED, | ||
145 | TPM_UNDEFINED, | ||
146 | TPM_SHORT, /* 70 */ | ||
147 | TPM_SHORT, | ||
148 | TPM_UNDEFINED, | ||
149 | TPM_UNDEFINED, | ||
150 | TPM_UNDEFINED, | ||
151 | TPM_UNDEFINED, /* 75 */ | ||
152 | TPM_UNDEFINED, | ||
153 | TPM_UNDEFINED, | ||
154 | TPM_UNDEFINED, | ||
155 | TPM_UNDEFINED, | ||
156 | TPM_LONG, /* 80 */ | ||
157 | TPM_UNDEFINED, | ||
158 | TPM_MEDIUM, | ||
159 | TPM_LONG, | ||
160 | TPM_SHORT, | ||
161 | TPM_UNDEFINED, /* 85 */ | ||
162 | TPM_UNDEFINED, | ||
163 | TPM_UNDEFINED, | ||
164 | TPM_UNDEFINED, | ||
165 | TPM_UNDEFINED, | ||
166 | TPM_SHORT, /* 90 */ | ||
167 | TPM_SHORT, | ||
168 | TPM_SHORT, | ||
169 | TPM_SHORT, | ||
170 | TPM_SHORT, | ||
171 | TPM_UNDEFINED, /* 95 */ | ||
172 | TPM_UNDEFINED, | ||
173 | TPM_UNDEFINED, | ||
174 | TPM_UNDEFINED, | ||
175 | TPM_UNDEFINED, | ||
176 | TPM_MEDIUM, /* 100 */ | ||
177 | TPM_SHORT, | ||
178 | TPM_SHORT, | ||
179 | TPM_UNDEFINED, | ||
180 | TPM_UNDEFINED, | ||
181 | TPM_UNDEFINED, /* 105 */ | ||
182 | TPM_UNDEFINED, | ||
183 | TPM_UNDEFINED, | ||
184 | TPM_UNDEFINED, | ||
185 | TPM_UNDEFINED, | ||
186 | TPM_SHORT, /* 110 */ | ||
187 | TPM_SHORT, | ||
188 | TPM_SHORT, | ||
189 | TPM_SHORT, | ||
190 | TPM_SHORT, | ||
191 | TPM_SHORT, /* 115 */ | ||
192 | TPM_SHORT, | ||
193 | TPM_SHORT, | ||
194 | TPM_UNDEFINED, | ||
195 | TPM_UNDEFINED, | ||
196 | TPM_LONG, /* 120 */ | ||
197 | TPM_LONG, | ||
198 | TPM_MEDIUM, | ||
199 | TPM_UNDEFINED, | ||
200 | TPM_SHORT, | ||
201 | TPM_SHORT, /* 125 */ | ||
202 | TPM_SHORT, | ||
203 | TPM_LONG, | ||
204 | TPM_SHORT, | ||
205 | TPM_SHORT, | ||
206 | TPM_SHORT, /* 130 */ | ||
207 | TPM_MEDIUM, | ||
208 | TPM_UNDEFINED, | ||
209 | TPM_SHORT, | ||
210 | TPM_MEDIUM, | ||
211 | TPM_UNDEFINED, /* 135 */ | ||
212 | TPM_UNDEFINED, | ||
213 | TPM_UNDEFINED, | ||
214 | TPM_UNDEFINED, | ||
215 | TPM_UNDEFINED, | ||
216 | TPM_SHORT, /* 140 */ | ||
217 | TPM_SHORT, | ||
218 | TPM_UNDEFINED, | ||
219 | TPM_UNDEFINED, | ||
220 | TPM_UNDEFINED, | ||
221 | TPM_UNDEFINED, /* 145 */ | ||
222 | TPM_UNDEFINED, | ||
223 | TPM_UNDEFINED, | ||
224 | TPM_UNDEFINED, | ||
225 | TPM_UNDEFINED, | ||
226 | TPM_SHORT, /* 150 */ | ||
227 | TPM_MEDIUM, | ||
228 | TPM_MEDIUM, | ||
229 | TPM_SHORT, | ||
230 | TPM_SHORT, | ||
231 | TPM_UNDEFINED, /* 155 */ | ||
232 | TPM_UNDEFINED, | ||
233 | TPM_UNDEFINED, | ||
234 | TPM_UNDEFINED, | ||
235 | TPM_UNDEFINED, | ||
236 | TPM_SHORT, /* 160 */ | ||
237 | TPM_SHORT, | ||
238 | TPM_SHORT, | ||
239 | TPM_SHORT, | ||
240 | TPM_UNDEFINED, | ||
241 | TPM_UNDEFINED, /* 165 */ | ||
242 | TPM_UNDEFINED, | ||
243 | TPM_UNDEFINED, | ||
244 | TPM_UNDEFINED, | ||
245 | TPM_UNDEFINED, | ||
246 | TPM_LONG, /* 170 */ | ||
247 | TPM_UNDEFINED, | ||
248 | TPM_UNDEFINED, | ||
249 | TPM_UNDEFINED, | ||
250 | TPM_UNDEFINED, | ||
251 | TPM_UNDEFINED, /* 175 */ | ||
252 | TPM_UNDEFINED, | ||
253 | TPM_UNDEFINED, | ||
254 | TPM_UNDEFINED, | ||
255 | TPM_UNDEFINED, | ||
256 | TPM_MEDIUM, /* 180 */ | ||
257 | TPM_SHORT, | ||
258 | TPM_MEDIUM, | ||
259 | TPM_MEDIUM, | ||
260 | TPM_MEDIUM, | ||
261 | TPM_MEDIUM, /* 185 */ | ||
262 | TPM_SHORT, | ||
263 | TPM_UNDEFINED, | ||
264 | TPM_UNDEFINED, | ||
265 | TPM_UNDEFINED, | ||
266 | TPM_UNDEFINED, /* 190 */ | ||
267 | TPM_UNDEFINED, | ||
268 | TPM_UNDEFINED, | ||
269 | TPM_UNDEFINED, | ||
270 | TPM_UNDEFINED, | ||
271 | TPM_UNDEFINED, /* 195 */ | ||
272 | TPM_UNDEFINED, | ||
273 | TPM_UNDEFINED, | ||
274 | TPM_UNDEFINED, | ||
275 | TPM_UNDEFINED, | ||
276 | TPM_SHORT, /* 200 */ | ||
277 | TPM_UNDEFINED, | ||
278 | TPM_UNDEFINED, | ||
279 | TPM_UNDEFINED, | ||
280 | TPM_SHORT, | ||
281 | TPM_SHORT, /* 205 */ | ||
282 | TPM_SHORT, | ||
283 | TPM_SHORT, | ||
284 | TPM_SHORT, | ||
285 | TPM_SHORT, | ||
286 | TPM_MEDIUM, /* 210 */ | ||
287 | TPM_UNDEFINED, | ||
288 | TPM_MEDIUM, | ||
289 | TPM_MEDIUM, | ||
290 | TPM_MEDIUM, | ||
291 | TPM_UNDEFINED, /* 215 */ | ||
292 | TPM_MEDIUM, | ||
293 | TPM_UNDEFINED, | ||
294 | TPM_UNDEFINED, | ||
295 | TPM_SHORT, | ||
296 | TPM_SHORT, /* 220 */ | ||
297 | TPM_SHORT, | ||
298 | TPM_SHORT, | ||
299 | TPM_SHORT, | ||
300 | TPM_SHORT, | ||
301 | TPM_UNDEFINED, /* 225 */ | ||
302 | TPM_UNDEFINED, | ||
303 | TPM_UNDEFINED, | ||
304 | TPM_UNDEFINED, | ||
305 | TPM_UNDEFINED, | ||
306 | TPM_SHORT, /* 230 */ | ||
307 | TPM_LONG, | ||
308 | TPM_MEDIUM, | ||
309 | TPM_UNDEFINED, | ||
310 | TPM_UNDEFINED, | ||
311 | TPM_UNDEFINED, /* 235 */ | ||
312 | TPM_UNDEFINED, | ||
313 | TPM_UNDEFINED, | ||
314 | TPM_UNDEFINED, | ||
315 | TPM_UNDEFINED, | ||
316 | TPM_SHORT, /* 240 */ | ||
317 | TPM_UNDEFINED, | ||
318 | TPM_MEDIUM, | ||
319 | }; | ||
41 | 320 | ||
42 | static void user_reader_timeout(unsigned long ptr) | 321 | static void user_reader_timeout(unsigned long ptr) |
43 | { | 322 | { |
@@ -46,7 +325,7 @@ static void user_reader_timeout(unsigned long ptr) | |||
46 | schedule_work(&chip->work); | 325 | schedule_work(&chip->work); |
47 | } | 326 | } |
48 | 327 | ||
49 | static void timeout_work(void * ptr) | 328 | static void timeout_work(void *ptr) |
50 | { | 329 | { |
51 | struct tpm_chip *chip = ptr; | 330 | struct tpm_chip *chip = ptr; |
52 | 331 | ||
@@ -57,17 +336,43 @@ static void timeout_work(void * ptr) | |||
57 | } | 336 | } |
58 | 337 | ||
59 | /* | 338 | /* |
339 | * Returns max number of jiffies to wait | ||
340 | */ | ||
341 | unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, | ||
342 | u32 ordinal) | ||
343 | { | ||
344 | int duration_idx = TPM_UNDEFINED; | ||
345 | int duration = 0; | ||
346 | |||
347 | if (ordinal < TPM_MAX_ORDINAL) | ||
348 | duration_idx = tpm_ordinal_duration[ordinal]; | ||
349 | else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) < | ||
350 | TPM_MAX_PROTECTED_ORDINAL) | ||
351 | duration_idx = | ||
352 | tpm_protected_ordinal_duration[ordinal & | ||
353 | TPM_PROTECTED_ORDINAL_MASK]; | ||
354 | |||
355 | if (duration_idx != TPM_UNDEFINED) | ||
356 | duration = chip->vendor.duration[duration_idx]; | ||
357 | if (duration <= 0) | ||
358 | return 2 * 60 * HZ; | ||
359 | else | ||
360 | return duration; | ||
361 | } | ||
362 | EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); | ||
363 | |||
364 | /* | ||
60 | * Internal kernel interface to transmit TPM commands | 365 | * Internal kernel interface to transmit TPM commands |
61 | */ | 366 | */ |
62 | static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | 367 | static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, |
63 | size_t bufsiz) | 368 | size_t bufsiz) |
64 | { | 369 | { |
65 | ssize_t rc; | 370 | ssize_t rc; |
66 | u32 count; | 371 | u32 count, ordinal; |
67 | unsigned long stop; | 372 | unsigned long stop; |
68 | 373 | ||
69 | count = be32_to_cpu(*((__be32 *) (buf + 2))); | 374 | count = be32_to_cpu(*((__be32 *) (buf + 2))); |
70 | 375 | ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); | |
71 | if (count == 0) | 376 | if (count == 0) |
72 | return -ENODATA; | 377 | return -ENODATA; |
73 | if (count > bufsiz) { | 378 | if (count > bufsiz) { |
@@ -78,21 +383,23 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | |||
78 | 383 | ||
79 | down(&chip->tpm_mutex); | 384 | down(&chip->tpm_mutex); |
80 | 385 | ||
81 | if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) { | 386 | if ((rc = chip->vendor.send(chip, (u8 *) buf, count)) < 0) { |
82 | dev_err(chip->dev, | 387 | dev_err(chip->dev, |
83 | "tpm_transmit: tpm_send: error %zd\n", rc); | 388 | "tpm_transmit: tpm_send: error %zd\n", rc); |
84 | goto out; | 389 | goto out; |
85 | } | 390 | } |
86 | 391 | ||
87 | stop = jiffies + 2 * 60 * HZ; | 392 | if (chip->vendor.irq) |
393 | goto out_recv; | ||
394 | |||
395 | stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal); | ||
88 | do { | 396 | do { |
89 | u8 status = chip->vendor->status(chip); | 397 | u8 status = chip->vendor.status(chip); |
90 | if ((status & chip->vendor->req_complete_mask) == | 398 | if ((status & chip->vendor.req_complete_mask) == |
91 | chip->vendor->req_complete_val) { | 399 | chip->vendor.req_complete_val) |
92 | goto out_recv; | 400 | goto out_recv; |
93 | } | ||
94 | 401 | ||
95 | if ((status == chip->vendor->req_canceled)) { | 402 | if ((status == chip->vendor.req_canceled)) { |
96 | dev_err(chip->dev, "Operation Canceled\n"); | 403 | dev_err(chip->dev, "Operation Canceled\n"); |
97 | rc = -ECANCELED; | 404 | rc = -ECANCELED; |
98 | goto out; | 405 | goto out; |
@@ -102,14 +409,13 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | |||
102 | rmb(); | 409 | rmb(); |
103 | } while (time_before(jiffies, stop)); | 410 | } while (time_before(jiffies, stop)); |
104 | 411 | ||
105 | 412 | chip->vendor.cancel(chip); | |
106 | chip->vendor->cancel(chip); | ||
107 | dev_err(chip->dev, "Operation Timed out\n"); | 413 | dev_err(chip->dev, "Operation Timed out\n"); |
108 | rc = -ETIME; | 414 | rc = -ETIME; |
109 | goto out; | 415 | goto out; |
110 | 416 | ||
111 | out_recv: | 417 | out_recv: |
112 | rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz); | 418 | rc = chip->vendor.recv(chip, (u8 *) buf, bufsiz); |
113 | if (rc < 0) | 419 | if (rc < 0) |
114 | dev_err(chip->dev, | 420 | dev_err(chip->dev, |
115 | "tpm_transmit: tpm_recv: error %zd\n", rc); | 421 | "tpm_transmit: tpm_recv: error %zd\n", rc); |
@@ -119,17 +425,247 @@ out: | |||
119 | } | 425 | } |
120 | 426 | ||
121 | #define TPM_DIGEST_SIZE 20 | 427 | #define TPM_DIGEST_SIZE 20 |
122 | #define CAP_PCR_RESULT_SIZE 18 | 428 | #define TPM_ERROR_SIZE 10 |
123 | static const u8 cap_pcr[] = { | 429 | #define TPM_RET_CODE_IDX 6 |
430 | #define TPM_GET_CAP_RET_SIZE_IDX 10 | ||
431 | #define TPM_GET_CAP_RET_UINT32_1_IDX 14 | ||
432 | #define TPM_GET_CAP_RET_UINT32_2_IDX 18 | ||
433 | #define TPM_GET_CAP_RET_UINT32_3_IDX 22 | ||
434 | #define TPM_GET_CAP_RET_UINT32_4_IDX 26 | ||
435 | #define TPM_GET_CAP_PERM_DISABLE_IDX 16 | ||
436 | #define TPM_GET_CAP_PERM_INACTIVE_IDX 18 | ||
437 | #define TPM_GET_CAP_RET_BOOL_1_IDX 14 | ||
438 | #define TPM_GET_CAP_TEMP_INACTIVE_IDX 16 | ||
439 | |||
440 | #define TPM_CAP_IDX 13 | ||
441 | #define TPM_CAP_SUBCAP_IDX 21 | ||
442 | |||
443 | enum tpm_capabilities { | ||
444 | TPM_CAP_FLAG = 4, | ||
445 | TPM_CAP_PROP = 5, | ||
446 | }; | ||
447 | |||
448 | enum tpm_sub_capabilities { | ||
449 | TPM_CAP_PROP_PCR = 0x1, | ||
450 | TPM_CAP_PROP_MANUFACTURER = 0x3, | ||
451 | TPM_CAP_FLAG_PERM = 0x8, | ||
452 | TPM_CAP_FLAG_VOL = 0x9, | ||
453 | TPM_CAP_PROP_OWNER = 0x11, | ||
454 | TPM_CAP_PROP_TIS_TIMEOUT = 0x15, | ||
455 | TPM_CAP_PROP_TIS_DURATION = 0x20, | ||
456 | }; | ||
457 | |||
458 | /* | ||
459 | * This is a semi generic GetCapability command for use | ||
460 | * with the capability type TPM_CAP_PROP or TPM_CAP_FLAG | ||
461 | * and their associated sub_capabilities. | ||
462 | */ | ||
463 | |||
464 | static const u8 tpm_cap[] = { | ||
124 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 465 | 0, 193, /* TPM_TAG_RQU_COMMAND */ |
125 | 0, 0, 0, 22, /* length */ | 466 | 0, 0, 0, 22, /* length */ |
126 | 0, 0, 0, 101, /* TPM_ORD_GetCapability */ | 467 | 0, 0, 0, 101, /* TPM_ORD_GetCapability */ |
127 | 0, 0, 0, 5, | 468 | 0, 0, 0, 0, /* TPM_CAP_<TYPE> */ |
128 | 0, 0, 0, 4, | 469 | 0, 0, 0, 4, /* TPM_CAP_SUB_<TYPE> size */ |
129 | 0, 0, 1, 1 | 470 | 0, 0, 1, 0 /* TPM_CAP_SUB_<TYPE> */ |
130 | }; | 471 | }; |
131 | 472 | ||
132 | #define READ_PCR_RESULT_SIZE 30 | 473 | static ssize_t transmit_cmd(struct tpm_chip *chip, u8 *data, int len, |
474 | char *desc) | ||
475 | { | ||
476 | int err; | ||
477 | |||
478 | len = tpm_transmit(chip, data, len); | ||
479 | if (len < 0) | ||
480 | return len; | ||
481 | if (len == TPM_ERROR_SIZE) { | ||
482 | err = be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))); | ||
483 | dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); | ||
484 | return err; | ||
485 | } | ||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | void tpm_gen_interrupt(struct tpm_chip *chip) | ||
490 | { | ||
491 | u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)]; | ||
492 | ssize_t rc; | ||
493 | |||
494 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
495 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | ||
496 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT; | ||
497 | |||
498 | rc = transmit_cmd(chip, data, sizeof(data), | ||
499 | "attempting to determine the timeouts"); | ||
500 | } | ||
501 | EXPORT_SYMBOL_GPL(tpm_gen_interrupt); | ||
502 | |||
503 | void tpm_get_timeouts(struct tpm_chip *chip) | ||
504 | { | ||
505 | u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)]; | ||
506 | ssize_t rc; | ||
507 | u32 timeout; | ||
508 | |||
509 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
510 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | ||
511 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT; | ||
512 | |||
513 | rc = transmit_cmd(chip, data, sizeof(data), | ||
514 | "attempting to determine the timeouts"); | ||
515 | if (rc) | ||
516 | goto duration; | ||
517 | |||
518 | if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX))) | ||
519 | != 4 * sizeof(u32)) | ||
520 | goto duration; | ||
521 | |||
522 | /* Don't overwrite default if value is 0 */ | ||
523 | timeout = | ||
524 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))); | ||
525 | if (timeout) | ||
526 | chip->vendor.timeout_a = msecs_to_jiffies(timeout); | ||
527 | timeout = | ||
528 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX))); | ||
529 | if (timeout) | ||
530 | chip->vendor.timeout_b = msecs_to_jiffies(timeout); | ||
531 | timeout = | ||
532 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX))); | ||
533 | if (timeout) | ||
534 | chip->vendor.timeout_c = msecs_to_jiffies(timeout); | ||
535 | timeout = | ||
536 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX))); | ||
537 | if (timeout) | ||
538 | chip->vendor.timeout_d = msecs_to_jiffies(timeout); | ||
539 | |||
540 | duration: | ||
541 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
542 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | ||
543 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_DURATION; | ||
544 | |||
545 | rc = transmit_cmd(chip, data, sizeof(data), | ||
546 | "attempting to determine the durations"); | ||
547 | if (rc) | ||
548 | return; | ||
549 | |||
550 | if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX))) | ||
551 | != 3 * sizeof(u32)) | ||
552 | return; | ||
553 | |||
554 | chip->vendor.duration[TPM_SHORT] = | ||
555 | msecs_to_jiffies(be32_to_cpu | ||
556 | (*((__be32 *) (data + | ||
557 | TPM_GET_CAP_RET_UINT32_1_IDX)))); | ||
558 | chip->vendor.duration[TPM_MEDIUM] = | ||
559 | msecs_to_jiffies(be32_to_cpu | ||
560 | (*((__be32 *) (data + | ||
561 | TPM_GET_CAP_RET_UINT32_2_IDX)))); | ||
562 | chip->vendor.duration[TPM_LONG] = | ||
563 | msecs_to_jiffies(be32_to_cpu | ||
564 | (*((__be32 *) (data + | ||
565 | TPM_GET_CAP_RET_UINT32_3_IDX)))); | ||
566 | } | ||
567 | EXPORT_SYMBOL_GPL(tpm_get_timeouts); | ||
568 | |||
569 | void tpm_continue_selftest(struct tpm_chip *chip) | ||
570 | { | ||
571 | u8 data[] = { | ||
572 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | ||
573 | 0, 0, 0, 10, /* length */ | ||
574 | 0, 0, 0, 83, /* TPM_ORD_GetCapability */ | ||
575 | }; | ||
576 | |||
577 | tpm_transmit(chip, data, sizeof(data)); | ||
578 | } | ||
579 | EXPORT_SYMBOL_GPL(tpm_continue_selftest); | ||
580 | |||
581 | ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, | ||
582 | char *buf) | ||
583 | { | ||
584 | u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)]; | ||
585 | ssize_t rc; | ||
586 | |||
587 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
588 | if (chip == NULL) | ||
589 | return -ENODEV; | ||
590 | |||
591 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
592 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; | ||
593 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; | ||
594 | |||
595 | rc = transmit_cmd(chip, data, sizeof(data), | ||
596 | "attemtping to determine the permanent state"); | ||
597 | if (rc) | ||
598 | return 0; | ||
599 | return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]); | ||
600 | } | ||
601 | EXPORT_SYMBOL_GPL(tpm_show_enabled); | ||
602 | |||
603 | ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr, | ||
604 | char *buf) | ||
605 | { | ||
606 | u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)]; | ||
607 | ssize_t rc; | ||
608 | |||
609 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
610 | if (chip == NULL) | ||
611 | return -ENODEV; | ||
612 | |||
613 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
614 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; | ||
615 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; | ||
616 | |||
617 | rc = transmit_cmd(chip, data, sizeof(data), | ||
618 | "attemtping to determine the permanent state"); | ||
619 | if (rc) | ||
620 | return 0; | ||
621 | return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]); | ||
622 | } | ||
623 | EXPORT_SYMBOL_GPL(tpm_show_active); | ||
624 | |||
625 | ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr, | ||
626 | char *buf) | ||
627 | { | ||
628 | u8 data[sizeof(tpm_cap)]; | ||
629 | ssize_t rc; | ||
630 | |||
631 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
632 | if (chip == NULL) | ||
633 | return -ENODEV; | ||
634 | |||
635 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
636 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | ||
637 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER; | ||
638 | |||
639 | rc = transmit_cmd(chip, data, sizeof(data), | ||
640 | "attempting to determine the owner state"); | ||
641 | if (rc) | ||
642 | return 0; | ||
643 | return sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]); | ||
644 | } | ||
645 | EXPORT_SYMBOL_GPL(tpm_show_owned); | ||
646 | |||
647 | ssize_t tpm_show_temp_deactivated(struct device * dev, | ||
648 | struct device_attribute * attr, char *buf) | ||
649 | { | ||
650 | u8 data[sizeof(tpm_cap)]; | ||
651 | ssize_t rc; | ||
652 | |||
653 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
654 | if (chip == NULL) | ||
655 | return -ENODEV; | ||
656 | |||
657 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
658 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; | ||
659 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL; | ||
660 | |||
661 | rc = transmit_cmd(chip, data, sizeof(data), | ||
662 | "attempting to determine the temporary state"); | ||
663 | if (rc) | ||
664 | return 0; | ||
665 | return sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]); | ||
666 | } | ||
667 | EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); | ||
668 | |||
133 | static const u8 pcrread[] = { | 669 | static const u8 pcrread[] = { |
134 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 670 | 0, 193, /* TPM_TAG_RQU_COMMAND */ |
135 | 0, 0, 0, 14, /* length */ | 671 | 0, 0, 0, 14, /* length */ |
@@ -140,8 +676,8 @@ static const u8 pcrread[] = { | |||
140 | ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, | 676 | ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, |
141 | char *buf) | 677 | char *buf) |
142 | { | 678 | { |
143 | u8 data[READ_PCR_RESULT_SIZE]; | 679 | u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(pcrread)), 30)]; |
144 | ssize_t len; | 680 | ssize_t rc; |
145 | int i, j, num_pcrs; | 681 | int i, j, num_pcrs; |
146 | __be32 index; | 682 | __be32 index; |
147 | char *str = buf; | 683 | char *str = buf; |
@@ -150,29 +686,24 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, | |||
150 | if (chip == NULL) | 686 | if (chip == NULL) |
151 | return -ENODEV; | 687 | return -ENODEV; |
152 | 688 | ||
153 | memcpy(data, cap_pcr, sizeof(cap_pcr)); | 689 | memcpy(data, tpm_cap, sizeof(tpm_cap)); |
154 | if ((len = tpm_transmit(chip, data, sizeof(data))) | 690 | data[TPM_CAP_IDX] = TPM_CAP_PROP; |
155 | < CAP_PCR_RESULT_SIZE) { | 691 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR; |
156 | dev_dbg(chip->dev, "A TPM error (%d) occurred " | 692 | |
157 | "attempting to determine the number of PCRS\n", | 693 | rc = transmit_cmd(chip, data, sizeof(data), |
158 | be32_to_cpu(*((__be32 *) (data + 6)))); | 694 | "attempting to determine the number of PCRS"); |
695 | if (rc) | ||
159 | return 0; | 696 | return 0; |
160 | } | ||
161 | 697 | ||
162 | num_pcrs = be32_to_cpu(*((__be32 *) (data + 14))); | 698 | num_pcrs = be32_to_cpu(*((__be32 *) (data + 14))); |
163 | |||
164 | for (i = 0; i < num_pcrs; i++) { | 699 | for (i = 0; i < num_pcrs; i++) { |
165 | memcpy(data, pcrread, sizeof(pcrread)); | 700 | memcpy(data, pcrread, sizeof(pcrread)); |
166 | index = cpu_to_be32(i); | 701 | index = cpu_to_be32(i); |
167 | memcpy(data + 10, &index, 4); | 702 | memcpy(data + 10, &index, 4); |
168 | if ((len = tpm_transmit(chip, data, sizeof(data))) | 703 | rc = transmit_cmd(chip, data, sizeof(data), |
169 | < READ_PCR_RESULT_SIZE){ | 704 | "attempting to read a PCR"); |
170 | dev_dbg(chip->dev, "A TPM error (%d) occurred" | 705 | if (rc) |
171 | " attempting to read PCR %d of %d\n", | ||
172 | be32_to_cpu(*((__be32 *) (data + 6))), | ||
173 | i, num_pcrs); | ||
174 | goto out; | 706 | goto out; |
175 | } | ||
176 | str += sprintf(str, "PCR-%02d: ", i); | 707 | str += sprintf(str, "PCR-%02d: ", i); |
177 | for (j = 0; j < TPM_DIGEST_SIZE; j++) | 708 | for (j = 0; j < TPM_DIGEST_SIZE; j++) |
178 | str += sprintf(str, "%02X ", *(data + 10 + j)); | 709 | str += sprintf(str, "%02X ", *(data + 10 + j)); |
@@ -194,7 +725,7 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, | |||
194 | char *buf) | 725 | char *buf) |
195 | { | 726 | { |
196 | u8 *data; | 727 | u8 *data; |
197 | ssize_t len; | 728 | ssize_t err; |
198 | int i, rc; | 729 | int i, rc; |
199 | char *str = buf; | 730 | char *str = buf; |
200 | 731 | ||
@@ -208,14 +739,10 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, | |||
208 | 739 | ||
209 | memcpy(data, readpubek, sizeof(readpubek)); | 740 | memcpy(data, readpubek, sizeof(readpubek)); |
210 | 741 | ||
211 | if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) < | 742 | err = transmit_cmd(chip, data, READ_PUBEK_RESULT_SIZE, |
212 | READ_PUBEK_RESULT_SIZE) { | 743 | "attempting to read the PUBEK"); |
213 | dev_dbg(chip->dev, "A TPM error (%d) occurred " | 744 | if (err) |
214 | "attempting to read the PUBEK\n", | ||
215 | be32_to_cpu(*((__be32 *) (data + 6)))); | ||
216 | rc = 0; | ||
217 | goto out; | 745 | goto out; |
218 | } | ||
219 | 746 | ||
220 | /* | 747 | /* |
221 | ignore header 10 bytes | 748 | ignore header 10 bytes |
@@ -245,67 +772,110 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, | |||
245 | if ((i + 1) % 16 == 0) | 772 | if ((i + 1) % 16 == 0) |
246 | str += sprintf(str, "\n"); | 773 | str += sprintf(str, "\n"); |
247 | } | 774 | } |
248 | rc = str - buf; | ||
249 | out: | 775 | out: |
776 | rc = str - buf; | ||
250 | kfree(data); | 777 | kfree(data); |
251 | return rc; | 778 | return rc; |
252 | } | 779 | } |
253 | EXPORT_SYMBOL_GPL(tpm_show_pubek); | 780 | EXPORT_SYMBOL_GPL(tpm_show_pubek); |
254 | 781 | ||
255 | #define CAP_VER_RESULT_SIZE 18 | 782 | #define CAP_VERSION_1_1 6 |
783 | #define CAP_VERSION_1_2 0x1A | ||
784 | #define CAP_VERSION_IDX 13 | ||
256 | static const u8 cap_version[] = { | 785 | static const u8 cap_version[] = { |
257 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 786 | 0, 193, /* TPM_TAG_RQU_COMMAND */ |
258 | 0, 0, 0, 18, /* length */ | 787 | 0, 0, 0, 18, /* length */ |
259 | 0, 0, 0, 101, /* TPM_ORD_GetCapability */ | 788 | 0, 0, 0, 101, /* TPM_ORD_GetCapability */ |
260 | 0, 0, 0, 6, | 789 | 0, 0, 0, 0, |
261 | 0, 0, 0, 0 | 790 | 0, 0, 0, 0 |
262 | }; | 791 | }; |
263 | 792 | ||
264 | #define CAP_MANUFACTURER_RESULT_SIZE 18 | ||
265 | static const u8 cap_manufacturer[] = { | ||
266 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | ||
267 | 0, 0, 0, 22, /* length */ | ||
268 | 0, 0, 0, 101, /* TPM_ORD_GetCapability */ | ||
269 | 0, 0, 0, 5, | ||
270 | 0, 0, 0, 4, | ||
271 | 0, 0, 1, 3 | ||
272 | }; | ||
273 | |||
274 | ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, | 793 | ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, |
275 | char *buf) | 794 | char *buf) |
276 | { | 795 | { |
277 | u8 data[sizeof(cap_manufacturer)]; | 796 | u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)]; |
278 | ssize_t len; | 797 | ssize_t rc; |
279 | char *str = buf; | 798 | char *str = buf; |
280 | 799 | ||
281 | struct tpm_chip *chip = dev_get_drvdata(dev); | 800 | struct tpm_chip *chip = dev_get_drvdata(dev); |
282 | if (chip == NULL) | 801 | if (chip == NULL) |
283 | return -ENODEV; | 802 | return -ENODEV; |
284 | 803 | ||
285 | memcpy(data, cap_manufacturer, sizeof(cap_manufacturer)); | 804 | memcpy(data, tpm_cap, sizeof(tpm_cap)); |
805 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | ||
806 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; | ||
286 | 807 | ||
287 | if ((len = tpm_transmit(chip, data, sizeof(data))) < | 808 | rc = transmit_cmd(chip, data, sizeof(data), |
288 | CAP_MANUFACTURER_RESULT_SIZE) | 809 | "attempting to determine the manufacturer"); |
289 | return len; | 810 | if (rc) |
811 | return 0; | ||
290 | 812 | ||
291 | str += sprintf(str, "Manufacturer: 0x%x\n", | 813 | str += sprintf(str, "Manufacturer: 0x%x\n", |
292 | be32_to_cpu(*((__be32 *) (data + 14)))); | 814 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); |
293 | 815 | ||
294 | memcpy(data, cap_version, sizeof(cap_version)); | 816 | memcpy(data, cap_version, sizeof(cap_version)); |
817 | data[CAP_VERSION_IDX] = CAP_VERSION_1_1; | ||
818 | rc = transmit_cmd(chip, data, sizeof(data), | ||
819 | "attempting to determine the 1.1 version"); | ||
820 | if (rc) | ||
821 | goto out; | ||
295 | 822 | ||
296 | if ((len = tpm_transmit(chip, data, sizeof(data))) < | 823 | str += sprintf(str, |
297 | CAP_VER_RESULT_SIZE) | 824 | "TCG version: %d.%d\nFirmware version: %d.%d\n", |
298 | return len; | 825 | (int) data[14], (int) data[15], (int) data[16], |
299 | 826 | (int) data[17]); | |
300 | str += | ||
301 | sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n", | ||
302 | (int) data[14], (int) data[15], (int) data[16], | ||
303 | (int) data[17]); | ||
304 | 827 | ||
828 | out: | ||
305 | return str - buf; | 829 | return str - buf; |
306 | } | 830 | } |
307 | EXPORT_SYMBOL_GPL(tpm_show_caps); | 831 | EXPORT_SYMBOL_GPL(tpm_show_caps); |
308 | 832 | ||
833 | ssize_t tpm_show_caps_1_2(struct device * dev, | ||
834 | struct device_attribute * attr, char *buf) | ||
835 | { | ||
836 | u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)]; | ||
837 | ssize_t len; | ||
838 | char *str = buf; | ||
839 | |||
840 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
841 | if (chip == NULL) | ||
842 | return -ENODEV; | ||
843 | |||
844 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
845 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | ||
846 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; | ||
847 | |||
848 | if ((len = tpm_transmit(chip, data, sizeof(data))) <= | ||
849 | TPM_ERROR_SIZE) { | ||
850 | dev_dbg(chip->dev, "A TPM error (%d) occurred " | ||
851 | "attempting to determine the manufacturer\n", | ||
852 | be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); | ||
853 | return 0; | ||
854 | } | ||
855 | |||
856 | str += sprintf(str, "Manufacturer: 0x%x\n", | ||
857 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); | ||
858 | |||
859 | memcpy(data, cap_version, sizeof(cap_version)); | ||
860 | data[CAP_VERSION_IDX] = CAP_VERSION_1_2; | ||
861 | |||
862 | if ((len = tpm_transmit(chip, data, sizeof(data))) <= | ||
863 | TPM_ERROR_SIZE) { | ||
864 | dev_err(chip->dev, "A TPM error (%d) occurred " | ||
865 | "attempting to determine the 1.2 version\n", | ||
866 | be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); | ||
867 | goto out; | ||
868 | } | ||
869 | str += sprintf(str, | ||
870 | "TCG version: %d.%d\nFirmware version: %d.%d\n", | ||
871 | (int) data[16], (int) data[17], (int) data[18], | ||
872 | (int) data[19]); | ||
873 | |||
874 | out: | ||
875 | return str - buf; | ||
876 | } | ||
877 | EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); | ||
878 | |||
309 | ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, | 879 | ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, |
310 | const char *buf, size_t count) | 880 | const char *buf, size_t count) |
311 | { | 881 | { |
@@ -313,7 +883,7 @@ ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, | |||
313 | if (chip == NULL) | 883 | if (chip == NULL) |
314 | return 0; | 884 | return 0; |
315 | 885 | ||
316 | chip->vendor->cancel(chip); | 886 | chip->vendor.cancel(chip); |
317 | return count; | 887 | return count; |
318 | } | 888 | } |
319 | EXPORT_SYMBOL_GPL(tpm_store_cancel); | 889 | EXPORT_SYMBOL_GPL(tpm_store_cancel); |
@@ -329,7 +899,7 @@ int tpm_open(struct inode *inode, struct file *file) | |||
329 | spin_lock(&driver_lock); | 899 | spin_lock(&driver_lock); |
330 | 900 | ||
331 | list_for_each_entry(pos, &tpm_chip_list, list) { | 901 | list_for_each_entry(pos, &tpm_chip_list, list) { |
332 | if (pos->vendor->miscdev.minor == minor) { | 902 | if (pos->vendor.miscdev.minor == minor) { |
333 | chip = pos; | 903 | chip = pos; |
334 | break; | 904 | break; |
335 | } | 905 | } |
@@ -387,7 +957,7 @@ int tpm_release(struct inode *inode, struct file *file) | |||
387 | EXPORT_SYMBOL_GPL(tpm_release); | 957 | EXPORT_SYMBOL_GPL(tpm_release); |
388 | 958 | ||
389 | ssize_t tpm_write(struct file *file, const char __user *buf, | 959 | ssize_t tpm_write(struct file *file, const char __user *buf, |
390 | size_t size, loff_t * off) | 960 | size_t size, loff_t *off) |
391 | { | 961 | { |
392 | struct tpm_chip *chip = file->private_data; | 962 | struct tpm_chip *chip = file->private_data; |
393 | int in_size = size, out_size; | 963 | int in_size = size, out_size; |
@@ -419,11 +989,10 @@ ssize_t tpm_write(struct file *file, const char __user *buf, | |||
419 | 989 | ||
420 | return in_size; | 990 | return in_size; |
421 | } | 991 | } |
422 | |||
423 | EXPORT_SYMBOL_GPL(tpm_write); | 992 | EXPORT_SYMBOL_GPL(tpm_write); |
424 | 993 | ||
425 | ssize_t tpm_read(struct file * file, char __user *buf, | 994 | ssize_t tpm_read(struct file *file, char __user *buf, |
426 | size_t size, loff_t * off) | 995 | size_t size, loff_t *off) |
427 | { | 996 | { |
428 | struct tpm_chip *chip = file->private_data; | 997 | struct tpm_chip *chip = file->private_data; |
429 | int ret_size; | 998 | int ret_size; |
@@ -462,14 +1031,13 @@ void tpm_remove_hardware(struct device *dev) | |||
462 | spin_unlock(&driver_lock); | 1031 | spin_unlock(&driver_lock); |
463 | 1032 | ||
464 | dev_set_drvdata(dev, NULL); | 1033 | dev_set_drvdata(dev, NULL); |
465 | misc_deregister(&chip->vendor->miscdev); | 1034 | misc_deregister(&chip->vendor.miscdev); |
466 | kfree(chip->vendor->miscdev.name); | 1035 | kfree(chip->vendor.miscdev.name); |
467 | 1036 | ||
468 | sysfs_remove_group(&dev->kobj, chip->vendor->attr_group); | 1037 | sysfs_remove_group(&dev->kobj, chip->vendor.attr_group); |
469 | tpm_bios_log_teardown(chip->bios_dir); | 1038 | tpm_bios_log_teardown(chip->bios_dir); |
470 | 1039 | ||
471 | dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= | 1040 | clear_bit(chip->dev_num, dev_mask); |
472 | ~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES)); | ||
473 | 1041 | ||
474 | kfree(chip); | 1042 | kfree(chip); |
475 | 1043 | ||
@@ -520,18 +1088,18 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume); | |||
520 | * upon errant exit from this function specific probe function should call | 1088 | * upon errant exit from this function specific probe function should call |
521 | * pci_disable_device | 1089 | * pci_disable_device |
522 | */ | 1090 | */ |
523 | int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry) | 1091 | struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vendor_specific |
1092 | *entry) | ||
524 | { | 1093 | { |
525 | #define DEVNAME_SIZE 7 | 1094 | #define DEVNAME_SIZE 7 |
526 | 1095 | ||
527 | char *devname; | 1096 | char *devname; |
528 | struct tpm_chip *chip; | 1097 | struct tpm_chip *chip; |
529 | int i, j; | ||
530 | 1098 | ||
531 | /* Driver specific per-device data */ | 1099 | /* Driver specific per-device data */ |
532 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | 1100 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
533 | if (chip == NULL) | 1101 | if (chip == NULL) |
534 | return -ENOMEM; | 1102 | return NULL; |
535 | 1103 | ||
536 | init_MUTEX(&chip->buffer_mutex); | 1104 | init_MUTEX(&chip->buffer_mutex); |
537 | init_MUTEX(&chip->tpm_mutex); | 1105 | init_MUTEX(&chip->tpm_mutex); |
@@ -543,45 +1111,37 @@ int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry) | |||
543 | chip->user_read_timer.function = user_reader_timeout; | 1111 | chip->user_read_timer.function = user_reader_timeout; |
544 | chip->user_read_timer.data = (unsigned long) chip; | 1112 | chip->user_read_timer.data = (unsigned long) chip; |
545 | 1113 | ||
546 | chip->vendor = entry; | 1114 | memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific)); |
547 | |||
548 | chip->dev_num = -1; | ||
549 | 1115 | ||
550 | for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++) | 1116 | chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES); |
551 | for (j = 0; j < 8 * sizeof(int); j++) | ||
552 | if ((dev_mask[i] & (1 << j)) == 0) { | ||
553 | chip->dev_num = | ||
554 | i * TPM_NUM_MASK_ENTRIES + j; | ||
555 | dev_mask[i] |= 1 << j; | ||
556 | goto dev_num_search_complete; | ||
557 | } | ||
558 | 1117 | ||
559 | dev_num_search_complete: | 1118 | if (chip->dev_num >= TPM_NUM_DEVICES) { |
560 | if (chip->dev_num < 0) { | ||
561 | dev_err(dev, "No available tpm device numbers\n"); | 1119 | dev_err(dev, "No available tpm device numbers\n"); |
562 | kfree(chip); | 1120 | kfree(chip); |
563 | return -ENODEV; | 1121 | return NULL; |
564 | } else if (chip->dev_num == 0) | 1122 | } else if (chip->dev_num == 0) |
565 | chip->vendor->miscdev.minor = TPM_MINOR; | 1123 | chip->vendor.miscdev.minor = TPM_MINOR; |
566 | else | 1124 | else |
567 | chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR; | 1125 | chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR; |
1126 | |||
1127 | set_bit(chip->dev_num, dev_mask); | ||
568 | 1128 | ||
569 | devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL); | 1129 | devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL); |
570 | scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num); | 1130 | scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num); |
571 | chip->vendor->miscdev.name = devname; | 1131 | chip->vendor.miscdev.name = devname; |
572 | 1132 | ||
573 | chip->vendor->miscdev.dev = dev; | 1133 | chip->vendor.miscdev.dev = dev; |
574 | chip->dev = get_device(dev); | 1134 | chip->dev = get_device(dev); |
575 | 1135 | ||
576 | if (misc_register(&chip->vendor->miscdev)) { | 1136 | if (misc_register(&chip->vendor.miscdev)) { |
577 | dev_err(chip->dev, | 1137 | dev_err(chip->dev, |
578 | "unable to misc_register %s, minor %d\n", | 1138 | "unable to misc_register %s, minor %d\n", |
579 | chip->vendor->miscdev.name, | 1139 | chip->vendor.miscdev.name, |
580 | chip->vendor->miscdev.minor); | 1140 | chip->vendor.miscdev.minor); |
581 | put_device(dev); | 1141 | put_device(dev); |
1142 | clear_bit(chip->dev_num, dev_mask); | ||
582 | kfree(chip); | 1143 | kfree(chip); |
583 | dev_mask[i] &= !(1 << j); | 1144 | return NULL; |
584 | return -ENODEV; | ||
585 | } | 1145 | } |
586 | 1146 | ||
587 | spin_lock(&driver_lock); | 1147 | spin_lock(&driver_lock); |
@@ -592,11 +1152,11 @@ dev_num_search_complete: | |||
592 | 1152 | ||
593 | spin_unlock(&driver_lock); | 1153 | spin_unlock(&driver_lock); |
594 | 1154 | ||
595 | sysfs_create_group(&dev->kobj, chip->vendor->attr_group); | 1155 | sysfs_create_group(&dev->kobj, chip->vendor.attr_group); |
596 | 1156 | ||
597 | chip->bios_dir = tpm_bios_log_setup(devname); | 1157 | chip->bios_dir = tpm_bios_log_setup(devname); |
598 | 1158 | ||
599 | return 0; | 1159 | return chip; |
600 | } | 1160 | } |
601 | EXPORT_SYMBOL_GPL(tpm_register_hardware); | 1161 | EXPORT_SYMBOL_GPL(tpm_register_hardware); |
602 | 1162 | ||
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index dec0224b4478..050ced247f68 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -42,18 +42,30 @@ extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr, | |||
42 | char *); | 42 | char *); |
43 | extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr, | 43 | extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr, |
44 | char *); | 44 | char *); |
45 | extern ssize_t tpm_show_caps_1_2(struct device *, struct device_attribute *attr, | ||
46 | char *); | ||
45 | extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr, | 47 | extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr, |
46 | const char *, size_t); | 48 | const char *, size_t); |
49 | extern ssize_t tpm_show_enabled(struct device *, struct device_attribute *attr, | ||
50 | char *); | ||
51 | extern ssize_t tpm_show_active(struct device *, struct device_attribute *attr, | ||
52 | char *); | ||
53 | extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr, | ||
54 | char *); | ||
55 | extern ssize_t tpm_show_temp_deactivated(struct device *, | ||
56 | struct device_attribute *attr, char *); | ||
47 | 57 | ||
48 | struct tpm_chip; | 58 | struct tpm_chip; |
49 | 59 | ||
50 | struct tpm_vendor_specific { | 60 | struct tpm_vendor_specific { |
51 | u8 req_complete_mask; | 61 | const u8 req_complete_mask; |
52 | u8 req_complete_val; | 62 | const u8 req_complete_val; |
53 | u8 req_canceled; | 63 | const u8 req_canceled; |
54 | void __iomem *iobase; /* ioremapped address */ | 64 | void __iomem *iobase; /* ioremapped address */ |
55 | unsigned long base; /* TPM base address */ | 65 | unsigned long base; /* TPM base address */ |
56 | 66 | ||
67 | int irq; | ||
68 | |||
57 | int region_size; | 69 | int region_size; |
58 | int have_region; | 70 | int have_region; |
59 | 71 | ||
@@ -63,6 +75,13 @@ struct tpm_vendor_specific { | |||
63 | u8 (*status) (struct tpm_chip *); | 75 | u8 (*status) (struct tpm_chip *); |
64 | struct miscdevice miscdev; | 76 | struct miscdevice miscdev; |
65 | struct attribute_group *attr_group; | 77 | struct attribute_group *attr_group; |
78 | struct list_head list; | ||
79 | int locality; | ||
80 | unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */ | ||
81 | unsigned long duration[3]; /* jiffies */ | ||
82 | |||
83 | wait_queue_head_t read_queue; | ||
84 | wait_queue_head_t int_queue; | ||
66 | }; | 85 | }; |
67 | 86 | ||
68 | struct tpm_chip { | 87 | struct tpm_chip { |
@@ -81,13 +100,15 @@ struct tpm_chip { | |||
81 | struct work_struct work; | 100 | struct work_struct work; |
82 | struct semaphore tpm_mutex; /* tpm is processing */ | 101 | struct semaphore tpm_mutex; /* tpm is processing */ |
83 | 102 | ||
84 | struct tpm_vendor_specific *vendor; | 103 | struct tpm_vendor_specific vendor; |
85 | 104 | ||
86 | struct dentry **bios_dir; | 105 | struct dentry **bios_dir; |
87 | 106 | ||
88 | struct list_head list; | 107 | struct list_head list; |
89 | }; | 108 | }; |
90 | 109 | ||
110 | #define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor) | ||
111 | |||
91 | static inline int tpm_read_index(int base, int index) | 112 | static inline int tpm_read_index(int base, int index) |
92 | { | 113 | { |
93 | outb(index, base); | 114 | outb(index, base); |
@@ -100,8 +121,12 @@ static inline void tpm_write_index(int base, int index, int value) | |||
100 | outb(value & 0xFF, base+1); | 121 | outb(value & 0xFF, base+1); |
101 | } | 122 | } |
102 | 123 | ||
103 | extern int tpm_register_hardware(struct device *, | 124 | extern void tpm_get_timeouts(struct tpm_chip *); |
104 | struct tpm_vendor_specific *); | 125 | extern void tpm_gen_interrupt(struct tpm_chip *); |
126 | extern void tpm_continue_selftest(struct tpm_chip *); | ||
127 | extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); | ||
128 | extern struct tpm_chip* tpm_register_hardware(struct device *, | ||
129 | const struct tpm_vendor_specific *); | ||
105 | extern int tpm_open(struct inode *, struct file *); | 130 | extern int tpm_open(struct inode *, struct file *); |
106 | extern int tpm_release(struct inode *, struct file *); | 131 | extern int tpm_release(struct inode *, struct file *); |
107 | extern ssize_t tpm_write(struct file *, const char __user *, size_t, | 132 | extern ssize_t tpm_write(struct file *, const char __user *, size_t, |
@@ -115,7 +140,7 @@ extern int tpm_pm_resume(struct device *); | |||
115 | extern struct dentry ** tpm_bios_log_setup(char *); | 140 | extern struct dentry ** tpm_bios_log_setup(char *); |
116 | extern void tpm_bios_log_teardown(struct dentry **); | 141 | extern void tpm_bios_log_teardown(struct dentry **); |
117 | #else | 142 | #else |
118 | static inline struct dentry* tpm_bios_log_setup(char *name) | 143 | static inline struct dentry ** tpm_bios_log_setup(char *name) |
119 | { | 144 | { |
120 | return NULL; | 145 | return NULL; |
121 | } | 146 | } |
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index ff3654964fe3..58a258cec153 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c | |||
@@ -47,12 +47,12 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
47 | return -EIO; | 47 | return -EIO; |
48 | 48 | ||
49 | for (i = 0; i < 6; i++) { | 49 | for (i = 0; i < 6; i++) { |
50 | status = ioread8(chip->vendor->iobase + 1); | 50 | status = ioread8(chip->vendor.iobase + 1); |
51 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 51 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
52 | dev_err(chip->dev, "error reading header\n"); | 52 | dev_err(chip->dev, "error reading header\n"); |
53 | return -EIO; | 53 | return -EIO; |
54 | } | 54 | } |
55 | *buf++ = ioread8(chip->vendor->iobase); | 55 | *buf++ = ioread8(chip->vendor.iobase); |
56 | } | 56 | } |
57 | 57 | ||
58 | /* size of the data received */ | 58 | /* size of the data received */ |
@@ -63,7 +63,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
63 | dev_err(chip->dev, | 63 | dev_err(chip->dev, |
64 | "Recv size(%d) less than available space\n", size); | 64 | "Recv size(%d) less than available space\n", size); |
65 | for (; i < size; i++) { /* clear the waiting data anyway */ | 65 | for (; i < size; i++) { /* clear the waiting data anyway */ |
66 | status = ioread8(chip->vendor->iobase + 1); | 66 | status = ioread8(chip->vendor.iobase + 1); |
67 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 67 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
68 | dev_err(chip->dev, "error reading data\n"); | 68 | dev_err(chip->dev, "error reading data\n"); |
69 | return -EIO; | 69 | return -EIO; |
@@ -74,16 +74,16 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
74 | 74 | ||
75 | /* read all the data available */ | 75 | /* read all the data available */ |
76 | for (; i < size; i++) { | 76 | for (; i < size; i++) { |
77 | status = ioread8(chip->vendor->iobase + 1); | 77 | status = ioread8(chip->vendor.iobase + 1); |
78 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 78 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
79 | dev_err(chip->dev, "error reading data\n"); | 79 | dev_err(chip->dev, "error reading data\n"); |
80 | return -EIO; | 80 | return -EIO; |
81 | } | 81 | } |
82 | *buf++ = ioread8(chip->vendor->iobase); | 82 | *buf++ = ioread8(chip->vendor.iobase); |
83 | } | 83 | } |
84 | 84 | ||
85 | /* make sure data available is gone */ | 85 | /* make sure data available is gone */ |
86 | status = ioread8(chip->vendor->iobase + 1); | 86 | status = ioread8(chip->vendor.iobase + 1); |
87 | 87 | ||
88 | if (status & ATML_STATUS_DATA_AVAIL) { | 88 | if (status & ATML_STATUS_DATA_AVAIL) { |
89 | dev_err(chip->dev, "data available is stuck\n"); | 89 | dev_err(chip->dev, "data available is stuck\n"); |
@@ -100,7 +100,7 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
100 | dev_dbg(chip->dev, "tpm_atml_send:\n"); | 100 | dev_dbg(chip->dev, "tpm_atml_send:\n"); |
101 | for (i = 0; i < count; i++) { | 101 | for (i = 0; i < count; i++) { |
102 | dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); | 102 | dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); |
103 | iowrite8(buf[i], chip->vendor->iobase); | 103 | iowrite8(buf[i], chip->vendor.iobase); |
104 | } | 104 | } |
105 | 105 | ||
106 | return count; | 106 | return count; |
@@ -108,12 +108,12 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
108 | 108 | ||
109 | static void tpm_atml_cancel(struct tpm_chip *chip) | 109 | static void tpm_atml_cancel(struct tpm_chip *chip) |
110 | { | 110 | { |
111 | iowrite8(ATML_STATUS_ABORT, chip->vendor->iobase + 1); | 111 | iowrite8(ATML_STATUS_ABORT, chip->vendor.iobase + 1); |
112 | } | 112 | } |
113 | 113 | ||
114 | static u8 tpm_atml_status(struct tpm_chip *chip) | 114 | static u8 tpm_atml_status(struct tpm_chip *chip) |
115 | { | 115 | { |
116 | return ioread8(chip->vendor->iobase + 1); | 116 | return ioread8(chip->vendor.iobase + 1); |
117 | } | 117 | } |
118 | 118 | ||
119 | static struct file_operations atmel_ops = { | 119 | static struct file_operations atmel_ops = { |
@@ -140,7 +140,7 @@ static struct attribute* atmel_attrs[] = { | |||
140 | 140 | ||
141 | static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs }; | 141 | static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs }; |
142 | 142 | ||
143 | static struct tpm_vendor_specific tpm_atmel = { | 143 | static const struct tpm_vendor_specific tpm_atmel = { |
144 | .recv = tpm_atml_recv, | 144 | .recv = tpm_atml_recv, |
145 | .send = tpm_atml_send, | 145 | .send = tpm_atml_send, |
146 | .cancel = tpm_atml_cancel, | 146 | .cancel = tpm_atml_cancel, |
@@ -159,10 +159,10 @@ static void atml_plat_remove(void) | |||
159 | struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); | 159 | struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); |
160 | 160 | ||
161 | if (chip) { | 161 | if (chip) { |
162 | if (chip->vendor->have_region) | 162 | if (chip->vendor.have_region) |
163 | atmel_release_region(chip->vendor->base, | 163 | atmel_release_region(chip->vendor.base, |
164 | chip->vendor->region_size); | 164 | chip->vendor.region_size); |
165 | atmel_put_base_addr(chip->vendor); | 165 | atmel_put_base_addr(chip->vendor.iobase); |
166 | tpm_remove_hardware(chip->dev); | 166 | tpm_remove_hardware(chip->dev); |
167 | platform_device_unregister(pdev); | 167 | platform_device_unregister(pdev); |
168 | } | 168 | } |
@@ -179,18 +179,22 @@ static struct device_driver atml_drv = { | |||
179 | static int __init init_atmel(void) | 179 | static int __init init_atmel(void) |
180 | { | 180 | { |
181 | int rc = 0; | 181 | int rc = 0; |
182 | void __iomem *iobase = NULL; | ||
183 | int have_region, region_size; | ||
184 | unsigned long base; | ||
185 | struct tpm_chip *chip; | ||
182 | 186 | ||
183 | driver_register(&atml_drv); | 187 | driver_register(&atml_drv); |
184 | 188 | ||
185 | if ((tpm_atmel.iobase = atmel_get_base_addr(&tpm_atmel)) == NULL) { | 189 | if ((iobase = atmel_get_base_addr(&base, ®ion_size)) == NULL) { |
186 | rc = -ENODEV; | 190 | rc = -ENODEV; |
187 | goto err_unreg_drv; | 191 | goto err_unreg_drv; |
188 | } | 192 | } |
189 | 193 | ||
190 | tpm_atmel.have_region = | 194 | have_region = |
191 | (atmel_request_region | 195 | (atmel_request_region |
192 | (tpm_atmel.base, tpm_atmel.region_size, | 196 | (tpm_atmel.base, region_size, "tpm_atmel0") == NULL) ? 0 : 1; |
193 | "tpm_atmel0") == NULL) ? 0 : 1; | 197 | |
194 | 198 | ||
195 | if (IS_ERR | 199 | if (IS_ERR |
196 | (pdev = | 200 | (pdev = |
@@ -199,17 +203,25 @@ static int __init init_atmel(void) | |||
199 | goto err_rel_reg; | 203 | goto err_rel_reg; |
200 | } | 204 | } |
201 | 205 | ||
202 | if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0) | 206 | if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_atmel))) { |
207 | rc = -ENODEV; | ||
203 | goto err_unreg_dev; | 208 | goto err_unreg_dev; |
209 | } | ||
210 | |||
211 | chip->vendor.iobase = iobase; | ||
212 | chip->vendor.base = base; | ||
213 | chip->vendor.have_region = have_region; | ||
214 | chip->vendor.region_size = region_size; | ||
215 | |||
204 | return 0; | 216 | return 0; |
205 | 217 | ||
206 | err_unreg_dev: | 218 | err_unreg_dev: |
207 | platform_device_unregister(pdev); | 219 | platform_device_unregister(pdev); |
208 | err_rel_reg: | 220 | err_rel_reg: |
209 | atmel_put_base_addr(&tpm_atmel); | 221 | atmel_put_base_addr(iobase); |
210 | if (tpm_atmel.have_region) | 222 | if (have_region) |
211 | atmel_release_region(tpm_atmel.base, | 223 | atmel_release_region(base, |
212 | tpm_atmel.region_size); | 224 | region_size); |
213 | err_unreg_drv: | 225 | err_unreg_drv: |
214 | driver_unregister(&atml_drv); | 226 | driver_unregister(&atml_drv); |
215 | return rc; | 227 | return rc; |
diff --git a/drivers/char/tpm/tpm_atmel.h b/drivers/char/tpm/tpm_atmel.h index d3478aaadd77..2e68eeb8a2cd 100644 --- a/drivers/char/tpm/tpm_atmel.h +++ b/drivers/char/tpm/tpm_atmel.h | |||
@@ -28,13 +28,12 @@ | |||
28 | #define atmel_request_region request_mem_region | 28 | #define atmel_request_region request_mem_region |
29 | #define atmel_release_region release_mem_region | 29 | #define atmel_release_region release_mem_region |
30 | 30 | ||
31 | static inline void atmel_put_base_addr(struct tpm_vendor_specific | 31 | static inline void atmel_put_base_addr(void __iomem *iobase) |
32 | *vendor) | ||
33 | { | 32 | { |
34 | iounmap(vendor->iobase); | 33 | iounmap(iobase); |
35 | } | 34 | } |
36 | 35 | ||
37 | static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific *vendor) | 36 | static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size) |
38 | { | 37 | { |
39 | struct device_node *dn; | 38 | struct device_node *dn; |
40 | unsigned long address, size; | 39 | unsigned long address, size; |
@@ -71,9 +70,9 @@ static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific *vendor) | |||
71 | else | 70 | else |
72 | size = reg[naddrc]; | 71 | size = reg[naddrc]; |
73 | 72 | ||
74 | vendor->base = address; | 73 | *base = address; |
75 | vendor->region_size = size; | 74 | *region_size = size; |
76 | return ioremap(vendor->base, vendor->region_size); | 75 | return ioremap(*base, *region_size); |
77 | } | 76 | } |
78 | #else | 77 | #else |
79 | #define atmel_getb(chip, offset) inb(chip->vendor->base + offset) | 78 | #define atmel_getb(chip, offset) inb(chip->vendor->base + offset) |
@@ -106,14 +105,12 @@ static int atmel_verify_tpm11(void) | |||
106 | return 0; | 105 | return 0; |
107 | } | 106 | } |
108 | 107 | ||
109 | static inline void atmel_put_base_addr(struct tpm_vendor_specific | 108 | static inline void atmel_put_base_addr(void __iomem *iobase) |
110 | *vendor) | ||
111 | { | 109 | { |
112 | } | 110 | } |
113 | 111 | ||
114 | /* Determine where to talk to device */ | 112 | /* Determine where to talk to device */ |
115 | static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific | 113 | static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size) |
116 | *vendor) | ||
117 | { | 114 | { |
118 | int lo, hi; | 115 | int lo, hi; |
119 | 116 | ||
@@ -123,9 +120,9 @@ static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific | |||
123 | lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO); | 120 | lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO); |
124 | hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI); | 121 | hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI); |
125 | 122 | ||
126 | vendor->base = (hi << 8) | lo; | 123 | *base = (hi << 8) | lo; |
127 | vendor->region_size = 2; | 124 | *region_size = 2; |
128 | 125 | ||
129 | return ioport_map(vendor->base, vendor->region_size); | 126 | return ioport_map(*base, *region_size); |
130 | } | 127 | } |
131 | #endif | 128 | #endif |
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c index 537aa45d8c67..a611972024e6 100644 --- a/drivers/char/tpm/tpm_bios.c +++ b/drivers/char/tpm/tpm_bios.c | |||
@@ -29,6 +29,11 @@ | |||
29 | #define MAX_TEXT_EVENT 1000 /* Max event string length */ | 29 | #define MAX_TEXT_EVENT 1000 /* Max event string length */ |
30 | #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ | 30 | #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ |
31 | 31 | ||
32 | enum bios_platform_class { | ||
33 | BIOS_CLIENT = 0x00, | ||
34 | BIOS_SERVER = 0x01, | ||
35 | }; | ||
36 | |||
32 | struct tpm_bios_log { | 37 | struct tpm_bios_log { |
33 | void *bios_event_log; | 38 | void *bios_event_log; |
34 | void *bios_event_log_end; | 39 | void *bios_event_log_end; |
@@ -36,9 +41,18 @@ struct tpm_bios_log { | |||
36 | 41 | ||
37 | struct acpi_tcpa { | 42 | struct acpi_tcpa { |
38 | struct acpi_table_header hdr; | 43 | struct acpi_table_header hdr; |
39 | u16 reserved; | 44 | u16 platform_class; |
40 | u32 log_max_len __attribute__ ((packed)); | 45 | union { |
41 | u32 log_start_addr __attribute__ ((packed)); | 46 | struct client_hdr { |
47 | u32 log_max_len __attribute__ ((packed)); | ||
48 | u64 log_start_addr __attribute__ ((packed)); | ||
49 | } client; | ||
50 | struct server_hdr { | ||
51 | u16 reserved; | ||
52 | u64 log_max_len __attribute__ ((packed)); | ||
53 | u64 log_start_addr __attribute__ ((packed)); | ||
54 | } server; | ||
55 | }; | ||
42 | }; | 56 | }; |
43 | 57 | ||
44 | struct tcpa_event { | 58 | struct tcpa_event { |
@@ -91,6 +105,12 @@ static const char* tcpa_event_type_strings[] = { | |||
91 | "Non-Host Info" | 105 | "Non-Host Info" |
92 | }; | 106 | }; |
93 | 107 | ||
108 | struct tcpa_pc_event { | ||
109 | u32 event_id; | ||
110 | u32 event_size; | ||
111 | u8 event_data[0]; | ||
112 | }; | ||
113 | |||
94 | enum tcpa_pc_event_ids { | 114 | enum tcpa_pc_event_ids { |
95 | SMBIOS = 1, | 115 | SMBIOS = 1, |
96 | BIS_CERT, | 116 | BIS_CERT, |
@@ -100,14 +120,15 @@ enum tcpa_pc_event_ids { | |||
100 | NVRAM, | 120 | NVRAM, |
101 | OPTION_ROM_EXEC, | 121 | OPTION_ROM_EXEC, |
102 | OPTION_ROM_CONFIG, | 122 | OPTION_ROM_CONFIG, |
103 | OPTION_ROM_MICROCODE, | 123 | OPTION_ROM_MICROCODE = 10, |
104 | S_CRTM_VERSION, | 124 | S_CRTM_VERSION, |
105 | S_CRTM_CONTENTS, | 125 | S_CRTM_CONTENTS, |
106 | POST_CONTENTS, | 126 | POST_CONTENTS, |
127 | HOST_TABLE_OF_DEVICES, | ||
107 | }; | 128 | }; |
108 | 129 | ||
109 | static const char* tcpa_pc_event_id_strings[] = { | 130 | static const char* tcpa_pc_event_id_strings[] = { |
110 | "" | 131 | "", |
111 | "SMBIOS", | 132 | "SMBIOS", |
112 | "BIS Certificate", | 133 | "BIS Certificate", |
113 | "POST BIOS ", | 134 | "POST BIOS ", |
@@ -116,10 +137,12 @@ static const char* tcpa_pc_event_id_strings[] = { | |||
116 | "NVRAM", | 137 | "NVRAM", |
117 | "Option ROM", | 138 | "Option ROM", |
118 | "Option ROM config", | 139 | "Option ROM config", |
119 | "Option ROM microcode", | 140 | "", |
141 | "Option ROM microcode ", | ||
120 | "S-CRTM Version", | 142 | "S-CRTM Version", |
121 | "S-CRTM Contents", | 143 | "S-CRTM Contents ", |
122 | "S-CRTM POST Contents", | 144 | "POST Contents ", |
145 | "Table of Devices", | ||
123 | }; | 146 | }; |
124 | 147 | ||
125 | /* returns pointer to start of pos. entry of tcg log */ | 148 | /* returns pointer to start of pos. entry of tcg log */ |
@@ -191,7 +214,7 @@ static int get_event_name(char *dest, struct tcpa_event *event, | |||
191 | const char *name = ""; | 214 | const char *name = ""; |
192 | char data[40] = ""; | 215 | char data[40] = ""; |
193 | int i, n_len = 0, d_len = 0; | 216 | int i, n_len = 0, d_len = 0; |
194 | u32 event_id; | 217 | struct tcpa_pc_event *pc_event; |
195 | 218 | ||
196 | switch(event->event_type) { | 219 | switch(event->event_type) { |
197 | case PREBOOT: | 220 | case PREBOOT: |
@@ -220,31 +243,32 @@ static int get_event_name(char *dest, struct tcpa_event *event, | |||
220 | } | 243 | } |
221 | break; | 244 | break; |
222 | case EVENT_TAG: | 245 | case EVENT_TAG: |
223 | event_id = be32_to_cpu(*((u32 *)event_entry)); | 246 | pc_event = (struct tcpa_pc_event *)event_entry; |
224 | 247 | ||
225 | /* ToDo Row data -> Base64 */ | 248 | /* ToDo Row data -> Base64 */ |
226 | 249 | ||
227 | switch (event_id) { | 250 | switch (pc_event->event_id) { |
228 | case SMBIOS: | 251 | case SMBIOS: |
229 | case BIS_CERT: | 252 | case BIS_CERT: |
230 | case CMOS: | 253 | case CMOS: |
231 | case NVRAM: | 254 | case NVRAM: |
232 | case OPTION_ROM_EXEC: | 255 | case OPTION_ROM_EXEC: |
233 | case OPTION_ROM_CONFIG: | 256 | case OPTION_ROM_CONFIG: |
234 | case OPTION_ROM_MICROCODE: | ||
235 | case S_CRTM_VERSION: | 257 | case S_CRTM_VERSION: |
236 | case S_CRTM_CONTENTS: | 258 | name = tcpa_pc_event_id_strings[pc_event->event_id]; |
237 | case POST_CONTENTS: | ||
238 | name = tcpa_pc_event_id_strings[event_id]; | ||
239 | n_len = strlen(name); | 259 | n_len = strlen(name); |
240 | break; | 260 | break; |
261 | /* hash data */ | ||
241 | case POST_BIOS_ROM: | 262 | case POST_BIOS_ROM: |
242 | case ESCD: | 263 | case ESCD: |
243 | name = tcpa_pc_event_id_strings[event_id]; | 264 | case OPTION_ROM_MICROCODE: |
265 | case S_CRTM_CONTENTS: | ||
266 | case POST_CONTENTS: | ||
267 | name = tcpa_pc_event_id_strings[pc_event->event_id]; | ||
244 | n_len = strlen(name); | 268 | n_len = strlen(name); |
245 | for (i = 0; i < 20; i++) | 269 | for (i = 0; i < 20; i++) |
246 | d_len += sprintf(data, "%02x", | 270 | d_len += sprintf(&data[2*i], "%02x", |
247 | event_entry[8 + i]); | 271 | pc_event->event_data[i]); |
248 | break; | 272 | break; |
249 | default: | 273 | default: |
250 | break; | 274 | break; |
@@ -260,52 +284,13 @@ static int get_event_name(char *dest, struct tcpa_event *event, | |||
260 | 284 | ||
261 | static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) | 285 | static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) |
262 | { | 286 | { |
287 | struct tcpa_event *event = v; | ||
288 | char *data = v; | ||
289 | int i; | ||
263 | 290 | ||
264 | char *eventname; | 291 | for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++) |
265 | char data[4]; | ||
266 | u32 help; | ||
267 | int i, len; | ||
268 | struct tcpa_event *event = (struct tcpa_event *) v; | ||
269 | unsigned char *event_entry = | ||
270 | (unsigned char *) (v + sizeof(struct tcpa_event)); | ||
271 | |||
272 | eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL); | ||
273 | if (!eventname) { | ||
274 | printk(KERN_ERR "%s: ERROR - No Memory for event name\n ", | ||
275 | __func__); | ||
276 | return -ENOMEM; | ||
277 | } | ||
278 | |||
279 | /* 1st: PCR used is in little-endian format (4 bytes) */ | ||
280 | help = le32_to_cpu(event->pcr_index); | ||
281 | memcpy(data, &help, 4); | ||
282 | for (i = 0; i < 4; i++) | ||
283 | seq_putc(m, data[i]); | ||
284 | |||
285 | /* 2nd: SHA1 (20 bytes) */ | ||
286 | for (i = 0; i < 20; i++) | ||
287 | seq_putc(m, event->pcr_value[i]); | ||
288 | |||
289 | /* 3rd: event type identifier (4 bytes) */ | ||
290 | help = le32_to_cpu(event->event_type); | ||
291 | memcpy(data, &help, 4); | ||
292 | for (i = 0; i < 4; i++) | ||
293 | seq_putc(m, data[i]); | 292 | seq_putc(m, data[i]); |
294 | 293 | ||
295 | len = 0; | ||
296 | |||
297 | len += get_event_name(eventname, event, event_entry); | ||
298 | |||
299 | /* 4th: filename <= 255 + \'0' delimiter */ | ||
300 | if (len > TCG_EVENT_NAME_LEN_MAX) | ||
301 | len = TCG_EVENT_NAME_LEN_MAX; | ||
302 | |||
303 | for (i = 0; i < len; i++) | ||
304 | seq_putc(m, eventname[i]); | ||
305 | |||
306 | /* 5th: delimiter */ | ||
307 | seq_putc(m, '\0'); | ||
308 | |||
309 | return 0; | 294 | return 0; |
310 | } | 295 | } |
311 | 296 | ||
@@ -353,6 +338,7 @@ static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v) | |||
353 | /* 4th: eventname <= max + \'0' delimiter */ | 338 | /* 4th: eventname <= max + \'0' delimiter */ |
354 | seq_printf(m, " %s\n", eventname); | 339 | seq_printf(m, " %s\n", eventname); |
355 | 340 | ||
341 | kfree(eventname); | ||
356 | return 0; | 342 | return 0; |
357 | } | 343 | } |
358 | 344 | ||
@@ -376,6 +362,7 @@ static int read_log(struct tpm_bios_log *log) | |||
376 | struct acpi_tcpa *buff; | 362 | struct acpi_tcpa *buff; |
377 | acpi_status status; | 363 | acpi_status status; |
378 | struct acpi_table_header *virt; | 364 | struct acpi_table_header *virt; |
365 | u64 len, start; | ||
379 | 366 | ||
380 | if (log->bios_event_log != NULL) { | 367 | if (log->bios_event_log != NULL) { |
381 | printk(KERN_ERR | 368 | printk(KERN_ERR |
@@ -396,27 +383,37 @@ static int read_log(struct tpm_bios_log *log) | |||
396 | return -EIO; | 383 | return -EIO; |
397 | } | 384 | } |
398 | 385 | ||
399 | if (buff->log_max_len == 0) { | 386 | switch(buff->platform_class) { |
387 | case BIOS_SERVER: | ||
388 | len = buff->server.log_max_len; | ||
389 | start = buff->server.log_start_addr; | ||
390 | break; | ||
391 | case BIOS_CLIENT: | ||
392 | default: | ||
393 | len = buff->client.log_max_len; | ||
394 | start = buff->client.log_start_addr; | ||
395 | break; | ||
396 | } | ||
397 | if (!len) { | ||
400 | printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__); | 398 | printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__); |
401 | return -EIO; | 399 | return -EIO; |
402 | } | 400 | } |
403 | 401 | ||
404 | /* malloc EventLog space */ | 402 | /* malloc EventLog space */ |
405 | log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL); | 403 | log->bios_event_log = kmalloc(len, GFP_KERNEL); |
406 | if (!log->bios_event_log) { | 404 | if (!log->bios_event_log) { |
407 | printk | 405 | printk("%s: ERROR - Not enough Memory for BIOS measurements\n", |
408 | ("%s: ERROR - Not enough Memory for BIOS measurements\n", | 406 | __func__); |
409 | __func__); | ||
410 | return -ENOMEM; | 407 | return -ENOMEM; |
411 | } | 408 | } |
412 | 409 | ||
413 | log->bios_event_log_end = log->bios_event_log + buff->log_max_len; | 410 | log->bios_event_log_end = log->bios_event_log + len; |
414 | 411 | ||
415 | acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, (void *) &virt); | 412 | acpi_os_map_memory(start, len, (void *) &virt); |
416 | 413 | ||
417 | memcpy(log->bios_event_log, virt, buff->log_max_len); | 414 | memcpy(log->bios_event_log, virt, len); |
418 | 415 | ||
419 | acpi_os_unmap_memory(virt, buff->log_max_len); | 416 | acpi_os_unmap_memory(virt, len); |
420 | return 0; | 417 | return 0; |
421 | } | 418 | } |
422 | 419 | ||
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index 24095f6ee6da..adfff21beb21 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c | |||
@@ -15,6 +15,7 @@ | |||
15 | * License. | 15 | * License. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/init.h> | ||
18 | #include <linux/pnp.h> | 19 | #include <linux/pnp.h> |
19 | #include "tpm.h" | 20 | #include "tpm.h" |
20 | 21 | ||
@@ -104,7 +105,7 @@ static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo) | |||
104 | 105 | ||
105 | if (clear_wrfifo) { | 106 | if (clear_wrfifo) { |
106 | for (i = 0; i < 4096; i++) { | 107 | for (i = 0; i < 4096; i++) { |
107 | status = inb(chip->vendor->base + WRFIFO); | 108 | status = inb(chip->vendor.base + WRFIFO); |
108 | if (status == 0xff) { | 109 | if (status == 0xff) { |
109 | if (check == 5) | 110 | if (check == 5) |
110 | break; | 111 | break; |
@@ -124,8 +125,8 @@ static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo) | |||
124 | */ | 125 | */ |
125 | i = 0; | 126 | i = 0; |
126 | do { | 127 | do { |
127 | status = inb(chip->vendor->base + RDFIFO); | 128 | status = inb(chip->vendor.base + RDFIFO); |
128 | status = inb(chip->vendor->base + STAT); | 129 | status = inb(chip->vendor.base + STAT); |
129 | i++; | 130 | i++; |
130 | if (i == TPM_MAX_TRIES) | 131 | if (i == TPM_MAX_TRIES) |
131 | return -EIO; | 132 | return -EIO; |
@@ -138,7 +139,7 @@ static int wait(struct tpm_chip *chip, int wait_for_bit) | |||
138 | int status; | 139 | int status; |
139 | int i; | 140 | int i; |
140 | for (i = 0; i < TPM_MAX_TRIES; i++) { | 141 | for (i = 0; i < TPM_MAX_TRIES; i++) { |
141 | status = inb(chip->vendor->base + STAT); | 142 | status = inb(chip->vendor.base + STAT); |
142 | /* check the status-register if wait_for_bit is set */ | 143 | /* check the status-register if wait_for_bit is set */ |
143 | if (status & 1 << wait_for_bit) | 144 | if (status & 1 << wait_for_bit) |
144 | break; | 145 | break; |
@@ -157,7 +158,7 @@ static int wait(struct tpm_chip *chip, int wait_for_bit) | |||
157 | static void wait_and_send(struct tpm_chip *chip, u8 sendbyte) | 158 | static void wait_and_send(struct tpm_chip *chip, u8 sendbyte) |
158 | { | 159 | { |
159 | wait(chip, STAT_XFE); | 160 | wait(chip, STAT_XFE); |
160 | outb(sendbyte, chip->vendor->base + WRFIFO); | 161 | outb(sendbyte, chip->vendor.base + WRFIFO); |
161 | } | 162 | } |
162 | 163 | ||
163 | /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more | 164 | /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more |
@@ -204,7 +205,7 @@ recv_begin: | |||
204 | ret = wait(chip, STAT_RDA); | 205 | ret = wait(chip, STAT_RDA); |
205 | if (ret) | 206 | if (ret) |
206 | return -EIO; | 207 | return -EIO; |
207 | buf[i] = inb(chip->vendor->base + RDFIFO); | 208 | buf[i] = inb(chip->vendor.base + RDFIFO); |
208 | } | 209 | } |
209 | 210 | ||
210 | if (buf[0] != TPM_VL_VER) { | 211 | if (buf[0] != TPM_VL_VER) { |
@@ -219,7 +220,7 @@ recv_begin: | |||
219 | 220 | ||
220 | for (i = 0; i < size; i++) { | 221 | for (i = 0; i < size; i++) { |
221 | wait(chip, STAT_RDA); | 222 | wait(chip, STAT_RDA); |
222 | buf[i] = inb(chip->vendor->base + RDFIFO); | 223 | buf[i] = inb(chip->vendor.base + RDFIFO); |
223 | } | 224 | } |
224 | 225 | ||
225 | if ((size == 0x6D00) && (buf[1] == 0x80)) { | 226 | if ((size == 0x6D00) && (buf[1] == 0x80)) { |
@@ -268,7 +269,7 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count) | |||
268 | u8 count_high, count_low, count_4, count_3, count_2, count_1; | 269 | u8 count_high, count_low, count_4, count_3, count_2, count_1; |
269 | 270 | ||
270 | /* Disabling Reset, LP and IRQC */ | 271 | /* Disabling Reset, LP and IRQC */ |
271 | outb(RESET_LP_IRQC_DISABLE, chip->vendor->base + CMD); | 272 | outb(RESET_LP_IRQC_DISABLE, chip->vendor.base + CMD); |
272 | 273 | ||
273 | ret = empty_fifo(chip, 1); | 274 | ret = empty_fifo(chip, 1); |
274 | if (ret) { | 275 | if (ret) { |
@@ -319,7 +320,7 @@ static void tpm_inf_cancel(struct tpm_chip *chip) | |||
319 | 320 | ||
320 | static u8 tpm_inf_status(struct tpm_chip *chip) | 321 | static u8 tpm_inf_status(struct tpm_chip *chip) |
321 | { | 322 | { |
322 | return inb(chip->vendor->base + STAT); | 323 | return inb(chip->vendor.base + STAT); |
323 | } | 324 | } |
324 | 325 | ||
325 | static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); | 326 | static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); |
@@ -346,7 +347,7 @@ static struct file_operations inf_ops = { | |||
346 | .release = tpm_release, | 347 | .release = tpm_release, |
347 | }; | 348 | }; |
348 | 349 | ||
349 | static struct tpm_vendor_specific tpm_inf = { | 350 | static const struct tpm_vendor_specific tpm_inf = { |
350 | .recv = tpm_inf_recv, | 351 | .recv = tpm_inf_recv, |
351 | .send = tpm_inf_send, | 352 | .send = tpm_inf_send, |
352 | .cancel = tpm_inf_cancel, | 353 | .cancel = tpm_inf_cancel, |
@@ -375,6 +376,7 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
375 | int version[2]; | 376 | int version[2]; |
376 | int productid[2]; | 377 | int productid[2]; |
377 | char chipname[20]; | 378 | char chipname[20]; |
379 | struct tpm_chip *chip; | ||
378 | 380 | ||
379 | /* read IO-ports through PnP */ | 381 | /* read IO-ports through PnP */ |
380 | if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && | 382 | if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && |
@@ -395,14 +397,13 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
395 | goto err_last; | 397 | goto err_last; |
396 | } | 398 | } |
397 | /* publish my base address and request region */ | 399 | /* publish my base address and request region */ |
398 | tpm_inf.base = TPM_INF_BASE; | ||
399 | if (request_region | 400 | if (request_region |
400 | (tpm_inf.base, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) { | 401 | (TPM_INF_BASE, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) { |
401 | rc = -EINVAL; | 402 | rc = -EINVAL; |
402 | goto err_last; | 403 | goto err_last; |
403 | } | 404 | } |
404 | if (request_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN, | 405 | if (request_region |
405 | "tpm_infineon0") == NULL) { | 406 | (TPM_INF_ADDR, TPM_INF_ADDR_LEN, "tpm_infineon0") == NULL) { |
406 | rc = -EINVAL; | 407 | rc = -EINVAL; |
407 | goto err_last; | 408 | goto err_last; |
408 | } | 409 | } |
@@ -442,9 +443,9 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
442 | 443 | ||
443 | /* configure TPM with IO-ports */ | 444 | /* configure TPM with IO-ports */ |
444 | outb(IOLIMH, TPM_INF_ADDR); | 445 | outb(IOLIMH, TPM_INF_ADDR); |
445 | outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA); | 446 | outb(((TPM_INF_BASE >> 8) & 0xff), TPM_INF_DATA); |
446 | outb(IOLIML, TPM_INF_ADDR); | 447 | outb(IOLIML, TPM_INF_ADDR); |
447 | outb((tpm_inf.base & 0xff), TPM_INF_DATA); | 448 | outb((TPM_INF_BASE & 0xff), TPM_INF_DATA); |
448 | 449 | ||
449 | /* control if IO-ports are set correctly */ | 450 | /* control if IO-ports are set correctly */ |
450 | outb(IOLIMH, TPM_INF_ADDR); | 451 | outb(IOLIMH, TPM_INF_ADDR); |
@@ -452,10 +453,10 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
452 | outb(IOLIML, TPM_INF_ADDR); | 453 | outb(IOLIML, TPM_INF_ADDR); |
453 | iol = inb(TPM_INF_DATA); | 454 | iol = inb(TPM_INF_DATA); |
454 | 455 | ||
455 | if ((ioh << 8 | iol) != tpm_inf.base) { | 456 | if ((ioh << 8 | iol) != TPM_INF_BASE) { |
456 | dev_err(&dev->dev, | 457 | dev_err(&dev->dev, |
457 | "Could not set IO-ports to 0x%lx\n", | 458 | "Could not set IO-ports to 0x%x\n", |
458 | tpm_inf.base); | 459 | TPM_INF_BASE); |
459 | rc = -EIO; | 460 | rc = -EIO; |
460 | goto err_release_region; | 461 | goto err_release_region; |
461 | } | 462 | } |
@@ -466,15 +467,15 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
466 | outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR); | 467 | outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR); |
467 | 468 | ||
468 | /* disable RESET, LP and IRQC */ | 469 | /* disable RESET, LP and IRQC */ |
469 | outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD); | 470 | outb(RESET_LP_IRQC_DISABLE, TPM_INF_BASE + CMD); |
470 | 471 | ||
471 | /* Finally, we're done, print some infos */ | 472 | /* Finally, we're done, print some infos */ |
472 | dev_info(&dev->dev, "TPM found: " | 473 | dev_info(&dev->dev, "TPM found: " |
473 | "config base 0x%x, " | 474 | "config base 0x%x, " |
474 | "io base 0x%x, " | 475 | "io base 0x%x, " |
475 | "chip version %02x%02x, " | 476 | "chip version 0x%02x%02x, " |
476 | "vendor id %x%x (Infineon), " | 477 | "vendor id 0x%x%x (Infineon), " |
477 | "product id %02x%02x" | 478 | "product id 0x%02x%02x" |
478 | "%s\n", | 479 | "%s\n", |
479 | TPM_INF_ADDR, | 480 | TPM_INF_ADDR, |
480 | TPM_INF_BASE, | 481 | TPM_INF_BASE, |
@@ -482,11 +483,10 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
482 | vendorid[0], vendorid[1], | 483 | vendorid[0], vendorid[1], |
483 | productid[0], productid[1], chipname); | 484 | productid[0], productid[1], chipname); |
484 | 485 | ||
485 | rc = tpm_register_hardware(&dev->dev, &tpm_inf); | 486 | if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) { |
486 | if (rc < 0) { | ||
487 | rc = -ENODEV; | ||
488 | goto err_release_region; | 487 | goto err_release_region; |
489 | } | 488 | } |
489 | chip->vendor.base = TPM_INF_BASE; | ||
490 | return 0; | 490 | return 0; |
491 | } else { | 491 | } else { |
492 | rc = -ENODEV; | 492 | rc = -ENODEV; |
@@ -494,7 +494,7 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
494 | } | 494 | } |
495 | 495 | ||
496 | err_release_region: | 496 | err_release_region: |
497 | release_region(tpm_inf.base, TPM_INF_PORT_LEN); | 497 | release_region(TPM_INF_BASE, TPM_INF_PORT_LEN); |
498 | release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN); | 498 | release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN); |
499 | 499 | ||
500 | err_last: | 500 | err_last: |
@@ -506,7 +506,8 @@ static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev) | |||
506 | struct tpm_chip *chip = pnp_get_drvdata(dev); | 506 | struct tpm_chip *chip = pnp_get_drvdata(dev); |
507 | 507 | ||
508 | if (chip) { | 508 | if (chip) { |
509 | release_region(chip->vendor->base, TPM_INF_PORT_LEN); | 509 | release_region(TPM_INF_BASE, TPM_INF_PORT_LEN); |
510 | release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN); | ||
510 | tpm_remove_hardware(chip->dev); | 511 | tpm_remove_hardware(chip->dev); |
511 | } | 512 | } |
512 | } | 513 | } |
@@ -520,7 +521,7 @@ static struct pnp_driver tpm_inf_pnp = { | |||
520 | }, | 521 | }, |
521 | .id_table = tpm_pnp_tbl, | 522 | .id_table = tpm_pnp_tbl, |
522 | .probe = tpm_inf_pnp_probe, | 523 | .probe = tpm_inf_pnp_probe, |
523 | .remove = tpm_inf_pnp_remove, | 524 | .remove = __devexit_p(tpm_inf_pnp_remove), |
524 | }; | 525 | }; |
525 | 526 | ||
526 | static int __init init_inf(void) | 527 | static int __init init_inf(void) |
@@ -538,5 +539,5 @@ module_exit(cleanup_inf); | |||
538 | 539 | ||
539 | MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>"); | 540 | MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>"); |
540 | MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); | 541 | MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); |
541 | MODULE_VERSION("1.7"); | 542 | MODULE_VERSION("1.8"); |
542 | MODULE_LICENSE("GPL"); | 543 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c index 680a8e331887..4c8bc06c7d95 100644 --- a/drivers/char/tpm/tpm_nsc.c +++ b/drivers/char/tpm/tpm_nsc.c | |||
@@ -71,7 +71,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data) | |||
71 | unsigned long stop; | 71 | unsigned long stop; |
72 | 72 | ||
73 | /* status immediately available check */ | 73 | /* status immediately available check */ |
74 | *data = inb(chip->vendor->base + NSC_STATUS); | 74 | *data = inb(chip->vendor.base + NSC_STATUS); |
75 | if ((*data & mask) == val) | 75 | if ((*data & mask) == val) |
76 | return 0; | 76 | return 0; |
77 | 77 | ||
@@ -79,7 +79,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data) | |||
79 | stop = jiffies + 10 * HZ; | 79 | stop = jiffies + 10 * HZ; |
80 | do { | 80 | do { |
81 | msleep(TPM_TIMEOUT); | 81 | msleep(TPM_TIMEOUT); |
82 | *data = inb(chip->vendor->base + 1); | 82 | *data = inb(chip->vendor.base + 1); |
83 | if ((*data & mask) == val) | 83 | if ((*data & mask) == val) |
84 | return 0; | 84 | return 0; |
85 | } | 85 | } |
@@ -94,9 +94,9 @@ static int nsc_wait_for_ready(struct tpm_chip *chip) | |||
94 | unsigned long stop; | 94 | unsigned long stop; |
95 | 95 | ||
96 | /* status immediately available check */ | 96 | /* status immediately available check */ |
97 | status = inb(chip->vendor->base + NSC_STATUS); | 97 | status = inb(chip->vendor.base + NSC_STATUS); |
98 | if (status & NSC_STATUS_OBF) | 98 | if (status & NSC_STATUS_OBF) |
99 | status = inb(chip->vendor->base + NSC_DATA); | 99 | status = inb(chip->vendor.base + NSC_DATA); |
100 | if (status & NSC_STATUS_RDY) | 100 | if (status & NSC_STATUS_RDY) |
101 | return 0; | 101 | return 0; |
102 | 102 | ||
@@ -104,9 +104,9 @@ static int nsc_wait_for_ready(struct tpm_chip *chip) | |||
104 | stop = jiffies + 100; | 104 | stop = jiffies + 100; |
105 | do { | 105 | do { |
106 | msleep(TPM_TIMEOUT); | 106 | msleep(TPM_TIMEOUT); |
107 | status = inb(chip->vendor->base + NSC_STATUS); | 107 | status = inb(chip->vendor.base + NSC_STATUS); |
108 | if (status & NSC_STATUS_OBF) | 108 | if (status & NSC_STATUS_OBF) |
109 | status = inb(chip->vendor->base + NSC_DATA); | 109 | status = inb(chip->vendor.base + NSC_DATA); |
110 | if (status & NSC_STATUS_RDY) | 110 | if (status & NSC_STATUS_RDY) |
111 | return 0; | 111 | return 0; |
112 | } | 112 | } |
@@ -132,7 +132,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) | |||
132 | return -EIO; | 132 | return -EIO; |
133 | } | 133 | } |
134 | if ((data = | 134 | if ((data = |
135 | inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) { | 135 | inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) { |
136 | dev_err(chip->dev, "not in normal mode (0x%x)\n", | 136 | dev_err(chip->dev, "not in normal mode (0x%x)\n", |
137 | data); | 137 | data); |
138 | return -EIO; | 138 | return -EIO; |
@@ -148,7 +148,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) | |||
148 | } | 148 | } |
149 | if (data & NSC_STATUS_F0) | 149 | if (data & NSC_STATUS_F0) |
150 | break; | 150 | break; |
151 | *p = inb(chip->vendor->base + NSC_DATA); | 151 | *p = inb(chip->vendor.base + NSC_DATA); |
152 | } | 152 | } |
153 | 153 | ||
154 | if ((data & NSC_STATUS_F0) == 0 && | 154 | if ((data & NSC_STATUS_F0) == 0 && |
@@ -156,7 +156,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) | |||
156 | dev_err(chip->dev, "F0 not set\n"); | 156 | dev_err(chip->dev, "F0 not set\n"); |
157 | return -EIO; | 157 | return -EIO; |
158 | } | 158 | } |
159 | if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) { | 159 | if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) { |
160 | dev_err(chip->dev, | 160 | dev_err(chip->dev, |
161 | "expected end of command(0x%x)\n", data); | 161 | "expected end of command(0x%x)\n", data); |
162 | return -EIO; | 162 | return -EIO; |
@@ -182,7 +182,7 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count) | |||
182 | * fix it. Not sure why this is needed, we followed the flow | 182 | * fix it. Not sure why this is needed, we followed the flow |
183 | * chart in the manual to the letter. | 183 | * chart in the manual to the letter. |
184 | */ | 184 | */ |
185 | outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND); | 185 | outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND); |
186 | 186 | ||
187 | if (nsc_wait_for_ready(chip) != 0) | 187 | if (nsc_wait_for_ready(chip) != 0) |
188 | return -EIO; | 188 | return -EIO; |
@@ -192,7 +192,7 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count) | |||
192 | return -EIO; | 192 | return -EIO; |
193 | } | 193 | } |
194 | 194 | ||
195 | outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND); | 195 | outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND); |
196 | if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) { | 196 | if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) { |
197 | dev_err(chip->dev, "IBR timeout\n"); | 197 | dev_err(chip->dev, "IBR timeout\n"); |
198 | return -EIO; | 198 | return -EIO; |
@@ -204,26 +204,26 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count) | |||
204 | "IBF timeout (while writing data)\n"); | 204 | "IBF timeout (while writing data)\n"); |
205 | return -EIO; | 205 | return -EIO; |
206 | } | 206 | } |
207 | outb(buf[i], chip->vendor->base + NSC_DATA); | 207 | outb(buf[i], chip->vendor.base + NSC_DATA); |
208 | } | 208 | } |
209 | 209 | ||
210 | if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { | 210 | if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { |
211 | dev_err(chip->dev, "IBF timeout\n"); | 211 | dev_err(chip->dev, "IBF timeout\n"); |
212 | return -EIO; | 212 | return -EIO; |
213 | } | 213 | } |
214 | outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND); | 214 | outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND); |
215 | 215 | ||
216 | return count; | 216 | return count; |
217 | } | 217 | } |
218 | 218 | ||
219 | static void tpm_nsc_cancel(struct tpm_chip *chip) | 219 | static void tpm_nsc_cancel(struct tpm_chip *chip) |
220 | { | 220 | { |
221 | outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND); | 221 | outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND); |
222 | } | 222 | } |
223 | 223 | ||
224 | static u8 tpm_nsc_status(struct tpm_chip *chip) | 224 | static u8 tpm_nsc_status(struct tpm_chip *chip) |
225 | { | 225 | { |
226 | return inb(chip->vendor->base + NSC_STATUS); | 226 | return inb(chip->vendor.base + NSC_STATUS); |
227 | } | 227 | } |
228 | 228 | ||
229 | static struct file_operations nsc_ops = { | 229 | static struct file_operations nsc_ops = { |
@@ -250,7 +250,7 @@ static struct attribute * nsc_attrs[] = { | |||
250 | 250 | ||
251 | static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs }; | 251 | static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs }; |
252 | 252 | ||
253 | static struct tpm_vendor_specific tpm_nsc = { | 253 | static const struct tpm_vendor_specific tpm_nsc = { |
254 | .recv = tpm_nsc_recv, | 254 | .recv = tpm_nsc_recv, |
255 | .send = tpm_nsc_send, | 255 | .send = tpm_nsc_send, |
256 | .cancel = tpm_nsc_cancel, | 256 | .cancel = tpm_nsc_cancel, |
@@ -268,7 +268,7 @@ static void __devexit tpm_nsc_remove(struct device *dev) | |||
268 | { | 268 | { |
269 | struct tpm_chip *chip = dev_get_drvdata(dev); | 269 | struct tpm_chip *chip = dev_get_drvdata(dev); |
270 | if ( chip ) { | 270 | if ( chip ) { |
271 | release_region(chip->vendor->base, 2); | 271 | release_region(chip->vendor.base, 2); |
272 | tpm_remove_hardware(chip->dev); | 272 | tpm_remove_hardware(chip->dev); |
273 | } | 273 | } |
274 | } | 274 | } |
@@ -286,7 +286,8 @@ static int __init init_nsc(void) | |||
286 | int rc = 0; | 286 | int rc = 0; |
287 | int lo, hi; | 287 | int lo, hi; |
288 | int nscAddrBase = TPM_ADDR; | 288 | int nscAddrBase = TPM_ADDR; |
289 | 289 | struct tpm_chip *chip; | |
290 | unsigned long base; | ||
290 | 291 | ||
291 | /* verify that it is a National part (SID) */ | 292 | /* verify that it is a National part (SID) */ |
292 | if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) { | 293 | if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) { |
@@ -300,7 +301,7 @@ static int __init init_nsc(void) | |||
300 | 301 | ||
301 | hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI); | 302 | hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI); |
302 | lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO); | 303 | lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO); |
303 | tpm_nsc.base = (hi<<8) | lo; | 304 | base = (hi<<8) | lo; |
304 | 305 | ||
305 | /* enable the DPM module */ | 306 | /* enable the DPM module */ |
306 | tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01); | 307 | tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01); |
@@ -320,13 +321,15 @@ static int __init init_nsc(void) | |||
320 | if ((rc = platform_device_register(pdev)) < 0) | 321 | if ((rc = platform_device_register(pdev)) < 0) |
321 | goto err_free_dev; | 322 | goto err_free_dev; |
322 | 323 | ||
323 | if (request_region(tpm_nsc.base, 2, "tpm_nsc0") == NULL ) { | 324 | if (request_region(base, 2, "tpm_nsc0") == NULL ) { |
324 | rc = -EBUSY; | 325 | rc = -EBUSY; |
325 | goto err_unreg_dev; | 326 | goto err_unreg_dev; |
326 | } | 327 | } |
327 | 328 | ||
328 | if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0) | 329 | if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) { |
330 | rc = -ENODEV; | ||
329 | goto err_rel_reg; | 331 | goto err_rel_reg; |
332 | } | ||
330 | 333 | ||
331 | dev_dbg(&pdev->dev, "NSC TPM detected\n"); | 334 | dev_dbg(&pdev->dev, "NSC TPM detected\n"); |
332 | dev_dbg(&pdev->dev, | 335 | dev_dbg(&pdev->dev, |
@@ -361,10 +364,12 @@ static int __init init_nsc(void) | |||
361 | "NSC TPM revision %d\n", | 364 | "NSC TPM revision %d\n", |
362 | tpm_read_index(nscAddrBase, 0x27) & 0x1F); | 365 | tpm_read_index(nscAddrBase, 0x27) & 0x1F); |
363 | 366 | ||
367 | chip->vendor.base = base; | ||
368 | |||
364 | return 0; | 369 | return 0; |
365 | 370 | ||
366 | err_rel_reg: | 371 | err_rel_reg: |
367 | release_region(tpm_nsc.base, 2); | 372 | release_region(base, 2); |
368 | err_unreg_dev: | 373 | err_unreg_dev: |
369 | platform_device_unregister(pdev); | 374 | platform_device_unregister(pdev); |
370 | err_free_dev: | 375 | err_free_dev: |
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c new file mode 100644 index 000000000000..8ea70625f7ea --- /dev/null +++ b/drivers/char/tpm/tpm_tis.c | |||
@@ -0,0 +1,665 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005, 2006 IBM Corporation | ||
3 | * | ||
4 | * Authors: | ||
5 | * Leendert van Doorn <leendert@watson.ibm.com> | ||
6 | * Kylene Hall <kjhall@us.ibm.com> | ||
7 | * | ||
8 | * Device driver for TCG/TCPA TPM (trusted platform module). | ||
9 | * Specifications at www.trustedcomputinggroup.org | ||
10 | * | ||
11 | * This device driver implements the TPM interface as defined in | ||
12 | * the TCG TPM Interface Spec version 1.2, revision 1.0. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or | ||
15 | * modify it under the terms of the GNU General Public License as | ||
16 | * published by the Free Software Foundation, version 2 of the | ||
17 | * License. | ||
18 | */ | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/moduleparam.h> | ||
22 | #include <linux/pnp.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/wait.h> | ||
25 | #include "tpm.h" | ||
26 | |||
27 | #define TPM_HEADER_SIZE 10 | ||
28 | |||
29 | enum tis_access { | ||
30 | TPM_ACCESS_VALID = 0x80, | ||
31 | TPM_ACCESS_ACTIVE_LOCALITY = 0x20, | ||
32 | TPM_ACCESS_REQUEST_PENDING = 0x04, | ||
33 | TPM_ACCESS_REQUEST_USE = 0x02, | ||
34 | }; | ||
35 | |||
36 | enum tis_status { | ||
37 | TPM_STS_VALID = 0x80, | ||
38 | TPM_STS_COMMAND_READY = 0x40, | ||
39 | TPM_STS_GO = 0x20, | ||
40 | TPM_STS_DATA_AVAIL = 0x10, | ||
41 | TPM_STS_DATA_EXPECT = 0x08, | ||
42 | }; | ||
43 | |||
44 | enum tis_int_flags { | ||
45 | TPM_GLOBAL_INT_ENABLE = 0x80000000, | ||
46 | TPM_INTF_BURST_COUNT_STATIC = 0x100, | ||
47 | TPM_INTF_CMD_READY_INT = 0x080, | ||
48 | TPM_INTF_INT_EDGE_FALLING = 0x040, | ||
49 | TPM_INTF_INT_EDGE_RISING = 0x020, | ||
50 | TPM_INTF_INT_LEVEL_LOW = 0x010, | ||
51 | TPM_INTF_INT_LEVEL_HIGH = 0x008, | ||
52 | TPM_INTF_LOCALITY_CHANGE_INT = 0x004, | ||
53 | TPM_INTF_STS_VALID_INT = 0x002, | ||
54 | TPM_INTF_DATA_AVAIL_INT = 0x001, | ||
55 | }; | ||
56 | |||
57 | enum tis_defaults { | ||
58 | TIS_MEM_BASE = 0xFED40000, | ||
59 | TIS_MEM_LEN = 0x5000, | ||
60 | TIS_SHORT_TIMEOUT = 750, /* ms */ | ||
61 | TIS_LONG_TIMEOUT = 2000, /* 2 sec */ | ||
62 | }; | ||
63 | |||
64 | #define TPM_ACCESS(l) (0x0000 | ((l) << 12)) | ||
65 | #define TPM_INT_ENABLE(l) (0x0008 | ((l) << 12)) | ||
66 | #define TPM_INT_VECTOR(l) (0x000C | ((l) << 12)) | ||
67 | #define TPM_INT_STATUS(l) (0x0010 | ((l) << 12)) | ||
68 | #define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12)) | ||
69 | #define TPM_STS(l) (0x0018 | ((l) << 12)) | ||
70 | #define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12)) | ||
71 | |||
72 | #define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) | ||
73 | #define TPM_RID(l) (0x0F04 | ((l) << 12)) | ||
74 | |||
75 | static LIST_HEAD(tis_chips); | ||
76 | static DEFINE_SPINLOCK(tis_lock); | ||
77 | |||
78 | static int check_locality(struct tpm_chip *chip, int l) | ||
79 | { | ||
80 | if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) & | ||
81 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == | ||
82 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) | ||
83 | return chip->vendor.locality = l; | ||
84 | |||
85 | return -1; | ||
86 | } | ||
87 | |||
88 | static void release_locality(struct tpm_chip *chip, int l, int force) | ||
89 | { | ||
90 | if (force || (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) & | ||
91 | (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) == | ||
92 | (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) | ||
93 | iowrite8(TPM_ACCESS_ACTIVE_LOCALITY, | ||
94 | chip->vendor.iobase + TPM_ACCESS(l)); | ||
95 | } | ||
96 | |||
97 | static int request_locality(struct tpm_chip *chip, int l) | ||
98 | { | ||
99 | unsigned long stop; | ||
100 | long rc; | ||
101 | |||
102 | if (check_locality(chip, l) >= 0) | ||
103 | return l; | ||
104 | |||
105 | iowrite8(TPM_ACCESS_REQUEST_USE, | ||
106 | chip->vendor.iobase + TPM_ACCESS(l)); | ||
107 | |||
108 | if (chip->vendor.irq) { | ||
109 | rc = wait_event_interruptible_timeout(chip->vendor.int_queue, | ||
110 | (check_locality | ||
111 | (chip, l) >= 0), | ||
112 | chip->vendor.timeout_a); | ||
113 | if (rc > 0) | ||
114 | return l; | ||
115 | |||
116 | } else { | ||
117 | /* wait for burstcount */ | ||
118 | stop = jiffies + chip->vendor.timeout_a; | ||
119 | do { | ||
120 | if (check_locality(chip, l) >= 0) | ||
121 | return l; | ||
122 | msleep(TPM_TIMEOUT); | ||
123 | } | ||
124 | while (time_before(jiffies, stop)); | ||
125 | } | ||
126 | return -1; | ||
127 | } | ||
128 | |||
129 | static u8 tpm_tis_status(struct tpm_chip *chip) | ||
130 | { | ||
131 | return ioread8(chip->vendor.iobase + | ||
132 | TPM_STS(chip->vendor.locality)); | ||
133 | } | ||
134 | |||
135 | static void tpm_tis_ready(struct tpm_chip *chip) | ||
136 | { | ||
137 | /* this causes the current command to be aborted */ | ||
138 | iowrite8(TPM_STS_COMMAND_READY, | ||
139 | chip->vendor.iobase + TPM_STS(chip->vendor.locality)); | ||
140 | } | ||
141 | |||
142 | static int get_burstcount(struct tpm_chip *chip) | ||
143 | { | ||
144 | unsigned long stop; | ||
145 | int burstcnt; | ||
146 | |||
147 | /* wait for burstcount */ | ||
148 | /* which timeout value, spec has 2 answers (c & d) */ | ||
149 | stop = jiffies + chip->vendor.timeout_d; | ||
150 | do { | ||
151 | burstcnt = ioread8(chip->vendor.iobase + | ||
152 | TPM_STS(chip->vendor.locality) + 1); | ||
153 | burstcnt += ioread8(chip->vendor.iobase + | ||
154 | TPM_STS(chip->vendor.locality) + | ||
155 | 2) << 8; | ||
156 | if (burstcnt) | ||
157 | return burstcnt; | ||
158 | msleep(TPM_TIMEOUT); | ||
159 | } while (time_before(jiffies, stop)); | ||
160 | return -EBUSY; | ||
161 | } | ||
162 | |||
163 | static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, | ||
164 | wait_queue_head_t *queue) | ||
165 | { | ||
166 | unsigned long stop; | ||
167 | long rc; | ||
168 | u8 status; | ||
169 | |||
170 | /* check current status */ | ||
171 | status = tpm_tis_status(chip); | ||
172 | if ((status & mask) == mask) | ||
173 | return 0; | ||
174 | |||
175 | if (chip->vendor.irq) { | ||
176 | rc = wait_event_interruptible_timeout(*queue, | ||
177 | ((tpm_tis_status | ||
178 | (chip) & mask) == | ||
179 | mask), timeout); | ||
180 | if (rc > 0) | ||
181 | return 0; | ||
182 | } else { | ||
183 | stop = jiffies + timeout; | ||
184 | do { | ||
185 | msleep(TPM_TIMEOUT); | ||
186 | status = tpm_tis_status(chip); | ||
187 | if ((status & mask) == mask) | ||
188 | return 0; | ||
189 | } while (time_before(jiffies, stop)); | ||
190 | } | ||
191 | return -ETIME; | ||
192 | } | ||
193 | |||
194 | static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) | ||
195 | { | ||
196 | int size = 0, burstcnt; | ||
197 | while (size < count && | ||
198 | wait_for_stat(chip, | ||
199 | TPM_STS_DATA_AVAIL | TPM_STS_VALID, | ||
200 | chip->vendor.timeout_c, | ||
201 | &chip->vendor.read_queue) | ||
202 | == 0) { | ||
203 | burstcnt = get_burstcount(chip); | ||
204 | for (; burstcnt > 0 && size < count; burstcnt--) | ||
205 | buf[size++] = ioread8(chip->vendor.iobase + | ||
206 | TPM_DATA_FIFO(chip->vendor. | ||
207 | locality)); | ||
208 | } | ||
209 | return size; | ||
210 | } | ||
211 | |||
212 | static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) | ||
213 | { | ||
214 | int size = 0; | ||
215 | int expected, status; | ||
216 | |||
217 | if (count < TPM_HEADER_SIZE) { | ||
218 | size = -EIO; | ||
219 | goto out; | ||
220 | } | ||
221 | |||
222 | /* read first 10 bytes, including tag, paramsize, and result */ | ||
223 | if ((size = | ||
224 | recv_data(chip, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) { | ||
225 | dev_err(chip->dev, "Unable to read header\n"); | ||
226 | goto out; | ||
227 | } | ||
228 | |||
229 | expected = be32_to_cpu(*(__be32 *) (buf + 2)); | ||
230 | if (expected > count) { | ||
231 | size = -EIO; | ||
232 | goto out; | ||
233 | } | ||
234 | |||
235 | if ((size += | ||
236 | recv_data(chip, &buf[TPM_HEADER_SIZE], | ||
237 | expected - TPM_HEADER_SIZE)) < expected) { | ||
238 | dev_err(chip->dev, "Unable to read remainder of result\n"); | ||
239 | size = -ETIME; | ||
240 | goto out; | ||
241 | } | ||
242 | |||
243 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, | ||
244 | &chip->vendor.int_queue); | ||
245 | status = tpm_tis_status(chip); | ||
246 | if (status & TPM_STS_DATA_AVAIL) { /* retry? */ | ||
247 | dev_err(chip->dev, "Error left over data\n"); | ||
248 | size = -EIO; | ||
249 | goto out; | ||
250 | } | ||
251 | |||
252 | out: | ||
253 | tpm_tis_ready(chip); | ||
254 | release_locality(chip, chip->vendor.locality, 0); | ||
255 | return size; | ||
256 | } | ||
257 | |||
258 | /* | ||
259 | * If interrupts are used (signaled by an irq set in the vendor structure) | ||
260 | * tpm.c can skip polling for the data to be available as the interrupt is | ||
261 | * waited for here | ||
262 | */ | ||
263 | static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) | ||
264 | { | ||
265 | int rc, status, burstcnt; | ||
266 | size_t count = 0; | ||
267 | u32 ordinal; | ||
268 | |||
269 | if (request_locality(chip, 0) < 0) | ||
270 | return -EBUSY; | ||
271 | |||
272 | status = tpm_tis_status(chip); | ||
273 | if ((status & TPM_STS_COMMAND_READY) == 0) { | ||
274 | tpm_tis_ready(chip); | ||
275 | if (wait_for_stat | ||
276 | (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, | ||
277 | &chip->vendor.int_queue) < 0) { | ||
278 | rc = -ETIME; | ||
279 | goto out_err; | ||
280 | } | ||
281 | } | ||
282 | |||
283 | while (count < len - 1) { | ||
284 | burstcnt = get_burstcount(chip); | ||
285 | for (; burstcnt > 0 && count < len - 1; burstcnt--) { | ||
286 | iowrite8(buf[count], chip->vendor.iobase + | ||
287 | TPM_DATA_FIFO(chip->vendor.locality)); | ||
288 | count++; | ||
289 | } | ||
290 | |||
291 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, | ||
292 | &chip->vendor.int_queue); | ||
293 | status = tpm_tis_status(chip); | ||
294 | if ((status & TPM_STS_DATA_EXPECT) == 0) { | ||
295 | rc = -EIO; | ||
296 | goto out_err; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | /* write last byte */ | ||
301 | iowrite8(buf[count], | ||
302 | chip->vendor.iobase + | ||
303 | TPM_DATA_FIFO(chip->vendor.locality)); | ||
304 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, | ||
305 | &chip->vendor.int_queue); | ||
306 | status = tpm_tis_status(chip); | ||
307 | if ((status & TPM_STS_DATA_EXPECT) != 0) { | ||
308 | rc = -EIO; | ||
309 | goto out_err; | ||
310 | } | ||
311 | |||
312 | /* go and do it */ | ||
313 | iowrite8(TPM_STS_GO, | ||
314 | chip->vendor.iobase + TPM_STS(chip->vendor.locality)); | ||
315 | |||
316 | if (chip->vendor.irq) { | ||
317 | ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); | ||
318 | if (wait_for_stat | ||
319 | (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, | ||
320 | tpm_calc_ordinal_duration(chip, ordinal), | ||
321 | &chip->vendor.read_queue) < 0) { | ||
322 | rc = -ETIME; | ||
323 | goto out_err; | ||
324 | } | ||
325 | } | ||
326 | return len; | ||
327 | out_err: | ||
328 | tpm_tis_ready(chip); | ||
329 | release_locality(chip, chip->vendor.locality, 0); | ||
330 | return rc; | ||
331 | } | ||
332 | |||
333 | static struct file_operations tis_ops = { | ||
334 | .owner = THIS_MODULE, | ||
335 | .llseek = no_llseek, | ||
336 | .open = tpm_open, | ||
337 | .read = tpm_read, | ||
338 | .write = tpm_write, | ||
339 | .release = tpm_release, | ||
340 | }; | ||
341 | |||
342 | static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); | ||
343 | static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL); | ||
344 | static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL); | ||
345 | static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL); | ||
346 | static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL); | ||
347 | static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, | ||
348 | NULL); | ||
349 | static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL); | ||
350 | static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel); | ||
351 | |||
352 | static struct attribute *tis_attrs[] = { | ||
353 | &dev_attr_pubek.attr, | ||
354 | &dev_attr_pcrs.attr, | ||
355 | &dev_attr_enabled.attr, | ||
356 | &dev_attr_active.attr, | ||
357 | &dev_attr_owned.attr, | ||
358 | &dev_attr_temp_deactivated.attr, | ||
359 | &dev_attr_caps.attr, | ||
360 | &dev_attr_cancel.attr, NULL, | ||
361 | }; | ||
362 | |||
363 | static struct attribute_group tis_attr_grp = { | ||
364 | .attrs = tis_attrs | ||
365 | }; | ||
366 | |||
367 | static struct tpm_vendor_specific tpm_tis = { | ||
368 | .status = tpm_tis_status, | ||
369 | .recv = tpm_tis_recv, | ||
370 | .send = tpm_tis_send, | ||
371 | .cancel = tpm_tis_ready, | ||
372 | .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, | ||
373 | .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, | ||
374 | .req_canceled = TPM_STS_COMMAND_READY, | ||
375 | .attr_group = &tis_attr_grp, | ||
376 | .miscdev = { | ||
377 | .fops = &tis_ops,}, | ||
378 | }; | ||
379 | |||
380 | static irqreturn_t tis_int_probe(int irq, void *dev_id, struct pt_regs *regs) | ||
381 | { | ||
382 | struct tpm_chip *chip = (struct tpm_chip *) dev_id; | ||
383 | u32 interrupt; | ||
384 | |||
385 | interrupt = ioread32(chip->vendor.iobase + | ||
386 | TPM_INT_STATUS(chip->vendor.locality)); | ||
387 | |||
388 | if (interrupt == 0) | ||
389 | return IRQ_NONE; | ||
390 | |||
391 | chip->vendor.irq = irq; | ||
392 | |||
393 | /* Clear interrupts handled with TPM_EOI */ | ||
394 | iowrite32(interrupt, | ||
395 | chip->vendor.iobase + | ||
396 | TPM_INT_STATUS(chip->vendor.locality)); | ||
397 | return IRQ_HANDLED; | ||
398 | } | ||
399 | |||
400 | static irqreturn_t tis_int_handler(int irq, void *dev_id, struct pt_regs *regs) | ||
401 | { | ||
402 | struct tpm_chip *chip = (struct tpm_chip *) dev_id; | ||
403 | u32 interrupt; | ||
404 | int i; | ||
405 | |||
406 | interrupt = ioread32(chip->vendor.iobase + | ||
407 | TPM_INT_STATUS(chip->vendor.locality)); | ||
408 | |||
409 | if (interrupt == 0) | ||
410 | return IRQ_NONE; | ||
411 | |||
412 | if (interrupt & TPM_INTF_DATA_AVAIL_INT) | ||
413 | wake_up_interruptible(&chip->vendor.read_queue); | ||
414 | if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT) | ||
415 | for (i = 0; i < 5; i++) | ||
416 | if (check_locality(chip, i) >= 0) | ||
417 | break; | ||
418 | if (interrupt & | ||
419 | (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT | | ||
420 | TPM_INTF_CMD_READY_INT)) | ||
421 | wake_up_interruptible(&chip->vendor.int_queue); | ||
422 | |||
423 | /* Clear interrupts handled with TPM_EOI */ | ||
424 | iowrite32(interrupt, | ||
425 | chip->vendor.iobase + | ||
426 | TPM_INT_STATUS(chip->vendor.locality)); | ||
427 | return IRQ_HANDLED; | ||
428 | } | ||
429 | |||
430 | static int interrupts = 1; | ||
431 | module_param(interrupts, bool, 0444); | ||
432 | MODULE_PARM_DESC(interrupts, "Enable interrupts"); | ||
433 | |||
434 | static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, | ||
435 | const struct pnp_device_id *pnp_id) | ||
436 | { | ||
437 | u32 vendor, intfcaps, intmask; | ||
438 | int rc, i; | ||
439 | unsigned long start, len; | ||
440 | struct tpm_chip *chip; | ||
441 | |||
442 | start = pnp_mem_start(pnp_dev, 0); | ||
443 | len = pnp_mem_len(pnp_dev, 0); | ||
444 | |||
445 | if (!start) | ||
446 | start = TIS_MEM_BASE; | ||
447 | if (!len) | ||
448 | len = TIS_MEM_LEN; | ||
449 | |||
450 | if (!(chip = tpm_register_hardware(&pnp_dev->dev, &tpm_tis))) | ||
451 | return -ENODEV; | ||
452 | |||
453 | chip->vendor.iobase = ioremap(start, len); | ||
454 | if (!chip->vendor.iobase) { | ||
455 | rc = -EIO; | ||
456 | goto out_err; | ||
457 | } | ||
458 | |||
459 | vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); | ||
460 | |||
461 | /* Default timeouts */ | ||
462 | chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | ||
463 | chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); | ||
464 | chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | ||
465 | chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | ||
466 | |||
467 | dev_info(&pnp_dev->dev, | ||
468 | "1.2 TPM (device-id 0x%X, rev-id %d)\n", | ||
469 | vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); | ||
470 | |||
471 | /* Figure out the capabilities */ | ||
472 | intfcaps = | ||
473 | ioread32(chip->vendor.iobase + | ||
474 | TPM_INTF_CAPS(chip->vendor.locality)); | ||
475 | dev_dbg(&pnp_dev->dev, "TPM interface capabilities (0x%x):\n", | ||
476 | intfcaps); | ||
477 | if (intfcaps & TPM_INTF_BURST_COUNT_STATIC) | ||
478 | dev_dbg(&pnp_dev->dev, "\tBurst Count Static\n"); | ||
479 | if (intfcaps & TPM_INTF_CMD_READY_INT) | ||
480 | dev_dbg(&pnp_dev->dev, "\tCommand Ready Int Support\n"); | ||
481 | if (intfcaps & TPM_INTF_INT_EDGE_FALLING) | ||
482 | dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Falling\n"); | ||
483 | if (intfcaps & TPM_INTF_INT_EDGE_RISING) | ||
484 | dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Rising\n"); | ||
485 | if (intfcaps & TPM_INTF_INT_LEVEL_LOW) | ||
486 | dev_dbg(&pnp_dev->dev, "\tInterrupt Level Low\n"); | ||
487 | if (intfcaps & TPM_INTF_INT_LEVEL_HIGH) | ||
488 | dev_dbg(&pnp_dev->dev, "\tInterrupt Level High\n"); | ||
489 | if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT) | ||
490 | dev_dbg(&pnp_dev->dev, "\tLocality Change Int Support\n"); | ||
491 | if (intfcaps & TPM_INTF_STS_VALID_INT) | ||
492 | dev_dbg(&pnp_dev->dev, "\tSts Valid Int Support\n"); | ||
493 | if (intfcaps & TPM_INTF_DATA_AVAIL_INT) | ||
494 | dev_dbg(&pnp_dev->dev, "\tData Avail Int Support\n"); | ||
495 | |||
496 | if (request_locality(chip, 0) != 0) { | ||
497 | rc = -ENODEV; | ||
498 | goto out_err; | ||
499 | } | ||
500 | |||
501 | /* INTERRUPT Setup */ | ||
502 | init_waitqueue_head(&chip->vendor.read_queue); | ||
503 | init_waitqueue_head(&chip->vendor.int_queue); | ||
504 | |||
505 | intmask = | ||
506 | ioread32(chip->vendor.iobase + | ||
507 | TPM_INT_ENABLE(chip->vendor.locality)); | ||
508 | |||
509 | intmask |= TPM_INTF_CMD_READY_INT | ||
510 | | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT | ||
511 | | TPM_INTF_STS_VALID_INT; | ||
512 | |||
513 | iowrite32(intmask, | ||
514 | chip->vendor.iobase + | ||
515 | TPM_INT_ENABLE(chip->vendor.locality)); | ||
516 | if (interrupts) { | ||
517 | chip->vendor.irq = | ||
518 | ioread8(chip->vendor.iobase + | ||
519 | TPM_INT_VECTOR(chip->vendor.locality)); | ||
520 | |||
521 | for (i = 3; i < 16 && chip->vendor.irq == 0; i++) { | ||
522 | iowrite8(i, chip->vendor.iobase + | ||
523 | TPM_INT_VECTOR(chip->vendor.locality)); | ||
524 | if (request_irq | ||
525 | (i, tis_int_probe, SA_SHIRQ, | ||
526 | chip->vendor.miscdev.name, chip) != 0) { | ||
527 | dev_info(chip->dev, | ||
528 | "Unable to request irq: %d for probe\n", | ||
529 | i); | ||
530 | continue; | ||
531 | } | ||
532 | |||
533 | /* Clear all existing */ | ||
534 | iowrite32(ioread32 | ||
535 | (chip->vendor.iobase + | ||
536 | TPM_INT_STATUS(chip->vendor.locality)), | ||
537 | chip->vendor.iobase + | ||
538 | TPM_INT_STATUS(chip->vendor.locality)); | ||
539 | |||
540 | /* Turn on */ | ||
541 | iowrite32(intmask | TPM_GLOBAL_INT_ENABLE, | ||
542 | chip->vendor.iobase + | ||
543 | TPM_INT_ENABLE(chip->vendor.locality)); | ||
544 | |||
545 | /* Generate Interrupts */ | ||
546 | tpm_gen_interrupt(chip); | ||
547 | |||
548 | /* Turn off */ | ||
549 | iowrite32(intmask, | ||
550 | chip->vendor.iobase + | ||
551 | TPM_INT_ENABLE(chip->vendor.locality)); | ||
552 | free_irq(i, chip); | ||
553 | } | ||
554 | } | ||
555 | if (chip->vendor.irq) { | ||
556 | iowrite8(chip->vendor.irq, | ||
557 | chip->vendor.iobase + | ||
558 | TPM_INT_VECTOR(chip->vendor.locality)); | ||
559 | if (request_irq | ||
560 | (chip->vendor.irq, tis_int_handler, SA_SHIRQ, | ||
561 | chip->vendor.miscdev.name, chip) != 0) { | ||
562 | dev_info(chip->dev, | ||
563 | "Unable to request irq: %d for use\n", | ||
564 | chip->vendor.irq); | ||
565 | chip->vendor.irq = 0; | ||
566 | } else { | ||
567 | /* Clear all existing */ | ||
568 | iowrite32(ioread32 | ||
569 | (chip->vendor.iobase + | ||
570 | TPM_INT_STATUS(chip->vendor.locality)), | ||
571 | chip->vendor.iobase + | ||
572 | TPM_INT_STATUS(chip->vendor.locality)); | ||
573 | |||
574 | /* Turn on */ | ||
575 | iowrite32(intmask | TPM_GLOBAL_INT_ENABLE, | ||
576 | chip->vendor.iobase + | ||
577 | TPM_INT_ENABLE(chip->vendor.locality)); | ||
578 | } | ||
579 | } | ||
580 | |||
581 | INIT_LIST_HEAD(&chip->vendor.list); | ||
582 | spin_lock(&tis_lock); | ||
583 | list_add(&chip->vendor.list, &tis_chips); | ||
584 | spin_unlock(&tis_lock); | ||
585 | |||
586 | tpm_get_timeouts(chip); | ||
587 | tpm_continue_selftest(chip); | ||
588 | |||
589 | return 0; | ||
590 | out_err: | ||
591 | if (chip->vendor.iobase) | ||
592 | iounmap(chip->vendor.iobase); | ||
593 | tpm_remove_hardware(chip->dev); | ||
594 | return rc; | ||
595 | } | ||
596 | |||
597 | static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg) | ||
598 | { | ||
599 | return tpm_pm_suspend(&dev->dev, msg); | ||
600 | } | ||
601 | |||
602 | static int tpm_tis_pnp_resume(struct pnp_dev *dev) | ||
603 | { | ||
604 | return tpm_pm_resume(&dev->dev); | ||
605 | } | ||
606 | |||
607 | static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = { | ||
608 | {"PNP0C31", 0}, /* TPM */ | ||
609 | {"ATM1200", 0}, /* Atmel */ | ||
610 | {"IFX0102", 0}, /* Infineon */ | ||
611 | {"BCM0101", 0}, /* Broadcom */ | ||
612 | {"NSC1200", 0}, /* National */ | ||
613 | /* Add new here */ | ||
614 | {"", 0}, /* User Specified */ | ||
615 | {"", 0} /* Terminator */ | ||
616 | }; | ||
617 | |||
618 | static struct pnp_driver tis_pnp_driver = { | ||
619 | .name = "tpm_tis", | ||
620 | .id_table = tpm_pnp_tbl, | ||
621 | .probe = tpm_tis_pnp_init, | ||
622 | .suspend = tpm_tis_pnp_suspend, | ||
623 | .resume = tpm_tis_pnp_resume, | ||
624 | }; | ||
625 | |||
626 | #define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2 | ||
627 | module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, | ||
628 | sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); | ||
629 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); | ||
630 | |||
631 | static int __init init_tis(void) | ||
632 | { | ||
633 | return pnp_register_driver(&tis_pnp_driver); | ||
634 | } | ||
635 | |||
636 | static void __exit cleanup_tis(void) | ||
637 | { | ||
638 | struct tpm_vendor_specific *i, *j; | ||
639 | struct tpm_chip *chip; | ||
640 | spin_lock(&tis_lock); | ||
641 | list_for_each_entry_safe(i, j, &tis_chips, list) { | ||
642 | chip = to_tpm_chip(i); | ||
643 | iowrite32(~TPM_GLOBAL_INT_ENABLE & | ||
644 | ioread32(chip->vendor.iobase + | ||
645 | TPM_INT_ENABLE(chip->vendor. | ||
646 | locality)), | ||
647 | chip->vendor.iobase + | ||
648 | TPM_INT_ENABLE(chip->vendor.locality)); | ||
649 | release_locality(chip, chip->vendor.locality, 1); | ||
650 | if (chip->vendor.irq) | ||
651 | free_irq(chip->vendor.irq, chip); | ||
652 | iounmap(i->iobase); | ||
653 | list_del(&i->list); | ||
654 | tpm_remove_hardware(chip->dev); | ||
655 | } | ||
656 | spin_unlock(&tis_lock); | ||
657 | pnp_unregister_driver(&tis_pnp_driver); | ||
658 | } | ||
659 | |||
660 | module_init(init_tis); | ||
661 | module_exit(cleanup_tis); | ||
662 | MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)"); | ||
663 | MODULE_DESCRIPTION("TPM Driver"); | ||
664 | MODULE_VERSION("2.0"); | ||
665 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 0bfd1b63662e..a88b94a82b14 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -351,10 +351,10 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size) | |||
351 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 351 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
352 | return size; | 352 | return size; |
353 | } | 353 | } |
354 | |||
355 | EXPORT_SYMBOL_GPL(tty_buffer_request_room); | 354 | EXPORT_SYMBOL_GPL(tty_buffer_request_room); |
356 | 355 | ||
357 | int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, size_t size) | 356 | int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, |
357 | size_t size) | ||
358 | { | 358 | { |
359 | int copied = 0; | 359 | int copied = 0; |
360 | do { | 360 | do { |
@@ -368,17 +368,16 @@ int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, s | |||
368 | tb->used += space; | 368 | tb->used += space; |
369 | copied += space; | 369 | copied += space; |
370 | chars += space; | 370 | chars += space; |
371 | /* printk("Flip insert %d.\n", space); */ | ||
372 | } | 371 | } |
373 | /* There is a small chance that we need to split the data over | 372 | /* There is a small chance that we need to split the data over |
374 | several buffers. If this is the case we must loop */ | 373 | several buffers. If this is the case we must loop */ |
375 | while (unlikely(size > copied)); | 374 | while (unlikely(size > copied)); |
376 | return copied; | 375 | return copied; |
377 | } | 376 | } |
377 | EXPORT_SYMBOL(tty_insert_flip_string); | ||
378 | 378 | ||
379 | EXPORT_SYMBOL_GPL(tty_insert_flip_string); | 379 | int tty_insert_flip_string_flags(struct tty_struct *tty, |
380 | 380 | const unsigned char *chars, const char *flags, size_t size) | |
381 | int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size) | ||
382 | { | 381 | { |
383 | int copied = 0; | 382 | int copied = 0; |
384 | do { | 383 | do { |
@@ -399,9 +398,20 @@ int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *ch | |||
399 | while (unlikely(size > copied)); | 398 | while (unlikely(size > copied)); |
400 | return copied; | 399 | return copied; |
401 | } | 400 | } |
401 | EXPORT_SYMBOL(tty_insert_flip_string_flags); | ||
402 | 402 | ||
403 | EXPORT_SYMBOL_GPL(tty_insert_flip_string_flags); | 403 | void tty_schedule_flip(struct tty_struct *tty) |
404 | 404 | { | |
405 | unsigned long flags; | ||
406 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
407 | if (tty->buf.tail != NULL) { | ||
408 | tty->buf.tail->active = 0; | ||
409 | tty->buf.tail->commit = tty->buf.tail->used; | ||
410 | } | ||
411 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
412 | schedule_delayed_work(&tty->buf.work, 1); | ||
413 | } | ||
414 | EXPORT_SYMBOL(tty_schedule_flip); | ||
405 | 415 | ||
406 | /* | 416 | /* |
407 | * Prepare a block of space in the buffer for data. Returns the length | 417 | * Prepare a block of space in the buffer for data. Returns the length |
@@ -1730,7 +1740,7 @@ static void release_dev(struct file * filp) | |||
1730 | { | 1740 | { |
1731 | struct tty_struct *tty, *o_tty; | 1741 | struct tty_struct *tty, *o_tty; |
1732 | int pty_master, tty_closing, o_tty_closing, do_sleep; | 1742 | int pty_master, tty_closing, o_tty_closing, do_sleep; |
1733 | int devpts_master, devpts; | 1743 | int devpts; |
1734 | int idx; | 1744 | int idx; |
1735 | char buf[64]; | 1745 | char buf[64]; |
1736 | unsigned long flags; | 1746 | unsigned long flags; |
@@ -1747,7 +1757,6 @@ static void release_dev(struct file * filp) | |||
1747 | pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 1757 | pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
1748 | tty->driver->subtype == PTY_TYPE_MASTER); | 1758 | tty->driver->subtype == PTY_TYPE_MASTER); |
1749 | devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0; | 1759 | devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0; |
1750 | devpts_master = pty_master && devpts; | ||
1751 | o_tty = tty->link; | 1760 | o_tty = tty->link; |
1752 | 1761 | ||
1753 | #ifdef TTY_PARANOIA_CHECK | 1762 | #ifdef TTY_PARANOIA_CHECK |
@@ -2185,6 +2194,7 @@ static int ptmx_open(struct inode * inode, struct file * filp) | |||
2185 | return 0; | 2194 | return 0; |
2186 | out1: | 2195 | out1: |
2187 | release_dev(filp); | 2196 | release_dev(filp); |
2197 | return retval; | ||
2188 | out: | 2198 | out: |
2189 | down(&allocated_ptys_lock); | 2199 | down(&allocated_ptys_lock); |
2190 | idr_remove(&allocated_ptys, index); | 2200 | idr_remove(&allocated_ptys, index); |
@@ -2713,7 +2723,11 @@ static void __do_SAK(void *arg) | |||
2713 | } | 2723 | } |
2714 | task_lock(p); | 2724 | task_lock(p); |
2715 | if (p->files) { | 2725 | if (p->files) { |
2716 | rcu_read_lock(); | 2726 | /* |
2727 | * We don't take a ref to the file, so we must | ||
2728 | * hold ->file_lock instead. | ||
2729 | */ | ||
2730 | spin_lock(&p->files->file_lock); | ||
2717 | fdt = files_fdtable(p->files); | 2731 | fdt = files_fdtable(p->files); |
2718 | for (i=0; i < fdt->max_fds; i++) { | 2732 | for (i=0; i < fdt->max_fds; i++) { |
2719 | filp = fcheck_files(p->files, i); | 2733 | filp = fcheck_files(p->files, i); |
@@ -2724,11 +2738,11 @@ static void __do_SAK(void *arg) | |||
2724 | printk(KERN_NOTICE "SAK: killed process %d" | 2738 | printk(KERN_NOTICE "SAK: killed process %d" |
2725 | " (%s): fd#%d opened to the tty\n", | 2739 | " (%s): fd#%d opened to the tty\n", |
2726 | p->pid, p->comm, i); | 2740 | p->pid, p->comm, i); |
2727 | send_sig(SIGKILL, p, 1); | 2741 | force_sig(SIGKILL, p); |
2728 | break; | 2742 | break; |
2729 | } | 2743 | } |
2730 | } | 2744 | } |
2731 | rcu_read_unlock(); | 2745 | spin_unlock(&p->files->file_lock); |
2732 | } | 2746 | } |
2733 | task_unlock(p); | 2747 | task_unlock(p); |
2734 | } while_each_thread(g, p); | 2748 | } while_each_thread(g, p); |
diff --git a/drivers/char/vr41xx_rtc.c b/drivers/char/vr41xx_rtc.c deleted file mode 100644 index b109d9a502d6..000000000000 --- a/drivers/char/vr41xx_rtc.c +++ /dev/null | |||
@@ -1,717 +0,0 @@ | |||
1 | /* | ||
2 | * Driver for NEC VR4100 series Real Time Clock unit. | ||
3 | * | ||
4 | * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/fs.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/ioport.h> | ||
24 | #include <linux/irq.h> | ||
25 | #include <linux/mc146818rtc.h> | ||
26 | #include <linux/miscdevice.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/poll.h> | ||
29 | #include <linux/rtc.h> | ||
30 | #include <linux/spinlock.h> | ||
31 | #include <linux/types.h> | ||
32 | #include <linux/wait.h> | ||
33 | |||
34 | #include <asm/div64.h> | ||
35 | #include <asm/io.h> | ||
36 | #include <asm/time.h> | ||
37 | #include <asm/uaccess.h> | ||
38 | #include <asm/vr41xx/vr41xx.h> | ||
39 | |||
40 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | ||
41 | MODULE_DESCRIPTION("NEC VR4100 series RTC driver"); | ||
42 | MODULE_LICENSE("GPL"); | ||
43 | |||
44 | #define RTC1_TYPE1_START 0x0b0000c0UL | ||
45 | #define RTC1_TYPE1_END 0x0b0000dfUL | ||
46 | #define RTC2_TYPE1_START 0x0b0001c0UL | ||
47 | #define RTC2_TYPE1_END 0x0b0001dfUL | ||
48 | |||
49 | #define RTC1_TYPE2_START 0x0f000100UL | ||
50 | #define RTC1_TYPE2_END 0x0f00011fUL | ||
51 | #define RTC2_TYPE2_START 0x0f000120UL | ||
52 | #define RTC2_TYPE2_END 0x0f00013fUL | ||
53 | |||
54 | #define RTC1_SIZE 0x20 | ||
55 | #define RTC2_SIZE 0x20 | ||
56 | |||
57 | /* RTC 1 registers */ | ||
58 | #define ETIMELREG 0x00 | ||
59 | #define ETIMEMREG 0x02 | ||
60 | #define ETIMEHREG 0x04 | ||
61 | /* RFU */ | ||
62 | #define ECMPLREG 0x08 | ||
63 | #define ECMPMREG 0x0a | ||
64 | #define ECMPHREG 0x0c | ||
65 | /* RFU */ | ||
66 | #define RTCL1LREG 0x10 | ||
67 | #define RTCL1HREG 0x12 | ||
68 | #define RTCL1CNTLREG 0x14 | ||
69 | #define RTCL1CNTHREG 0x16 | ||
70 | #define RTCL2LREG 0x18 | ||
71 | #define RTCL2HREG 0x1a | ||
72 | #define RTCL2CNTLREG 0x1c | ||
73 | #define RTCL2CNTHREG 0x1e | ||
74 | |||
75 | /* RTC 2 registers */ | ||
76 | #define TCLKLREG 0x00 | ||
77 | #define TCLKHREG 0x02 | ||
78 | #define TCLKCNTLREG 0x04 | ||
79 | #define TCLKCNTHREG 0x06 | ||
80 | /* RFU */ | ||
81 | #define RTCINTREG 0x1e | ||
82 | #define TCLOCK_INT 0x08 | ||
83 | #define RTCLONG2_INT 0x04 | ||
84 | #define RTCLONG1_INT 0x02 | ||
85 | #define ELAPSEDTIME_INT 0x01 | ||
86 | |||
87 | #define RTC_FREQUENCY 32768 | ||
88 | #define MAX_PERIODIC_RATE 6553 | ||
89 | #define MAX_USER_PERIODIC_RATE 64 | ||
90 | |||
91 | static void __iomem *rtc1_base; | ||
92 | static void __iomem *rtc2_base; | ||
93 | |||
94 | #define rtc1_read(offset) readw(rtc1_base + (offset)) | ||
95 | #define rtc1_write(offset, value) writew((value), rtc1_base + (offset)) | ||
96 | |||
97 | #define rtc2_read(offset) readw(rtc2_base + (offset)) | ||
98 | #define rtc2_write(offset, value) writew((value), rtc2_base + (offset)) | ||
99 | |||
100 | static unsigned long epoch = 1970; /* Jan 1 1970 00:00:00 */ | ||
101 | |||
102 | static spinlock_t rtc_task_lock; | ||
103 | static wait_queue_head_t rtc_wait; | ||
104 | static unsigned long rtc_irq_data; | ||
105 | static struct fasync_struct *rtc_async_queue; | ||
106 | static rtc_task_t *rtc_callback; | ||
107 | static char rtc_name[] = "RTC"; | ||
108 | static unsigned long periodic_frequency; | ||
109 | static unsigned long periodic_count; | ||
110 | |||
111 | typedef enum { | ||
112 | RTC_RELEASE, | ||
113 | RTC_OPEN, | ||
114 | } rtc_status_t; | ||
115 | |||
116 | static rtc_status_t rtc_status; | ||
117 | |||
118 | typedef enum { | ||
119 | FUNCTION_RTC_IOCTL, | ||
120 | FUNCTION_RTC_CONTROL, | ||
121 | } rtc_callfrom_t; | ||
122 | |||
123 | struct resource rtc_resource[2] = { | ||
124 | { .name = rtc_name, | ||
125 | .flags = IORESOURCE_MEM, }, | ||
126 | { .name = rtc_name, | ||
127 | .flags = IORESOURCE_MEM, }, | ||
128 | }; | ||
129 | |||
130 | static inline unsigned long read_elapsed_second(void) | ||
131 | { | ||
132 | unsigned long first_low, first_mid, first_high; | ||
133 | unsigned long second_low, second_mid, second_high; | ||
134 | |||
135 | do { | ||
136 | first_low = rtc1_read(ETIMELREG); | ||
137 | first_mid = rtc1_read(ETIMEMREG); | ||
138 | first_high = rtc1_read(ETIMEHREG); | ||
139 | second_low = rtc1_read(ETIMELREG); | ||
140 | second_mid = rtc1_read(ETIMEMREG); | ||
141 | second_high = rtc1_read(ETIMEHREG); | ||
142 | } while (first_low != second_low || first_mid != second_mid || | ||
143 | first_high != second_high); | ||
144 | |||
145 | return (first_high << 17) | (first_mid << 1) | (first_low >> 15); | ||
146 | } | ||
147 | |||
148 | static inline void write_elapsed_second(unsigned long sec) | ||
149 | { | ||
150 | spin_lock_irq(&rtc_lock); | ||
151 | |||
152 | rtc1_write(ETIMELREG, (uint16_t)(sec << 15)); | ||
153 | rtc1_write(ETIMEMREG, (uint16_t)(sec >> 1)); | ||
154 | rtc1_write(ETIMEHREG, (uint16_t)(sec >> 17)); | ||
155 | |||
156 | spin_unlock_irq(&rtc_lock); | ||
157 | } | ||
158 | |||
159 | static void set_alarm(struct rtc_time *time) | ||
160 | { | ||
161 | unsigned long alarm_sec; | ||
162 | |||
163 | alarm_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, | ||
164 | time->tm_hour, time->tm_min, time->tm_sec); | ||
165 | |||
166 | spin_lock_irq(&rtc_lock); | ||
167 | |||
168 | rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15)); | ||
169 | rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1)); | ||
170 | rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17)); | ||
171 | |||
172 | spin_unlock_irq(&rtc_lock); | ||
173 | } | ||
174 | |||
175 | static void read_alarm(struct rtc_time *time) | ||
176 | { | ||
177 | unsigned long low, mid, high; | ||
178 | |||
179 | spin_lock_irq(&rtc_lock); | ||
180 | |||
181 | low = rtc1_read(ECMPLREG); | ||
182 | mid = rtc1_read(ECMPMREG); | ||
183 | high = rtc1_read(ECMPHREG); | ||
184 | |||
185 | spin_unlock_irq(&rtc_lock); | ||
186 | |||
187 | to_tm((high << 17) | (mid << 1) | (low >> 15), time); | ||
188 | time->tm_year -= 1900; | ||
189 | } | ||
190 | |||
191 | static void read_time(struct rtc_time *time) | ||
192 | { | ||
193 | unsigned long epoch_sec, elapsed_sec; | ||
194 | |||
195 | epoch_sec = mktime(epoch, 1, 1, 0, 0, 0); | ||
196 | elapsed_sec = read_elapsed_second(); | ||
197 | |||
198 | to_tm(epoch_sec + elapsed_sec, time); | ||
199 | time->tm_year -= 1900; | ||
200 | } | ||
201 | |||
202 | static void set_time(struct rtc_time *time) | ||
203 | { | ||
204 | unsigned long epoch_sec, current_sec; | ||
205 | |||
206 | epoch_sec = mktime(epoch, 1, 1, 0, 0, 0); | ||
207 | current_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, | ||
208 | time->tm_hour, time->tm_min, time->tm_sec); | ||
209 | |||
210 | write_elapsed_second(current_sec - epoch_sec); | ||
211 | } | ||
212 | |||
213 | static ssize_t rtc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | ||
214 | { | ||
215 | DECLARE_WAITQUEUE(wait, current); | ||
216 | unsigned long irq_data; | ||
217 | int retval = 0; | ||
218 | |||
219 | if (count != sizeof(unsigned int) && count != sizeof(unsigned long)) | ||
220 | return -EINVAL; | ||
221 | |||
222 | add_wait_queue(&rtc_wait, &wait); | ||
223 | |||
224 | do { | ||
225 | __set_current_state(TASK_INTERRUPTIBLE); | ||
226 | |||
227 | spin_lock_irq(&rtc_lock); | ||
228 | irq_data = rtc_irq_data; | ||
229 | rtc_irq_data = 0; | ||
230 | spin_unlock_irq(&rtc_lock); | ||
231 | |||
232 | if (irq_data != 0) | ||
233 | break; | ||
234 | |||
235 | if (file->f_flags & O_NONBLOCK) { | ||
236 | retval = -EAGAIN; | ||
237 | break; | ||
238 | } | ||
239 | |||
240 | if (signal_pending(current)) { | ||
241 | retval = -ERESTARTSYS; | ||
242 | break; | ||
243 | } | ||
244 | } while (1); | ||
245 | |||
246 | if (retval == 0) { | ||
247 | if (count == sizeof(unsigned int)) { | ||
248 | retval = put_user(irq_data, (unsigned int __user *)buf); | ||
249 | if (retval == 0) | ||
250 | retval = sizeof(unsigned int); | ||
251 | } else { | ||
252 | retval = put_user(irq_data, (unsigned long __user *)buf); | ||
253 | if (retval == 0) | ||
254 | retval = sizeof(unsigned long); | ||
255 | } | ||
256 | |||
257 | } | ||
258 | |||
259 | __set_current_state(TASK_RUNNING); | ||
260 | remove_wait_queue(&rtc_wait, &wait); | ||
261 | |||
262 | return retval; | ||
263 | } | ||
264 | |||
265 | static unsigned int rtc_poll(struct file *file, struct poll_table_struct *table) | ||
266 | { | ||
267 | poll_wait(file, &rtc_wait, table); | ||
268 | |||
269 | if (rtc_irq_data != 0) | ||
270 | return POLLIN | POLLRDNORM; | ||
271 | |||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, rtc_callfrom_t from) | ||
276 | { | ||
277 | struct rtc_time time; | ||
278 | unsigned long count; | ||
279 | |||
280 | switch (cmd) { | ||
281 | case RTC_AIE_ON: | ||
282 | enable_irq(ELAPSEDTIME_IRQ); | ||
283 | break; | ||
284 | case RTC_AIE_OFF: | ||
285 | disable_irq(ELAPSEDTIME_IRQ); | ||
286 | break; | ||
287 | case RTC_PIE_ON: | ||
288 | enable_irq(RTCLONG1_IRQ); | ||
289 | break; | ||
290 | case RTC_PIE_OFF: | ||
291 | disable_irq(RTCLONG1_IRQ); | ||
292 | break; | ||
293 | case RTC_ALM_SET: | ||
294 | if (copy_from_user(&time, (struct rtc_time __user *)arg, | ||
295 | sizeof(struct rtc_time))) | ||
296 | return -EFAULT; | ||
297 | |||
298 | set_alarm(&time); | ||
299 | break; | ||
300 | case RTC_ALM_READ: | ||
301 | memset(&time, 0, sizeof(struct rtc_time)); | ||
302 | read_alarm(&time); | ||
303 | break; | ||
304 | case RTC_RD_TIME: | ||
305 | memset(&time, 0, sizeof(struct rtc_time)); | ||
306 | read_time(&time); | ||
307 | if (copy_to_user((void __user *)arg, &time, sizeof(struct rtc_time))) | ||
308 | return -EFAULT; | ||
309 | break; | ||
310 | case RTC_SET_TIME: | ||
311 | if (capable(CAP_SYS_TIME) == 0) | ||
312 | return -EACCES; | ||
313 | |||
314 | if (copy_from_user(&time, (struct rtc_time __user *)arg, | ||
315 | sizeof(struct rtc_time))) | ||
316 | return -EFAULT; | ||
317 | |||
318 | set_time(&time); | ||
319 | break; | ||
320 | case RTC_IRQP_READ: | ||
321 | return put_user(periodic_frequency, (unsigned long __user *)arg); | ||
322 | break; | ||
323 | case RTC_IRQP_SET: | ||
324 | if (arg > MAX_PERIODIC_RATE) | ||
325 | return -EINVAL; | ||
326 | |||
327 | if (from == FUNCTION_RTC_IOCTL && arg > MAX_USER_PERIODIC_RATE && | ||
328 | capable(CAP_SYS_RESOURCE) == 0) | ||
329 | return -EACCES; | ||
330 | |||
331 | periodic_frequency = arg; | ||
332 | |||
333 | count = RTC_FREQUENCY; | ||
334 | do_div(count, arg); | ||
335 | |||
336 | periodic_count = count; | ||
337 | |||
338 | spin_lock_irq(&rtc_lock); | ||
339 | |||
340 | rtc1_write(RTCL1LREG, count); | ||
341 | rtc1_write(RTCL1HREG, count >> 16); | ||
342 | |||
343 | spin_unlock_irq(&rtc_lock); | ||
344 | break; | ||
345 | case RTC_EPOCH_READ: | ||
346 | return put_user(epoch, (unsigned long __user *)arg); | ||
347 | case RTC_EPOCH_SET: | ||
348 | /* Doesn't support before 1900 */ | ||
349 | if (arg < 1900) | ||
350 | return -EINVAL; | ||
351 | |||
352 | if (capable(CAP_SYS_TIME) == 0) | ||
353 | return -EACCES; | ||
354 | |||
355 | epoch = arg; | ||
356 | break; | ||
357 | default: | ||
358 | return -EINVAL; | ||
359 | } | ||
360 | |||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
365 | unsigned long arg) | ||
366 | { | ||
367 | return rtc_do_ioctl(cmd, arg, FUNCTION_RTC_IOCTL); | ||
368 | } | ||
369 | |||
370 | static int rtc_open(struct inode *inode, struct file *file) | ||
371 | { | ||
372 | spin_lock_irq(&rtc_lock); | ||
373 | |||
374 | if (rtc_status == RTC_OPEN) { | ||
375 | spin_unlock_irq(&rtc_lock); | ||
376 | return -EBUSY; | ||
377 | } | ||
378 | |||
379 | rtc_status = RTC_OPEN; | ||
380 | rtc_irq_data = 0; | ||
381 | |||
382 | spin_unlock_irq(&rtc_lock); | ||
383 | |||
384 | return 0; | ||
385 | } | ||
386 | |||
387 | static int rtc_release(struct inode *inode, struct file *file) | ||
388 | { | ||
389 | if (file->f_flags & FASYNC) | ||
390 | (void)fasync_helper(-1, file, 0, &rtc_async_queue); | ||
391 | |||
392 | spin_lock_irq(&rtc_lock); | ||
393 | |||
394 | rtc1_write(ECMPLREG, 0); | ||
395 | rtc1_write(ECMPMREG, 0); | ||
396 | rtc1_write(ECMPHREG, 0); | ||
397 | rtc1_write(RTCL1LREG, 0); | ||
398 | rtc1_write(RTCL1HREG, 0); | ||
399 | |||
400 | rtc_status = RTC_RELEASE; | ||
401 | |||
402 | spin_unlock_irq(&rtc_lock); | ||
403 | |||
404 | disable_irq(ELAPSEDTIME_IRQ); | ||
405 | disable_irq(RTCLONG1_IRQ); | ||
406 | |||
407 | return 0; | ||
408 | } | ||
409 | |||
410 | static int rtc_fasync(int fd, struct file *file, int on) | ||
411 | { | ||
412 | return fasync_helper(fd, file, on, &rtc_async_queue); | ||
413 | } | ||
414 | |||
415 | static struct file_operations rtc_fops = { | ||
416 | .owner = THIS_MODULE, | ||
417 | .llseek = no_llseek, | ||
418 | .read = rtc_read, | ||
419 | .poll = rtc_poll, | ||
420 | .ioctl = rtc_ioctl, | ||
421 | .open = rtc_open, | ||
422 | .release = rtc_release, | ||
423 | .fasync = rtc_fasync, | ||
424 | }; | ||
425 | |||
426 | static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
427 | { | ||
428 | spin_lock(&rtc_lock); | ||
429 | rtc2_write(RTCINTREG, ELAPSEDTIME_INT); | ||
430 | |||
431 | rtc_irq_data += 0x100; | ||
432 | rtc_irq_data &= ~0xff; | ||
433 | rtc_irq_data |= RTC_AF; | ||
434 | spin_unlock(&rtc_lock); | ||
435 | |||
436 | spin_lock(&rtc_lock); | ||
437 | if (rtc_callback) | ||
438 | rtc_callback->func(rtc_callback->private_data); | ||
439 | spin_unlock(&rtc_lock); | ||
440 | |||
441 | wake_up_interruptible(&rtc_wait); | ||
442 | |||
443 | kill_fasync(&rtc_async_queue, SIGIO, POLL_IN); | ||
444 | |||
445 | return IRQ_HANDLED; | ||
446 | } | ||
447 | |||
448 | static irqreturn_t rtclong1_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
449 | { | ||
450 | unsigned long count = periodic_count; | ||
451 | |||
452 | spin_lock(&rtc_lock); | ||
453 | rtc2_write(RTCINTREG, RTCLONG1_INT); | ||
454 | |||
455 | rtc1_write(RTCL1LREG, count); | ||
456 | rtc1_write(RTCL1HREG, count >> 16); | ||
457 | |||
458 | rtc_irq_data += 0x100; | ||
459 | rtc_irq_data &= ~0xff; | ||
460 | rtc_irq_data |= RTC_PF; | ||
461 | spin_unlock(&rtc_lock); | ||
462 | |||
463 | spin_lock(&rtc_task_lock); | ||
464 | if (rtc_callback) | ||
465 | rtc_callback->func(rtc_callback->private_data); | ||
466 | spin_unlock(&rtc_task_lock); | ||
467 | |||
468 | wake_up_interruptible(&rtc_wait); | ||
469 | |||
470 | kill_fasync(&rtc_async_queue, SIGIO, POLL_IN); | ||
471 | |||
472 | return IRQ_HANDLED; | ||
473 | } | ||
474 | |||
475 | int rtc_register(rtc_task_t *task) | ||
476 | { | ||
477 | if (task == NULL || task->func == NULL) | ||
478 | return -EINVAL; | ||
479 | |||
480 | spin_lock_irq(&rtc_lock); | ||
481 | if (rtc_status == RTC_OPEN) { | ||
482 | spin_unlock_irq(&rtc_lock); | ||
483 | return -EBUSY; | ||
484 | } | ||
485 | |||
486 | spin_lock(&rtc_task_lock); | ||
487 | if (rtc_callback != NULL) { | ||
488 | spin_unlock(&rtc_task_lock); | ||
489 | spin_unlock_irq(&rtc_task_lock); | ||
490 | return -EBUSY; | ||
491 | } | ||
492 | |||
493 | rtc_callback = task; | ||
494 | spin_unlock(&rtc_task_lock); | ||
495 | |||
496 | rtc_status = RTC_OPEN; | ||
497 | |||
498 | spin_unlock_irq(&rtc_lock); | ||
499 | |||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | EXPORT_SYMBOL_GPL(rtc_register); | ||
504 | |||
505 | int rtc_unregister(rtc_task_t *task) | ||
506 | { | ||
507 | spin_lock_irq(&rtc_task_lock); | ||
508 | if (task == NULL || rtc_callback != task) { | ||
509 | spin_unlock_irq(&rtc_task_lock); | ||
510 | return -ENXIO; | ||
511 | } | ||
512 | |||
513 | spin_lock(&rtc_lock); | ||
514 | |||
515 | rtc1_write(ECMPLREG, 0); | ||
516 | rtc1_write(ECMPMREG, 0); | ||
517 | rtc1_write(ECMPHREG, 0); | ||
518 | rtc1_write(RTCL1LREG, 0); | ||
519 | rtc1_write(RTCL1HREG, 0); | ||
520 | |||
521 | rtc_status = RTC_RELEASE; | ||
522 | |||
523 | spin_unlock(&rtc_lock); | ||
524 | |||
525 | rtc_callback = NULL; | ||
526 | |||
527 | spin_unlock_irq(&rtc_task_lock); | ||
528 | |||
529 | disable_irq(ELAPSEDTIME_IRQ); | ||
530 | disable_irq(RTCLONG1_IRQ); | ||
531 | |||
532 | return 0; | ||
533 | } | ||
534 | |||
535 | EXPORT_SYMBOL_GPL(rtc_unregister); | ||
536 | |||
537 | int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg) | ||
538 | { | ||
539 | int retval = 0; | ||
540 | |||
541 | spin_lock_irq(&rtc_task_lock); | ||
542 | |||
543 | if (rtc_callback != task) | ||
544 | retval = -ENXIO; | ||
545 | else | ||
546 | rtc_do_ioctl(cmd, arg, FUNCTION_RTC_CONTROL); | ||
547 | |||
548 | spin_unlock_irq(&rtc_task_lock); | ||
549 | |||
550 | return retval; | ||
551 | } | ||
552 | |||
553 | EXPORT_SYMBOL_GPL(rtc_control); | ||
554 | |||
555 | static struct miscdevice rtc_miscdevice = { | ||
556 | .minor = RTC_MINOR, | ||
557 | .name = rtc_name, | ||
558 | .fops = &rtc_fops, | ||
559 | }; | ||
560 | |||
561 | static int __devinit rtc_probe(struct platform_device *pdev) | ||
562 | { | ||
563 | unsigned int irq; | ||
564 | int retval; | ||
565 | |||
566 | if (pdev->num_resources != 2) | ||
567 | return -EBUSY; | ||
568 | |||
569 | rtc1_base = ioremap(pdev->resource[0].start, RTC1_SIZE); | ||
570 | if (rtc1_base == NULL) | ||
571 | return -EBUSY; | ||
572 | |||
573 | rtc2_base = ioremap(pdev->resource[1].start, RTC2_SIZE); | ||
574 | if (rtc2_base == NULL) { | ||
575 | iounmap(rtc1_base); | ||
576 | rtc1_base = NULL; | ||
577 | return -EBUSY; | ||
578 | } | ||
579 | |||
580 | retval = misc_register(&rtc_miscdevice); | ||
581 | if (retval < 0) { | ||
582 | iounmap(rtc1_base); | ||
583 | iounmap(rtc2_base); | ||
584 | rtc1_base = NULL; | ||
585 | rtc2_base = NULL; | ||
586 | return retval; | ||
587 | } | ||
588 | |||
589 | spin_lock_irq(&rtc_lock); | ||
590 | |||
591 | rtc1_write(ECMPLREG, 0); | ||
592 | rtc1_write(ECMPMREG, 0); | ||
593 | rtc1_write(ECMPHREG, 0); | ||
594 | rtc1_write(RTCL1LREG, 0); | ||
595 | rtc1_write(RTCL1HREG, 0); | ||
596 | |||
597 | rtc_status = RTC_RELEASE; | ||
598 | rtc_irq_data = 0; | ||
599 | |||
600 | spin_unlock_irq(&rtc_lock); | ||
601 | |||
602 | init_waitqueue_head(&rtc_wait); | ||
603 | |||
604 | irq = ELAPSEDTIME_IRQ; | ||
605 | retval = request_irq(irq, elapsedtime_interrupt, SA_INTERRUPT, | ||
606 | "elapsed_time", NULL); | ||
607 | if (retval == 0) { | ||
608 | irq = RTCLONG1_IRQ; | ||
609 | retval = request_irq(irq, rtclong1_interrupt, SA_INTERRUPT, | ||
610 | "rtclong1", NULL); | ||
611 | } | ||
612 | |||
613 | if (retval < 0) { | ||
614 | printk(KERN_ERR "rtc: IRQ%d is busy\n", irq); | ||
615 | if (irq == RTCLONG1_IRQ) | ||
616 | free_irq(ELAPSEDTIME_IRQ, NULL); | ||
617 | iounmap(rtc1_base); | ||
618 | iounmap(rtc2_base); | ||
619 | rtc1_base = NULL; | ||
620 | rtc2_base = NULL; | ||
621 | return retval; | ||
622 | } | ||
623 | |||
624 | disable_irq(ELAPSEDTIME_IRQ); | ||
625 | disable_irq(RTCLONG1_IRQ); | ||
626 | |||
627 | spin_lock_init(&rtc_task_lock); | ||
628 | |||
629 | printk(KERN_INFO "rtc: Real Time Clock of NEC VR4100 series\n"); | ||
630 | |||
631 | return 0; | ||
632 | } | ||
633 | |||
634 | static int __devexit rtc_remove(struct platform_device *dev) | ||
635 | { | ||
636 | int retval; | ||
637 | |||
638 | retval = misc_deregister(&rtc_miscdevice); | ||
639 | if (retval < 0) | ||
640 | return retval; | ||
641 | |||
642 | free_irq(ELAPSEDTIME_IRQ, NULL); | ||
643 | free_irq(RTCLONG1_IRQ, NULL); | ||
644 | if (rtc1_base != NULL) | ||
645 | iounmap(rtc1_base); | ||
646 | if (rtc2_base != NULL) | ||
647 | iounmap(rtc2_base); | ||
648 | |||
649 | return 0; | ||
650 | } | ||
651 | |||
652 | static struct platform_device *rtc_platform_device; | ||
653 | |||
654 | static struct platform_driver rtc_device_driver = { | ||
655 | .probe = rtc_probe, | ||
656 | .remove = __devexit_p(rtc_remove), | ||
657 | .driver = { | ||
658 | .name = rtc_name, | ||
659 | .owner = THIS_MODULE, | ||
660 | }, | ||
661 | }; | ||
662 | |||
663 | static int __init vr41xx_rtc_init(void) | ||
664 | { | ||
665 | int retval; | ||
666 | |||
667 | switch (current_cpu_data.cputype) { | ||
668 | case CPU_VR4111: | ||
669 | case CPU_VR4121: | ||
670 | rtc_resource[0].start = RTC1_TYPE1_START; | ||
671 | rtc_resource[0].end = RTC1_TYPE1_END; | ||
672 | rtc_resource[1].start = RTC2_TYPE1_START; | ||
673 | rtc_resource[1].end = RTC2_TYPE1_END; | ||
674 | break; | ||
675 | case CPU_VR4122: | ||
676 | case CPU_VR4131: | ||
677 | case CPU_VR4133: | ||
678 | rtc_resource[0].start = RTC1_TYPE2_START; | ||
679 | rtc_resource[0].end = RTC1_TYPE2_END; | ||
680 | rtc_resource[1].start = RTC2_TYPE2_START; | ||
681 | rtc_resource[1].end = RTC2_TYPE2_END; | ||
682 | break; | ||
683 | default: | ||
684 | return -ENODEV; | ||
685 | break; | ||
686 | } | ||
687 | |||
688 | rtc_platform_device = platform_device_alloc("RTC", -1); | ||
689 | if (!rtc_platform_device) | ||
690 | return -ENOMEM; | ||
691 | |||
692 | retval = platform_device_add_resources(rtc_platform_device, | ||
693 | rtc_resource, ARRAY_SIZE(rtc_resource)); | ||
694 | |||
695 | if (retval == 0) | ||
696 | retval = platform_device_add(rtc_platform_device); | ||
697 | |||
698 | if (retval < 0) { | ||
699 | platform_device_put(rtc_platform_device); | ||
700 | return retval; | ||
701 | } | ||
702 | |||
703 | retval = platform_driver_register(&rtc_device_driver); | ||
704 | if (retval < 0) | ||
705 | platform_device_unregister(rtc_platform_device); | ||
706 | |||
707 | return retval; | ||
708 | } | ||
709 | |||
710 | static void __exit vr41xx_rtc_exit(void) | ||
711 | { | ||
712 | platform_driver_unregister(&rtc_device_driver); | ||
713 | platform_device_unregister(rtc_platform_device); | ||
714 | } | ||
715 | |||
716 | module_init(vr41xx_rtc_init); | ||
717 | module_exit(vr41xx_rtc_exit); | ||
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index ca4844c527da..6c94879e0b99 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -2328,6 +2328,10 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) | |||
2328 | case TIOCL_SETVESABLANK: | 2328 | case TIOCL_SETVESABLANK: |
2329 | set_vesa_blanking(p); | 2329 | set_vesa_blanking(p); |
2330 | break; | 2330 | break; |
2331 | case TIOCL_GETKMSGREDIRECT: | ||
2332 | data = kmsg_redirect; | ||
2333 | ret = __put_user(data, p); | ||
2334 | break; | ||
2331 | case TIOCL_SETKMSGREDIRECT: | 2335 | case TIOCL_SETKMSGREDIRECT: |
2332 | if (!capable(CAP_SYS_ADMIN)) { | 2336 | if (!capable(CAP_SYS_ADMIN)) { |
2333 | ret = -EPERM; | 2337 | ret = -EPERM; |
@@ -3234,14 +3238,6 @@ void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org) | |||
3234 | } | 3238 | } |
3235 | } | 3239 | } |
3236 | 3240 | ||
3237 | int is_console_suspend_safe(void) | ||
3238 | { | ||
3239 | /* It is unsafe to suspend devices while X has control of the | ||
3240 | * hardware. Make sure we are running on a kernel-controlled console. | ||
3241 | */ | ||
3242 | return vc_cons[fg_console].d->vc_mode == KD_TEXT; | ||
3243 | } | ||
3244 | |||
3245 | /* | 3241 | /* |
3246 | * Visible symbols for modules | 3242 | * Visible symbols for modules |
3247 | */ | 3243 | */ |
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 16e99db2e12d..d53f664a4dd8 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig | |||
@@ -60,6 +60,13 @@ config SOFT_WATCHDOG | |||
60 | 60 | ||
61 | # ARM Architecture | 61 | # ARM Architecture |
62 | 62 | ||
63 | config AT91_WATCHDOG | ||
64 | tristate "AT91RM9200 watchdog" | ||
65 | depends on WATCHDOG && ARCH_AT91RM9200 | ||
66 | help | ||
67 | Watchdog timer embedded into AT91RM9200 chips. This will reboot your | ||
68 | system when the timeout is reached. | ||
69 | |||
63 | config 21285_WATCHDOG | 70 | config 21285_WATCHDOG |
64 | tristate "DC21285 watchdog" | 71 | tristate "DC21285 watchdog" |
65 | depends on WATCHDOG && FOOTBRIDGE | 72 | depends on WATCHDOG && FOOTBRIDGE |
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index d6f27fde9905..6ab77b61a643 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile | |||
@@ -23,6 +23,7 @@ obj-$(CONFIG_WDTPCI) += wdt_pci.o | |||
23 | obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o | 23 | obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o |
24 | 24 | ||
25 | # ARM Architecture | 25 | # ARM Architecture |
26 | obj-$(CONFIG_AT91_WATCHDOG) += at91_wdt.o | ||
26 | obj-$(CONFIG_21285_WATCHDOG) += wdt285.o | 27 | obj-$(CONFIG_21285_WATCHDOG) += wdt285.o |
27 | obj-$(CONFIG_977_WATCHDOG) += wdt977.o | 28 | obj-$(CONFIG_977_WATCHDOG) += wdt977.o |
28 | obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o | 29 | obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o |
diff --git a/drivers/char/watchdog/at91_wdt.c b/drivers/char/watchdog/at91_wdt.c new file mode 100644 index 000000000000..ac83bc4b019a --- /dev/null +++ b/drivers/char/watchdog/at91_wdt.c | |||
@@ -0,0 +1,228 @@ | |||
1 | /* | ||
2 | * Watchdog driver for Atmel AT91RM9200 (Thunder) | ||
3 | * | ||
4 | * Copyright (C) 2003 SAN People (Pty) Ltd | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <linux/errno.h> | ||
14 | #include <linux/fs.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/miscdevice.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/moduleparam.h> | ||
20 | #include <linux/types.h> | ||
21 | #include <linux/watchdog.h> | ||
22 | #include <asm/bitops.h> | ||
23 | #include <asm/uaccess.h> | ||
24 | |||
25 | |||
26 | #define WDT_DEFAULT_TIME 5 /* 5 seconds */ | ||
27 | #define WDT_MAX_TIME 256 /* 256 seconds */ | ||
28 | |||
29 | static int wdt_time = WDT_DEFAULT_TIME; | ||
30 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
31 | |||
32 | module_param(wdt_time, int, 0); | ||
33 | MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")"); | ||
34 | |||
35 | module_param(nowayout, int, 0); | ||
36 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
37 | |||
38 | |||
39 | static unsigned long at91wdt_busy; | ||
40 | |||
41 | /* ......................................................................... */ | ||
42 | |||
43 | /* | ||
44 | * Disable the watchdog. | ||
45 | */ | ||
46 | static void inline at91_wdt_stop(void) | ||
47 | { | ||
48 | at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN); | ||
49 | } | ||
50 | |||
51 | /* | ||
52 | * Enable and reset the watchdog. | ||
53 | */ | ||
54 | static void inline at91_wdt_start(void) | ||
55 | { | ||
56 | at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN | (((65536 * wdt_time) >> 8) & AT91_ST_WDV)); | ||
57 | at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); | ||
58 | } | ||
59 | |||
60 | /* | ||
61 | * Reload the watchdog timer. (ie, pat the watchdog) | ||
62 | */ | ||
63 | static void inline at91_wdt_reload(void) | ||
64 | { | ||
65 | at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); | ||
66 | } | ||
67 | |||
68 | /* ......................................................................... */ | ||
69 | |||
70 | /* | ||
71 | * Watchdog device is opened, and watchdog starts running. | ||
72 | */ | ||
73 | static int at91_wdt_open(struct inode *inode, struct file *file) | ||
74 | { | ||
75 | if (test_and_set_bit(0, &at91wdt_busy)) | ||
76 | return -EBUSY; | ||
77 | |||
78 | at91_wdt_start(); | ||
79 | return nonseekable_open(inode, file); | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * Close the watchdog device. | ||
84 | * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also | ||
85 | * disabled. | ||
86 | */ | ||
87 | static int at91_wdt_close(struct inode *inode, struct file *file) | ||
88 | { | ||
89 | if (!nowayout) | ||
90 | at91_wdt_stop(); /* Disable the watchdog when file is closed */ | ||
91 | |||
92 | clear_bit(0, &at91wdt_busy); | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Change the watchdog time interval. | ||
98 | */ | ||
99 | static int at91_wdt_settimeout(int new_time) | ||
100 | { | ||
101 | /* | ||
102 | * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz | ||
103 | * | ||
104 | * Since WDV is a 16-bit counter, the maximum period is | ||
105 | * 65536 / 0.256 = 256 seconds. | ||
106 | */ | ||
107 | if ((new_time <= 0) || (new_time > WDT_MAX_TIME)) | ||
108 | return -EINVAL; | ||
109 | |||
110 | /* Set new watchdog time. It will be used when at91_wdt_start() is called. */ | ||
111 | wdt_time = new_time; | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static struct watchdog_info at91_wdt_info = { | ||
116 | .identity = "at91 watchdog", | ||
117 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | ||
118 | }; | ||
119 | |||
120 | /* | ||
121 | * Handle commands from user-space. | ||
122 | */ | ||
123 | static int at91_wdt_ioctl(struct inode *inode, struct file *file, | ||
124 | unsigned int cmd, unsigned long arg) | ||
125 | { | ||
126 | void __user *argp = (void __user *)arg; | ||
127 | int __user *p = argp; | ||
128 | int new_value; | ||
129 | |||
130 | switch(cmd) { | ||
131 | case WDIOC_KEEPALIVE: | ||
132 | at91_wdt_reload(); /* pat the watchdog */ | ||
133 | return 0; | ||
134 | |||
135 | case WDIOC_GETSUPPORT: | ||
136 | return copy_to_user(argp, &at91_wdt_info, sizeof(at91_wdt_info)) ? -EFAULT : 0; | ||
137 | |||
138 | case WDIOC_SETTIMEOUT: | ||
139 | if (get_user(new_value, p)) | ||
140 | return -EFAULT; | ||
141 | |||
142 | if (at91_wdt_settimeout(new_value)) | ||
143 | return -EINVAL; | ||
144 | |||
145 | /* Enable new time value */ | ||
146 | at91_wdt_start(); | ||
147 | |||
148 | /* Return current value */ | ||
149 | return put_user(wdt_time, p); | ||
150 | |||
151 | case WDIOC_GETTIMEOUT: | ||
152 | return put_user(wdt_time, p); | ||
153 | |||
154 | case WDIOC_GETSTATUS: | ||
155 | case WDIOC_GETBOOTSTATUS: | ||
156 | return put_user(0, p); | ||
157 | |||
158 | case WDIOC_SETOPTIONS: | ||
159 | if (get_user(new_value, p)) | ||
160 | return -EFAULT; | ||
161 | |||
162 | if (new_value & WDIOS_DISABLECARD) | ||
163 | at91_wdt_stop(); | ||
164 | if (new_value & WDIOS_ENABLECARD) | ||
165 | at91_wdt_start(); | ||
166 | return 0; | ||
167 | |||
168 | default: | ||
169 | return -ENOIOCTLCMD; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | /* | ||
174 | * Pat the watchdog whenever device is written to. | ||
175 | */ | ||
176 | static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) | ||
177 | { | ||
178 | at91_wdt_reload(); /* pat the watchdog */ | ||
179 | return len; | ||
180 | } | ||
181 | |||
182 | /* ......................................................................... */ | ||
183 | |||
184 | static struct file_operations at91wdt_fops = { | ||
185 | .owner = THIS_MODULE, | ||
186 | .llseek = no_llseek, | ||
187 | .ioctl = at91_wdt_ioctl, | ||
188 | .open = at91_wdt_open, | ||
189 | .release = at91_wdt_close, | ||
190 | .write = at91_wdt_write, | ||
191 | }; | ||
192 | |||
193 | static struct miscdevice at91wdt_miscdev = { | ||
194 | .minor = WATCHDOG_MINOR, | ||
195 | .name = "watchdog", | ||
196 | .fops = &at91wdt_fops, | ||
197 | }; | ||
198 | |||
199 | static int __init at91_wdt_init(void) | ||
200 | { | ||
201 | int res; | ||
202 | |||
203 | /* Check that the heartbeat value is within range; if not reset to the default */ | ||
204 | if (at91_wdt_settimeout(wdt_time)) { | ||
205 | at91_wdt_settimeout(WDT_DEFAULT_TIME); | ||
206 | printk(KERN_INFO "at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time); | ||
207 | } | ||
208 | |||
209 | res = misc_register(&at91wdt_miscdev); | ||
210 | if (res) | ||
211 | return res; | ||
212 | |||
213 | printk("AT91 Watchdog Timer enabled (%d seconds, nowayout=%d)\n", wdt_time, nowayout); | ||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static void __exit at91_wdt_exit(void) | ||
218 | { | ||
219 | misc_deregister(&at91wdt_miscdev); | ||
220 | } | ||
221 | |||
222 | module_init(at91_wdt_init); | ||
223 | module_exit(at91_wdt_exit); | ||
224 | |||
225 | MODULE_AUTHOR("Andrew Victor"); | ||
226 | MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200"); | ||
227 | MODULE_LICENSE("GPL"); | ||
228 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c index a13395e2c372..fa2ba9ebe42a 100644 --- a/drivers/char/watchdog/i8xx_tco.c +++ b/drivers/char/watchdog/i8xx_tco.c | |||
@@ -33,11 +33,6 @@ | |||
33 | * 82801E (C-ICH) : document number 273599-001, 273645-002, | 33 | * 82801E (C-ICH) : document number 273599-001, 273645-002, |
34 | * 82801EB (ICH5) : document number 252516-001, 252517-003, | 34 | * 82801EB (ICH5) : document number 252516-001, 252517-003, |
35 | * 82801ER (ICH5R) : document number 252516-001, 252517-003, | 35 | * 82801ER (ICH5R) : document number 252516-001, 252517-003, |
36 | * 82801FB (ICH6) : document number 301473-002, 301474-007, | ||
37 | * 82801FR (ICH6R) : document number 301473-002, 301474-007, | ||
38 | * 82801FBM (ICH6-M) : document number 301473-002, 301474-007, | ||
39 | * 82801FW (ICH6W) : document number 301473-001, 301474-007, | ||
40 | * 82801FRW (ICH6RW) : document number 301473-001, 301474-007 | ||
41 | * | 36 | * |
42 | * 20000710 Nils Faerber | 37 | * 20000710 Nils Faerber |
43 | * Initial Version 0.01 | 38 | * Initial Version 0.01 |
@@ -66,6 +61,10 @@ | |||
66 | * 20050807 Wim Van Sebroeck <wim@iguana.be> | 61 | * 20050807 Wim Van Sebroeck <wim@iguana.be> |
67 | * 0.08 Make sure that the watchdog is only "armed" when started. | 62 | * 0.08 Make sure that the watchdog is only "armed" when started. |
68 | * (Kernel Bug 4251) | 63 | * (Kernel Bug 4251) |
64 | * 20060416 Wim Van Sebroeck <wim@iguana.be> | ||
65 | * 0.09 Remove support for the ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW and | ||
66 | * ICH7 chipsets. (See Kernel Bug 6031 - other code will support these | ||
67 | * chipsets) | ||
69 | */ | 68 | */ |
70 | 69 | ||
71 | /* | 70 | /* |
@@ -90,7 +89,7 @@ | |||
90 | #include "i8xx_tco.h" | 89 | #include "i8xx_tco.h" |
91 | 90 | ||
92 | /* Module and version information */ | 91 | /* Module and version information */ |
93 | #define TCO_VERSION "0.08" | 92 | #define TCO_VERSION "0.09" |
94 | #define TCO_MODULE_NAME "i8xx TCO timer" | 93 | #define TCO_MODULE_NAME "i8xx TCO timer" |
95 | #define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION | 94 | #define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION |
96 | #define PFX TCO_MODULE_NAME ": " | 95 | #define PFX TCO_MODULE_NAME ": " |
@@ -391,11 +390,6 @@ static struct pci_device_id i8xx_tco_pci_tbl[] = { | |||
391 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, PCI_ANY_ID, PCI_ANY_ID, }, | 390 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, PCI_ANY_ID, PCI_ANY_ID, }, |
392 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, }, | 391 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, }, |
393 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, }, | 392 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, }, |
394 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, PCI_ANY_ID, PCI_ANY_ID, }, | ||
395 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, PCI_ANY_ID, PCI_ANY_ID, }, | ||
396 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, }, | ||
397 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, }, | ||
398 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, }, | ||
399 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, PCI_ANY_ID, PCI_ANY_ID, }, | 393 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, PCI_ANY_ID, PCI_ANY_ID, }, |
400 | { 0, }, /* End of list */ | 394 | { 0, }, /* End of list */ |
401 | }; | 395 | }; |
diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c index 8d6b249ad66b..6d44ca68312d 100644 --- a/drivers/char/watchdog/pcwd.c +++ b/drivers/char/watchdog/pcwd.c | |||
@@ -66,15 +66,13 @@ | |||
66 | #include <linux/fs.h> /* For file operations */ | 66 | #include <linux/fs.h> /* For file operations */ |
67 | #include <linux/ioport.h> /* For io-port access */ | 67 | #include <linux/ioport.h> /* For io-port access */ |
68 | #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ | 68 | #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ |
69 | #include <linux/sched.h> /* TASK_INTERRUPTIBLE, set_current_state() and friends */ | ||
70 | #include <linux/slab.h> /* For kmalloc */ | ||
71 | 69 | ||
72 | #include <asm/uaccess.h> /* For copy_to_user/put_user/... */ | 70 | #include <asm/uaccess.h> /* For copy_to_user/put_user/... */ |
73 | #include <asm/io.h> /* For inb/outb/... */ | 71 | #include <asm/io.h> /* For inb/outb/... */ |
74 | 72 | ||
75 | /* Module and version information */ | 73 | /* Module and version information */ |
76 | #define WATCHDOG_VERSION "1.16" | 74 | #define WATCHDOG_VERSION "1.17" |
77 | #define WATCHDOG_DATE "03 Jan 2006" | 75 | #define WATCHDOG_DATE "12 Feb 2006" |
78 | #define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog" | 76 | #define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog" |
79 | #define WATCHDOG_NAME "pcwd" | 77 | #define WATCHDOG_NAME "pcwd" |
80 | #define PFX WATCHDOG_NAME ": " | 78 | #define PFX WATCHDOG_NAME ": " |
@@ -96,15 +94,19 @@ | |||
96 | * PCI-PC Watchdog card. | 94 | * PCI-PC Watchdog card. |
97 | */ | 95 | */ |
98 | /* Port 1 : Control Status #1 for the PC Watchdog card, revision A. */ | 96 | /* Port 1 : Control Status #1 for the PC Watchdog card, revision A. */ |
99 | #define WD_WDRST 0x01 /* Previously reset state */ | 97 | #define WD_WDRST 0x01 /* Previously reset state */ |
100 | #define WD_T110 0x02 /* Temperature overheat sense */ | 98 | #define WD_T110 0x02 /* Temperature overheat sense */ |
101 | #define WD_HRTBT 0x04 /* Heartbeat sense */ | 99 | #define WD_HRTBT 0x04 /* Heartbeat sense */ |
102 | #define WD_RLY2 0x08 /* External relay triggered */ | 100 | #define WD_RLY2 0x08 /* External relay triggered */ |
103 | #define WD_SRLY2 0x80 /* Software external relay triggered */ | 101 | #define WD_SRLY2 0x80 /* Software external relay triggered */ |
104 | /* Port 1 : Control Status #1 for the PC Watchdog card, revision C. */ | 102 | /* Port 1 : Control Status #1 for the PC Watchdog card, revision C. */ |
105 | #define WD_REVC_WTRP 0x01 /* Watchdog Trip status */ | 103 | #define WD_REVC_WTRP 0x01 /* Watchdog Trip status */ |
106 | #define WD_REVC_HRBT 0x02 /* Watchdog Heartbeat */ | 104 | #define WD_REVC_HRBT 0x02 /* Watchdog Heartbeat */ |
107 | #define WD_REVC_TTRP 0x04 /* Temperature Trip status */ | 105 | #define WD_REVC_TTRP 0x04 /* Temperature Trip status */ |
106 | #define WD_REVC_RL2A 0x08 /* Relay 2 activated by on-board processor */ | ||
107 | #define WD_REVC_RL1A 0x10 /* Relay 1 active */ | ||
108 | #define WD_REVC_R2DS 0x40 /* Relay 2 disable */ | ||
109 | #define WD_REVC_RLY2 0x80 /* Relay 2 activated? */ | ||
108 | /* Port 2 : Control Status #2 */ | 110 | /* Port 2 : Control Status #2 */ |
109 | #define WD_WDIS 0x10 /* Watchdog Disabled */ | 111 | #define WD_WDIS 0x10 /* Watchdog Disabled */ |
110 | #define WD_ENTP 0x20 /* Watchdog Enable Temperature Trip */ | 112 | #define WD_ENTP 0x20 /* Watchdog Enable Temperature Trip */ |
@@ -122,9 +124,14 @@ | |||
122 | #define CMD_ISA_VERSION_HUNDRETH 0x03 | 124 | #define CMD_ISA_VERSION_HUNDRETH 0x03 |
123 | #define CMD_ISA_VERSION_MINOR 0x04 | 125 | #define CMD_ISA_VERSION_MINOR 0x04 |
124 | #define CMD_ISA_SWITCH_SETTINGS 0x05 | 126 | #define CMD_ISA_SWITCH_SETTINGS 0x05 |
127 | #define CMD_ISA_RESET_PC 0x06 | ||
128 | #define CMD_ISA_ARM_0 0x07 | ||
129 | #define CMD_ISA_ARM_30 0x08 | ||
130 | #define CMD_ISA_ARM_60 0x09 | ||
125 | #define CMD_ISA_DELAY_TIME_2SECS 0x0A | 131 | #define CMD_ISA_DELAY_TIME_2SECS 0x0A |
126 | #define CMD_ISA_DELAY_TIME_4SECS 0x0B | 132 | #define CMD_ISA_DELAY_TIME_4SECS 0x0B |
127 | #define CMD_ISA_DELAY_TIME_8SECS 0x0C | 133 | #define CMD_ISA_DELAY_TIME_8SECS 0x0C |
134 | #define CMD_ISA_RESET_RELAYS 0x0D | ||
128 | 135 | ||
129 | /* | 136 | /* |
130 | * We are using an kernel timer to do the pinging of the watchdog | 137 | * We are using an kernel timer to do the pinging of the watchdog |
@@ -142,6 +149,7 @@ static atomic_t open_allowed = ATOMIC_INIT(1); | |||
142 | static char expect_close; | 149 | static char expect_close; |
143 | static int temp_panic; | 150 | static int temp_panic; |
144 | static struct { /* this is private data for each ISA-PC watchdog card */ | 151 | static struct { /* this is private data for each ISA-PC watchdog card */ |
152 | char fw_ver_str[6]; /* The cards firmware version */ | ||
145 | int revision; /* The card's revision */ | 153 | int revision; /* The card's revision */ |
146 | int supports_temp; /* Wether or not the card has a temperature device */ | 154 | int supports_temp; /* Wether or not the card has a temperature device */ |
147 | int command_mode; /* Wether or not the card is in command mode */ | 155 | int command_mode; /* Wether or not the card is in command mode */ |
@@ -153,6 +161,13 @@ static struct { /* this is private data for each ISA-PC watchdog card */ | |||
153 | } pcwd_private; | 161 | } pcwd_private; |
154 | 162 | ||
155 | /* module parameters */ | 163 | /* module parameters */ |
164 | #define QUIET 0 /* Default */ | ||
165 | #define VERBOSE 1 /* Verbose */ | ||
166 | #define DEBUG 2 /* print fancy stuff too */ | ||
167 | static int debug = QUIET; | ||
168 | module_param(debug, int, 0); | ||
169 | MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)"); | ||
170 | |||
156 | #define WATCHDOG_HEARTBEAT 60 /* 60 sec default heartbeat */ | 171 | #define WATCHDOG_HEARTBEAT 60 /* 60 sec default heartbeat */ |
157 | static int heartbeat = WATCHDOG_HEARTBEAT; | 172 | static int heartbeat = WATCHDOG_HEARTBEAT; |
158 | module_param(heartbeat, int, 0); | 173 | module_param(heartbeat, int, 0); |
@@ -172,6 +187,10 @@ static int send_isa_command(int cmd) | |||
172 | int control_status; | 187 | int control_status; |
173 | int port0, last_port0; /* Double read for stabilising */ | 188 | int port0, last_port0; /* Double read for stabilising */ |
174 | 189 | ||
190 | if (debug >= DEBUG) | ||
191 | printk(KERN_DEBUG PFX "sending following data cmd=0x%02x\n", | ||
192 | cmd); | ||
193 | |||
175 | /* The WCMD bit must be 1 and the command is only 4 bits in size */ | 194 | /* The WCMD bit must be 1 and the command is only 4 bits in size */ |
176 | control_status = (cmd & 0x0F) | WD_WCMD; | 195 | control_status = (cmd & 0x0F) | WD_WCMD; |
177 | outb_p(control_status, pcwd_private.io_addr + 2); | 196 | outb_p(control_status, pcwd_private.io_addr + 2); |
@@ -188,6 +207,10 @@ static int send_isa_command(int cmd) | |||
188 | udelay (250); | 207 | udelay (250); |
189 | } | 208 | } |
190 | 209 | ||
210 | if (debug >= DEBUG) | ||
211 | printk(KERN_DEBUG PFX "received following data for cmd=0x%02x: port0=0x%02x last_port0=0x%02x\n", | ||
212 | cmd, port0, last_port0); | ||
213 | |||
191 | return port0; | 214 | return port0; |
192 | } | 215 | } |
193 | 216 | ||
@@ -214,6 +237,10 @@ static int set_command_mode(void) | |||
214 | spin_unlock(&pcwd_private.io_lock); | 237 | spin_unlock(&pcwd_private.io_lock); |
215 | pcwd_private.command_mode = found; | 238 | pcwd_private.command_mode = found; |
216 | 239 | ||
240 | if (debug >= DEBUG) | ||
241 | printk(KERN_DEBUG PFX "command_mode=%d\n", | ||
242 | pcwd_private.command_mode); | ||
243 | |||
217 | return(found); | 244 | return(found); |
218 | } | 245 | } |
219 | 246 | ||
@@ -226,6 +253,10 @@ static void unset_command_mode(void) | |||
226 | spin_unlock(&pcwd_private.io_lock); | 253 | spin_unlock(&pcwd_private.io_lock); |
227 | 254 | ||
228 | pcwd_private.command_mode = 0; | 255 | pcwd_private.command_mode = 0; |
256 | |||
257 | if (debug >= DEBUG) | ||
258 | printk(KERN_DEBUG PFX "command_mode=%d\n", | ||
259 | pcwd_private.command_mode); | ||
229 | } | 260 | } |
230 | 261 | ||
231 | static inline void pcwd_check_temperature_support(void) | 262 | static inline void pcwd_check_temperature_support(void) |
@@ -234,27 +265,22 @@ static inline void pcwd_check_temperature_support(void) | |||
234 | pcwd_private.supports_temp = 1; | 265 | pcwd_private.supports_temp = 1; |
235 | } | 266 | } |
236 | 267 | ||
237 | static inline char *get_firmware(void) | 268 | static inline void pcwd_get_firmware(void) |
238 | { | 269 | { |
239 | int one, ten, hund, minor; | 270 | int one, ten, hund, minor; |
240 | char *ret; | ||
241 | 271 | ||
242 | ret = kmalloc(6, GFP_KERNEL); | 272 | strcpy(pcwd_private.fw_ver_str, "ERROR"); |
243 | if(ret == NULL) | ||
244 | return NULL; | ||
245 | 273 | ||
246 | if (set_command_mode()) { | 274 | if (set_command_mode()) { |
247 | one = send_isa_command(CMD_ISA_VERSION_INTEGER); | 275 | one = send_isa_command(CMD_ISA_VERSION_INTEGER); |
248 | ten = send_isa_command(CMD_ISA_VERSION_TENTH); | 276 | ten = send_isa_command(CMD_ISA_VERSION_TENTH); |
249 | hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH); | 277 | hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH); |
250 | minor = send_isa_command(CMD_ISA_VERSION_MINOR); | 278 | minor = send_isa_command(CMD_ISA_VERSION_MINOR); |
251 | sprintf(ret, "%c.%c%c%c", one, ten, hund, minor); | 279 | sprintf(pcwd_private.fw_ver_str, "%c.%c%c%c", one, ten, hund, minor); |
252 | } | 280 | } |
253 | else | ||
254 | sprintf(ret, "ERROR"); | ||
255 | |||
256 | unset_command_mode(); | 281 | unset_command_mode(); |
257 | return(ret); | 282 | |
283 | return; | ||
258 | } | 284 | } |
259 | 285 | ||
260 | static inline int pcwd_get_option_switches(void) | 286 | static inline int pcwd_get_option_switches(void) |
@@ -272,17 +298,15 @@ static inline int pcwd_get_option_switches(void) | |||
272 | 298 | ||
273 | static void pcwd_show_card_info(void) | 299 | static void pcwd_show_card_info(void) |
274 | { | 300 | { |
275 | char *firmware; | ||
276 | int option_switches; | 301 | int option_switches; |
277 | 302 | ||
278 | /* Get some extra info from the hardware (in command/debug/diag mode) */ | 303 | /* Get some extra info from the hardware (in command/debug/diag mode) */ |
279 | if (pcwd_private.revision == PCWD_REVISION_A) | 304 | if (pcwd_private.revision == PCWD_REVISION_A) |
280 | printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr); | 305 | printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr); |
281 | else if (pcwd_private.revision == PCWD_REVISION_C) { | 306 | else if (pcwd_private.revision == PCWD_REVISION_C) { |
282 | firmware = get_firmware(); | 307 | pcwd_get_firmware(); |
283 | printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n", | 308 | printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n", |
284 | pcwd_private.io_addr, firmware); | 309 | pcwd_private.io_addr, pcwd_private.fw_ver_str); |
285 | kfree(firmware); | ||
286 | option_switches = pcwd_get_option_switches(); | 310 | option_switches = pcwd_get_option_switches(); |
287 | printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", | 311 | printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", |
288 | option_switches, | 312 | option_switches, |
@@ -362,6 +386,10 @@ static int pcwd_start(void) | |||
362 | return -EIO; | 386 | return -EIO; |
363 | } | 387 | } |
364 | } | 388 | } |
389 | |||
390 | if (debug >= VERBOSE) | ||
391 | printk(KERN_DEBUG PFX "Watchdog started\n"); | ||
392 | |||
365 | return 0; | 393 | return 0; |
366 | } | 394 | } |
367 | 395 | ||
@@ -386,6 +414,10 @@ static int pcwd_stop(void) | |||
386 | return -EIO; | 414 | return -EIO; |
387 | } | 415 | } |
388 | } | 416 | } |
417 | |||
418 | if (debug >= VERBOSE) | ||
419 | printk(KERN_DEBUG PFX "Watchdog stopped\n"); | ||
420 | |||
389 | return 0; | 421 | return 0; |
390 | } | 422 | } |
391 | 423 | ||
@@ -393,6 +425,10 @@ static int pcwd_keepalive(void) | |||
393 | { | 425 | { |
394 | /* user land ping */ | 426 | /* user land ping */ |
395 | pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ); | 427 | pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ); |
428 | |||
429 | if (debug >= DEBUG) | ||
430 | printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n"); | ||
431 | |||
396 | return 0; | 432 | return 0; |
397 | } | 433 | } |
398 | 434 | ||
@@ -402,12 +438,17 @@ static int pcwd_set_heartbeat(int t) | |||
402 | return -EINVAL; | 438 | return -EINVAL; |
403 | 439 | ||
404 | heartbeat = t; | 440 | heartbeat = t; |
441 | |||
442 | if (debug >= VERBOSE) | ||
443 | printk(KERN_DEBUG PFX "New heartbeat: %d\n", | ||
444 | heartbeat); | ||
445 | |||
405 | return 0; | 446 | return 0; |
406 | } | 447 | } |
407 | 448 | ||
408 | static int pcwd_get_status(int *status) | 449 | static int pcwd_get_status(int *status) |
409 | { | 450 | { |
410 | int card_status; | 451 | int control_status; |
411 | 452 | ||
412 | *status=0; | 453 | *status=0; |
413 | spin_lock(&pcwd_private.io_lock); | 454 | spin_lock(&pcwd_private.io_lock); |
@@ -415,37 +456,39 @@ static int pcwd_get_status(int *status) | |||
415 | /* Rev A cards return status information from | 456 | /* Rev A cards return status information from |
416 | * the base register, which is used for the | 457 | * the base register, which is used for the |
417 | * temperature in other cards. */ | 458 | * temperature in other cards. */ |
418 | card_status = inb(pcwd_private.io_addr); | 459 | control_status = inb(pcwd_private.io_addr); |
419 | else { | 460 | else { |
420 | /* Rev C cards return card status in the base | 461 | /* Rev C cards return card status in the base |
421 | * address + 1 register. And use different bits | 462 | * address + 1 register. And use different bits |
422 | * to indicate a card initiated reset, and an | 463 | * to indicate a card initiated reset, and an |
423 | * over-temperature condition. And the reboot | 464 | * over-temperature condition. And the reboot |
424 | * status can be reset. */ | 465 | * status can be reset. */ |
425 | card_status = inb(pcwd_private.io_addr + 1); | 466 | control_status = inb(pcwd_private.io_addr + 1); |
426 | } | 467 | } |
427 | spin_unlock(&pcwd_private.io_lock); | 468 | spin_unlock(&pcwd_private.io_lock); |
428 | 469 | ||
429 | if (pcwd_private.revision == PCWD_REVISION_A) { | 470 | if (pcwd_private.revision == PCWD_REVISION_A) { |
430 | if (card_status & WD_WDRST) | 471 | if (control_status & WD_WDRST) |
431 | *status |= WDIOF_CARDRESET; | 472 | *status |= WDIOF_CARDRESET; |
432 | 473 | ||
433 | if (card_status & WD_T110) { | 474 | if (control_status & WD_T110) { |
434 | *status |= WDIOF_OVERHEAT; | 475 | *status |= WDIOF_OVERHEAT; |
435 | if (temp_panic) { | 476 | if (temp_panic) { |
436 | printk (KERN_INFO PFX "Temperature overheat trip!\n"); | 477 | printk (KERN_INFO PFX "Temperature overheat trip!\n"); |
437 | kernel_power_off(); | 478 | kernel_power_off(); |
479 | /* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */ | ||
438 | } | 480 | } |
439 | } | 481 | } |
440 | } else { | 482 | } else { |
441 | if (card_status & WD_REVC_WTRP) | 483 | if (control_status & WD_REVC_WTRP) |
442 | *status |= WDIOF_CARDRESET; | 484 | *status |= WDIOF_CARDRESET; |
443 | 485 | ||
444 | if (card_status & WD_REVC_TTRP) { | 486 | if (control_status & WD_REVC_TTRP) { |
445 | *status |= WDIOF_OVERHEAT; | 487 | *status |= WDIOF_OVERHEAT; |
446 | if (temp_panic) { | 488 | if (temp_panic) { |
447 | printk (KERN_INFO PFX "Temperature overheat trip!\n"); | 489 | printk (KERN_INFO PFX "Temperature overheat trip!\n"); |
448 | kernel_power_off(); | 490 | kernel_power_off(); |
491 | /* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */ | ||
449 | } | 492 | } |
450 | } | 493 | } |
451 | } | 494 | } |
@@ -455,9 +498,25 @@ static int pcwd_get_status(int *status) | |||
455 | 498 | ||
456 | static int pcwd_clear_status(void) | 499 | static int pcwd_clear_status(void) |
457 | { | 500 | { |
501 | int control_status; | ||
502 | |||
458 | if (pcwd_private.revision == PCWD_REVISION_C) { | 503 | if (pcwd_private.revision == PCWD_REVISION_C) { |
459 | spin_lock(&pcwd_private.io_lock); | 504 | spin_lock(&pcwd_private.io_lock); |
460 | outb_p(0x00, pcwd_private.io_addr + 1); /* clear reset status */ | 505 | |
506 | if (debug >= VERBOSE) | ||
507 | printk(KERN_INFO PFX "clearing watchdog trip status\n"); | ||
508 | |||
509 | control_status = inb_p(pcwd_private.io_addr + 1); | ||
510 | |||
511 | if (debug >= DEBUG) { | ||
512 | printk(KERN_DEBUG PFX "status was: 0x%02x\n", control_status); | ||
513 | printk(KERN_DEBUG PFX "sending: 0x%02x\n", | ||
514 | (control_status & WD_REVC_R2DS)); | ||
515 | } | ||
516 | |||
517 | /* clear reset status & Keep Relay 2 disable state as it is */ | ||
518 | outb_p((control_status & WD_REVC_R2DS), pcwd_private.io_addr + 1); | ||
519 | |||
461 | spin_unlock(&pcwd_private.io_lock); | 520 | spin_unlock(&pcwd_private.io_lock); |
462 | } | 521 | } |
463 | return 0; | 522 | return 0; |
@@ -481,6 +540,11 @@ static int pcwd_get_temperature(int *temperature) | |||
481 | *temperature = ((inb(pcwd_private.io_addr)) * 9 / 5) + 32; | 540 | *temperature = ((inb(pcwd_private.io_addr)) * 9 / 5) + 32; |
482 | spin_unlock(&pcwd_private.io_lock); | 541 | spin_unlock(&pcwd_private.io_lock); |
483 | 542 | ||
543 | if (debug >= DEBUG) { | ||
544 | printk(KERN_DEBUG PFX "temperature is: %d F\n", | ||
545 | *temperature); | ||
546 | } | ||
547 | |||
484 | return 0; | 548 | return 0; |
485 | } | 549 | } |
486 | 550 | ||
@@ -599,6 +663,8 @@ static ssize_t pcwd_write(struct file *file, const char __user *buf, size_t len, | |||
599 | static int pcwd_open(struct inode *inode, struct file *file) | 663 | static int pcwd_open(struct inode *inode, struct file *file) |
600 | { | 664 | { |
601 | if (!atomic_dec_and_test(&open_allowed) ) { | 665 | if (!atomic_dec_and_test(&open_allowed) ) { |
666 | if (debug >= VERBOSE) | ||
667 | printk(KERN_ERR PFX "Attempt to open already opened device.\n"); | ||
602 | atomic_inc( &open_allowed ); | 668 | atomic_inc( &open_allowed ); |
603 | return -EBUSY; | 669 | return -EBUSY; |
604 | } | 670 | } |
@@ -922,7 +988,8 @@ static void __exit pcwd_cleanup_module(void) | |||
922 | { | 988 | { |
923 | if (pcwd_private.io_addr) | 989 | if (pcwd_private.io_addr) |
924 | pcwatchdog_exit(); | 990 | pcwatchdog_exit(); |
925 | return; | 991 | |
992 | printk(KERN_INFO PFX "Watchdog Module Unloaded.\n"); | ||
926 | } | 993 | } |
927 | 994 | ||
928 | module_init(pcwd_init_module); | 995 | module_init(pcwd_init_module); |
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c index 2700c5c45b8a..3fdfda9324fa 100644 --- a/drivers/char/watchdog/pcwd_usb.c +++ b/drivers/char/watchdog/pcwd_usb.c | |||
@@ -705,7 +705,8 @@ err_out_misc_deregister: | |||
705 | err_out_unregister_reboot: | 705 | err_out_unregister_reboot: |
706 | unregister_reboot_notifier(&usb_pcwd_notifier); | 706 | unregister_reboot_notifier(&usb_pcwd_notifier); |
707 | error: | 707 | error: |
708 | usb_pcwd_delete (usb_pcwd); | 708 | if (usb_pcwd) |
709 | usb_pcwd_delete(usb_pcwd); | ||
709 | usb_pcwd_device = NULL; | 710 | usb_pcwd_device = NULL; |
710 | return retval; | 711 | return retval; |
711 | } | 712 | } |
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c index 9dc54736e4eb..1ea04e9b2b0b 100644 --- a/drivers/char/watchdog/s3c2410_wdt.c +++ b/drivers/char/watchdog/s3c2410_wdt.c | |||
@@ -423,6 +423,12 @@ static int s3c2410wdt_probe(struct platform_device *pdev) | |||
423 | if (tmr_atboot && started == 0) { | 423 | if (tmr_atboot && started == 0) { |
424 | printk(KERN_INFO PFX "Starting Watchdog Timer\n"); | 424 | printk(KERN_INFO PFX "Starting Watchdog Timer\n"); |
425 | s3c2410wdt_start(); | 425 | s3c2410wdt_start(); |
426 | } else if (!tmr_atboot) { | ||
427 | /* if we're not enabling the watchdog, then ensure it is | ||
428 | * disabled if it has been left running from the bootloader | ||
429 | * or other source */ | ||
430 | |||
431 | s3c2410wdt_stop(); | ||
426 | } | 432 | } |
427 | 433 | ||
428 | return 0; | 434 | return 0; |
diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c index 515ce7572049..20b88f9b7be2 100644 --- a/drivers/char/watchdog/sc1200wdt.c +++ b/drivers/char/watchdog/sc1200wdt.c | |||
@@ -377,7 +377,7 @@ static int __init sc1200wdt_init(void) | |||
377 | { | 377 | { |
378 | int ret; | 378 | int ret; |
379 | 379 | ||
380 | printk(banner); | 380 | printk("%s\n", banner); |
381 | 381 | ||
382 | spin_lock_init(&sc1200wdt_lock); | 382 | spin_lock_init(&sc1200wdt_lock); |
383 | sema_init(&open_sem, 1); | 383 | sema_init(&open_sem, 1); |