diff options
Diffstat (limited to 'drivers/char')
41 files changed, 1629 insertions, 179 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 0e6f35fcc2eb..2af12fc45115 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -409,14 +409,6 @@ config SGI_MBCS | |||
409 | If you have an SGI Altix with an attached SABrick | 409 | If you have an SGI Altix with an attached SABrick |
410 | say Y or M here, otherwise say N. | 410 | say Y or M here, otherwise say N. |
411 | 411 | ||
412 | config MSPEC | ||
413 | tristate "Memory special operations driver" | ||
414 | depends on IA64 | ||
415 | help | ||
416 | If you have an ia64 and you want to enable memory special | ||
417 | operations support (formerly known as fetchop), say Y here, | ||
418 | otherwise say N. | ||
419 | |||
420 | source "drivers/serial/Kconfig" | 412 | source "drivers/serial/Kconfig" |
421 | 413 | ||
422 | config UNIX98_PTYS | 414 | config UNIX98_PTYS |
@@ -1046,7 +1038,7 @@ source "drivers/char/tpm/Kconfig" | |||
1046 | 1038 | ||
1047 | config TELCLOCK | 1039 | config TELCLOCK |
1048 | tristate "Telecom clock driver for MPBL0010 ATCA SBC" | 1040 | tristate "Telecom clock driver for MPBL0010 ATCA SBC" |
1049 | depends on EXPERIMENTAL | 1041 | depends on EXPERIMENTAL && X86 |
1050 | default n | 1042 | default n |
1051 | help | 1043 | help |
1052 | The telecom clock device is specific to the MPBL0010 ATCA computer and | 1044 | The telecom clock device is specific to the MPBL0010 ATCA computer and |
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index 91b71e750ee1..dffc19382f7e 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c | |||
@@ -27,32 +27,42 @@ | |||
27 | static int uninorth_rev; | 27 | static int uninorth_rev; |
28 | static int is_u3; | 28 | static int is_u3; |
29 | 29 | ||
30 | static char __devinitdata *aperture = NULL; | ||
30 | 31 | ||
31 | static int uninorth_fetch_size(void) | 32 | static int uninorth_fetch_size(void) |
32 | { | 33 | { |
33 | int i; | 34 | int i, size = 0; |
34 | u32 temp; | 35 | struct aper_size_info_32 *values = |
35 | struct aper_size_info_32 *values; | 36 | A_SIZE_32(agp_bridge->driver->aperture_sizes); |
36 | 37 | ||
37 | pci_read_config_dword(agp_bridge->dev, UNI_N_CFG_GART_BASE, &temp); | 38 | if (aperture) { |
38 | temp &= ~(0xfffff000); | 39 | char *save = aperture; |
39 | values = A_SIZE_32(agp_bridge->driver->aperture_sizes); | 40 | |
40 | 41 | size = memparse(aperture, &aperture) >> 20; | |
41 | for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { | 42 | aperture = save; |
42 | if (temp == values[i].size_value) { | 43 | |
43 | agp_bridge->previous_size = | 44 | for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) |
44 | agp_bridge->current_size = (void *) (values + i); | 45 | if (size == values[i].size) |
45 | agp_bridge->aperture_size_idx = i; | 46 | break; |
46 | return values[i].size; | 47 | |
48 | if (i == agp_bridge->driver->num_aperture_sizes) { | ||
49 | printk(KERN_ERR PFX "Invalid aperture size, using" | ||
50 | " default\n"); | ||
51 | size = 0; | ||
52 | aperture = NULL; | ||
47 | } | 53 | } |
48 | } | 54 | } |
49 | 55 | ||
50 | agp_bridge->previous_size = | 56 | if (!size) { |
51 | agp_bridge->current_size = (void *) (values + 1); | 57 | for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) |
52 | agp_bridge->aperture_size_idx = 1; | 58 | if (values[i].size == 32) |
53 | return values[1].size; | 59 | break; |
60 | } | ||
54 | 61 | ||
55 | return 0; | 62 | agp_bridge->previous_size = |
63 | agp_bridge->current_size = (void *)(values + i); | ||
64 | agp_bridge->aperture_size_idx = i; | ||
65 | return values[i].size; | ||
56 | } | 66 | } |
57 | 67 | ||
58 | static void uninorth_tlbflush(struct agp_memory *mem) | 68 | static void uninorth_tlbflush(struct agp_memory *mem) |
@@ -683,5 +693,11 @@ static void __exit agp_uninorth_cleanup(void) | |||
683 | module_init(agp_uninorth_init); | 693 | module_init(agp_uninorth_init); |
684 | module_exit(agp_uninorth_cleanup); | 694 | module_exit(agp_uninorth_cleanup); |
685 | 695 | ||
696 | module_param(aperture, charp, 0); | ||
697 | MODULE_PARM_DESC(aperture, | ||
698 | "Aperture size, must be power of two between 4MB and an\n" | ||
699 | "\t\tupper limit specific to the UniNorth revision.\n" | ||
700 | "\t\tDefault: 32M"); | ||
701 | |||
686 | MODULE_AUTHOR("Ben Herrenschmidt & Paul Mackerras"); | 702 | MODULE_AUTHOR("Ben Herrenschmidt & Paul Mackerras"); |
687 | MODULE_LICENSE("GPL"); | 703 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index 029baea33b62..6eafff13dab6 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c | |||
@@ -237,6 +237,8 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
237 | 237 | ||
238 | list = drm_alloc(sizeof(*list), DRM_MEM_MAPS); | 238 | list = drm_alloc(sizeof(*list), DRM_MEM_MAPS); |
239 | if (!list) { | 239 | if (!list) { |
240 | if (map->type == _DRM_REGISTERS) | ||
241 | drm_ioremapfree(map->handle, map->size, dev); | ||
240 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | 242 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); |
241 | return -EINVAL; | 243 | return -EINVAL; |
242 | } | 244 | } |
@@ -252,6 +254,8 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
252 | map->offset; | 254 | map->offset; |
253 | ret = drm_map_handle(dev, &list->hash, user_token, 0); | 255 | ret = drm_map_handle(dev, &list->hash, user_token, 0); |
254 | if (ret) { | 256 | if (ret) { |
257 | if (map->type == _DRM_REGISTERS) | ||
258 | drm_ioremapfree(map->handle, map->size, dev); | ||
255 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | 259 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); |
256 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); | 260 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); |
257 | mutex_unlock(&dev->struct_mutex); | 261 | mutex_unlock(&dev->struct_mutex); |
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c index 51ad98c685c3..ba4b8de83cf0 100644 --- a/drivers/char/drm/drm_sysfs.c +++ b/drivers/char/drm/drm_sysfs.c | |||
@@ -42,13 +42,24 @@ static CLASS_ATTR(version, S_IRUGO, version_show, NULL); | |||
42 | struct class *drm_sysfs_create(struct module *owner, char *name) | 42 | struct class *drm_sysfs_create(struct module *owner, char *name) |
43 | { | 43 | { |
44 | struct class *class; | 44 | struct class *class; |
45 | int err; | ||
45 | 46 | ||
46 | class = class_create(owner, name); | 47 | class = class_create(owner, name); |
47 | if (!class) | 48 | if (!class) { |
48 | return class; | 49 | err = -ENOMEM; |
50 | goto err_out; | ||
51 | } | ||
52 | |||
53 | err = class_create_file(class, &class_attr_version); | ||
54 | if (err) | ||
55 | goto err_out_class; | ||
49 | 56 | ||
50 | class_create_file(class, &class_attr_version); | ||
51 | return class; | 57 | return class; |
58 | |||
59 | err_out_class: | ||
60 | class_destroy(class); | ||
61 | err_out: | ||
62 | return ERR_PTR(err); | ||
52 | } | 63 | } |
53 | 64 | ||
54 | /** | 65 | /** |
@@ -96,20 +107,36 @@ static struct class_device_attribute class_device_attrs[] = { | |||
96 | struct class_device *drm_sysfs_device_add(struct class *cs, drm_head_t *head) | 107 | struct class_device *drm_sysfs_device_add(struct class *cs, drm_head_t *head) |
97 | { | 108 | { |
98 | struct class_device *class_dev; | 109 | struct class_device *class_dev; |
99 | int i; | 110 | int i, j, err; |
100 | 111 | ||
101 | class_dev = class_device_create(cs, NULL, | 112 | class_dev = class_device_create(cs, NULL, |
102 | MKDEV(DRM_MAJOR, head->minor), | 113 | MKDEV(DRM_MAJOR, head->minor), |
103 | &(head->dev->pdev)->dev, | 114 | &(head->dev->pdev)->dev, |
104 | "card%d", head->minor); | 115 | "card%d", head->minor); |
105 | if (!class_dev) | 116 | if (!class_dev) { |
106 | return NULL; | 117 | err = -ENOMEM; |
118 | goto err_out; | ||
119 | } | ||
107 | 120 | ||
108 | class_set_devdata(class_dev, head); | 121 | class_set_devdata(class_dev, head); |
109 | 122 | ||
110 | for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) | 123 | for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) { |
111 | class_device_create_file(class_dev, &class_device_attrs[i]); | 124 | err = class_device_create_file(class_dev, |
125 | &class_device_attrs[i]); | ||
126 | if (err) | ||
127 | goto err_out_files; | ||
128 | } | ||
129 | |||
112 | return class_dev; | 130 | return class_dev; |
131 | |||
132 | err_out_files: | ||
133 | if (i > 0) | ||
134 | for (j = 0; j < i; j++) | ||
135 | class_device_remove_file(class_dev, | ||
136 | &class_device_attrs[i]); | ||
137 | class_device_unregister(class_dev); | ||
138 | err_out: | ||
139 | return ERR_PTR(err); | ||
113 | } | 140 | } |
114 | 141 | ||
115 | /** | 142 | /** |
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c index e30f556b79f1..be49dbb9ec3f 100644 --- a/drivers/char/drm/mga_drv.c +++ b/drivers/char/drm/mga_drv.c | |||
@@ -47,6 +47,7 @@ static struct drm_driver driver = { | |||
47 | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | | 47 | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | |
48 | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | | 48 | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | |
49 | DRIVER_IRQ_VBL, | 49 | DRIVER_IRQ_VBL, |
50 | .dev_priv_size = sizeof(drm_mga_buf_priv_t), | ||
50 | .load = mga_driver_load, | 51 | .load = mga_driver_load, |
51 | .unload = mga_driver_unload, | 52 | .unload = mga_driver_unload, |
52 | .lastclose = mga_driver_lastclose, | 53 | .lastclose = mga_driver_lastclose, |
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c index 26bdf2ca59d7..d14477ba3679 100644 --- a/drivers/char/drm/r300_cmdbuf.c +++ b/drivers/char/drm/r300_cmdbuf.c | |||
@@ -538,6 +538,36 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, | |||
538 | return 0; | 538 | return 0; |
539 | } | 539 | } |
540 | 540 | ||
541 | static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv, | ||
542 | drm_radeon_kcmd_buffer_t *cmdbuf) | ||
543 | { | ||
544 | u32 *cmd = (u32 *) cmdbuf->buf; | ||
545 | int count, ret; | ||
546 | RING_LOCALS; | ||
547 | |||
548 | count=(cmd[0]>>16) & 0x3fff; | ||
549 | |||
550 | if ((cmd[1] & 0x8000ffff) != 0x80000810) { | ||
551 | DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); | ||
552 | return DRM_ERR(EINVAL); | ||
553 | } | ||
554 | ret = r300_check_offset(dev_priv, cmd[2]); | ||
555 | if (ret) { | ||
556 | DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); | ||
557 | return DRM_ERR(EINVAL); | ||
558 | } | ||
559 | |||
560 | BEGIN_RING(count+2); | ||
561 | OUT_RING(cmd[0]); | ||
562 | OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1); | ||
563 | ADVANCE_RING(); | ||
564 | |||
565 | cmdbuf->buf += (count+2)*4; | ||
566 | cmdbuf->bufsz -= (count+2)*4; | ||
567 | |||
568 | return 0; | ||
569 | } | ||
570 | |||
541 | static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, | 571 | static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, |
542 | drm_radeon_kcmd_buffer_t *cmdbuf) | 572 | drm_radeon_kcmd_buffer_t *cmdbuf) |
543 | { | 573 | { |
@@ -578,10 +608,11 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, | |||
578 | case RADEON_CNTL_BITBLT_MULTI: | 608 | case RADEON_CNTL_BITBLT_MULTI: |
579 | return r300_emit_bitblt_multi(dev_priv, cmdbuf); | 609 | return r300_emit_bitblt_multi(dev_priv, cmdbuf); |
580 | 610 | ||
611 | case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ | ||
612 | return r300_emit_indx_buffer(dev_priv, cmdbuf); | ||
581 | case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */ | 613 | case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */ |
582 | case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */ | 614 | case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */ |
583 | case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */ | 615 | case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */ |
584 | case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ | ||
585 | case RADEON_WAIT_FOR_IDLE: | 616 | case RADEON_WAIT_FOR_IDLE: |
586 | case RADEON_CP_NOP: | 617 | case RADEON_CP_NOP: |
587 | /* these packets are safe */ | 618 | /* these packets are safe */ |
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index feac5f005d47..6e04fdd732ac 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c | |||
@@ -275,6 +275,8 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * | |||
275 | unsigned int *cmdsz) | 275 | unsigned int *cmdsz) |
276 | { | 276 | { |
277 | u32 *cmd = (u32 *) cmdbuf->buf; | 277 | u32 *cmd = (u32 *) cmdbuf->buf; |
278 | u32 offset, narrays; | ||
279 | int count, i, k; | ||
278 | 280 | ||
279 | *cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16); | 281 | *cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16); |
280 | 282 | ||
@@ -288,10 +290,106 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * | |||
288 | return DRM_ERR(EINVAL); | 290 | return DRM_ERR(EINVAL); |
289 | } | 291 | } |
290 | 292 | ||
291 | /* Check client state and fix it up if necessary */ | 293 | switch(cmd[0] & 0xff00) { |
292 | if (cmd[0] & 0x8000) { /* MSB of opcode: next DWORD GUI_CNTL */ | 294 | /* XXX Are there old drivers needing other packets? */ |
293 | u32 offset; | ||
294 | 295 | ||
296 | case RADEON_3D_DRAW_IMMD: | ||
297 | case RADEON_3D_DRAW_VBUF: | ||
298 | case RADEON_3D_DRAW_INDX: | ||
299 | case RADEON_WAIT_FOR_IDLE: | ||
300 | case RADEON_CP_NOP: | ||
301 | case RADEON_3D_CLEAR_ZMASK: | ||
302 | /* case RADEON_CP_NEXT_CHAR: | ||
303 | case RADEON_CP_PLY_NEXTSCAN: | ||
304 | case RADEON_CP_SET_SCISSORS: */ /* probably safe but will never need them? */ | ||
305 | /* these packets are safe */ | ||
306 | break; | ||
307 | |||
308 | case RADEON_CP_3D_DRAW_IMMD_2: | ||
309 | case RADEON_CP_3D_DRAW_VBUF_2: | ||
310 | case RADEON_CP_3D_DRAW_INDX_2: | ||
311 | case RADEON_3D_CLEAR_HIZ: | ||
312 | /* safe but r200 only */ | ||
313 | if (dev_priv->microcode_version != UCODE_R200) { | ||
314 | DRM_ERROR("Invalid 3d packet for r100-class chip\n"); | ||
315 | return DRM_ERR(EINVAL); | ||
316 | } | ||
317 | break; | ||
318 | |||
319 | case RADEON_3D_LOAD_VBPNTR: | ||
320 | count = (cmd[0] >> 16) & 0x3fff; | ||
321 | |||
322 | if (count > 18) { /* 12 arrays max */ | ||
323 | DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n", | ||
324 | count); | ||
325 | return DRM_ERR(EINVAL); | ||
326 | } | ||
327 | |||
328 | /* carefully check packet contents */ | ||
329 | narrays = cmd[1] & ~0xc000; | ||
330 | k = 0; | ||
331 | i = 2; | ||
332 | while ((k < narrays) && (i < (count + 2))) { | ||
333 | i++; /* skip attribute field */ | ||
334 | if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) { | ||
335 | DRM_ERROR | ||
336 | ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", | ||
337 | k, i); | ||
338 | return DRM_ERR(EINVAL); | ||
339 | } | ||
340 | k++; | ||
341 | i++; | ||
342 | if (k == narrays) | ||
343 | break; | ||
344 | /* have one more to process, they come in pairs */ | ||
345 | if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) { | ||
346 | DRM_ERROR | ||
347 | ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", | ||
348 | k, i); | ||
349 | return DRM_ERR(EINVAL); | ||
350 | } | ||
351 | k++; | ||
352 | i++; | ||
353 | } | ||
354 | /* do the counts match what we expect ? */ | ||
355 | if ((k != narrays) || (i != (count + 2))) { | ||
356 | DRM_ERROR | ||
357 | ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n", | ||
358 | k, i, narrays, count + 1); | ||
359 | return DRM_ERR(EINVAL); | ||
360 | } | ||
361 | break; | ||
362 | |||
363 | case RADEON_3D_RNDR_GEN_INDX_PRIM: | ||
364 | if (dev_priv->microcode_version != UCODE_R100) { | ||
365 | DRM_ERROR("Invalid 3d packet for r200-class chip\n"); | ||
366 | return DRM_ERR(EINVAL); | ||
367 | } | ||
368 | if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[1])) { | ||
369 | DRM_ERROR("Invalid rndr_gen_indx offset\n"); | ||
370 | return DRM_ERR(EINVAL); | ||
371 | } | ||
372 | break; | ||
373 | |||
374 | case RADEON_CP_INDX_BUFFER: | ||
375 | if (dev_priv->microcode_version != UCODE_R200) { | ||
376 | DRM_ERROR("Invalid 3d packet for r100-class chip\n"); | ||
377 | return DRM_ERR(EINVAL); | ||
378 | } | ||
379 | if ((cmd[1] & 0x8000ffff) != 0x80000810) { | ||
380 | DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); | ||
381 | return DRM_ERR(EINVAL); | ||
382 | } | ||
383 | if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[2])) { | ||
384 | DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); | ||
385 | return DRM_ERR(EINVAL); | ||
386 | } | ||
387 | break; | ||
388 | |||
389 | case RADEON_CNTL_HOSTDATA_BLT: | ||
390 | case RADEON_CNTL_PAINT_MULTI: | ||
391 | case RADEON_CNTL_BITBLT_MULTI: | ||
392 | /* MSB of opcode: next DWORD GUI_CNTL */ | ||
295 | if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL | 393 | if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
296 | | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { | 394 | | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { |
297 | offset = cmd[2] << 10; | 395 | offset = cmd[2] << 10; |
@@ -313,6 +411,11 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * | |||
313 | } | 411 | } |
314 | cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10; | 412 | cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10; |
315 | } | 413 | } |
414 | break; | ||
415 | |||
416 | default: | ||
417 | DRM_ERROR("Invalid packet type %x\n", cmd[0] & 0xff00); | ||
418 | return DRM_ERR(EINVAL); | ||
316 | } | 419 | } |
317 | 420 | ||
318 | return 0; | 421 | return 0; |
diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c index 59c7520bf9a2..a9a84f88df5e 100644 --- a/drivers/char/drm/savage_bci.c +++ b/drivers/char/drm/savage_bci.c | |||
@@ -728,6 +728,7 @@ static int savage_do_init_bci(drm_device_t * dev, drm_savage_init_t * init) | |||
728 | dev_priv->status = NULL; | 728 | dev_priv->status = NULL; |
729 | } | 729 | } |
730 | if (dev_priv->dma_type == SAVAGE_DMA_AGP && init->buffers_offset) { | 730 | if (dev_priv->dma_type == SAVAGE_DMA_AGP && init->buffers_offset) { |
731 | dev->agp_buffer_token = init->buffers_offset; | ||
731 | dev->agp_buffer_map = drm_core_findmap(dev, | 732 | dev->agp_buffer_map = drm_core_findmap(dev, |
732 | init->buffers_offset); | 733 | init->buffers_offset); |
733 | if (!dev->agp_buffer_map) { | 734 | if (!dev->agp_buffer_map) { |
diff --git a/drivers/char/drm/savage_state.c b/drivers/char/drm/savage_state.c index ef2581d16146..1ca1e9cb5a33 100644 --- a/drivers/char/drm/savage_state.c +++ b/drivers/char/drm/savage_state.c | |||
@@ -994,7 +994,7 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS) | |||
994 | if (cmdbuf.size) { | 994 | if (cmdbuf.size) { |
995 | kcmd_addr = drm_alloc(cmdbuf.size * 8, DRM_MEM_DRIVER); | 995 | kcmd_addr = drm_alloc(cmdbuf.size * 8, DRM_MEM_DRIVER); |
996 | if (kcmd_addr == NULL) | 996 | if (kcmd_addr == NULL) |
997 | return ENOMEM; | 997 | return DRM_ERR(ENOMEM); |
998 | 998 | ||
999 | if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf.cmd_addr, | 999 | if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf.cmd_addr, |
1000 | cmdbuf.size * 8)) | 1000 | cmdbuf.size * 8)) |
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index c3f95583a120..706733c0b36a 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
@@ -1157,6 +1157,7 @@ static int __init pc_init(void) | |||
1157 | int crd; | 1157 | int crd; |
1158 | struct board_info *bd; | 1158 | struct board_info *bd; |
1159 | unsigned char board_id = 0; | 1159 | unsigned char board_id = 0; |
1160 | int err = -ENOMEM; | ||
1160 | 1161 | ||
1161 | int pci_boards_found, pci_count; | 1162 | int pci_boards_found, pci_count; |
1162 | 1163 | ||
@@ -1164,13 +1165,11 @@ static int __init pc_init(void) | |||
1164 | 1165 | ||
1165 | pc_driver = alloc_tty_driver(MAX_ALLOC); | 1166 | pc_driver = alloc_tty_driver(MAX_ALLOC); |
1166 | if (!pc_driver) | 1167 | if (!pc_driver) |
1167 | return -ENOMEM; | 1168 | goto out1; |
1168 | 1169 | ||
1169 | pc_info = alloc_tty_driver(MAX_ALLOC); | 1170 | pc_info = alloc_tty_driver(MAX_ALLOC); |
1170 | if (!pc_info) { | 1171 | if (!pc_info) |
1171 | put_tty_driver(pc_driver); | 1172 | goto out2; |
1172 | return -ENOMEM; | ||
1173 | } | ||
1174 | 1173 | ||
1175 | /* ----------------------------------------------------------------------- | 1174 | /* ----------------------------------------------------------------------- |
1176 | If epca_setup has not been ran by LILO set num_cards to defaults; copy | 1175 | If epca_setup has not been ran by LILO set num_cards to defaults; copy |
@@ -1370,11 +1369,17 @@ static int __init pc_init(void) | |||
1370 | 1369 | ||
1371 | } /* End for each card */ | 1370 | } /* End for each card */ |
1372 | 1371 | ||
1373 | if (tty_register_driver(pc_driver)) | 1372 | err = tty_register_driver(pc_driver); |
1374 | panic("Couldn't register Digi PC/ driver"); | 1373 | if (err) { |
1374 | printk(KERN_ERR "Couldn't register Digi PC/ driver"); | ||
1375 | goto out3; | ||
1376 | } | ||
1375 | 1377 | ||
1376 | if (tty_register_driver(pc_info)) | 1378 | err = tty_register_driver(pc_info); |
1377 | panic("Couldn't register Digi PC/ info "); | 1379 | if (err) { |
1380 | printk(KERN_ERR "Couldn't register Digi PC/ info "); | ||
1381 | goto out4; | ||
1382 | } | ||
1378 | 1383 | ||
1379 | /* ------------------------------------------------------------------- | 1384 | /* ------------------------------------------------------------------- |
1380 | Start up the poller to check for events on all enabled boards | 1385 | Start up the poller to check for events on all enabled boards |
@@ -1385,6 +1390,15 @@ static int __init pc_init(void) | |||
1385 | mod_timer(&epca_timer, jiffies + HZ/25); | 1390 | mod_timer(&epca_timer, jiffies + HZ/25); |
1386 | return 0; | 1391 | return 0; |
1387 | 1392 | ||
1393 | out4: | ||
1394 | tty_unregister_driver(pc_driver); | ||
1395 | out3: | ||
1396 | put_tty_driver(pc_info); | ||
1397 | out2: | ||
1398 | put_tty_driver(pc_driver); | ||
1399 | out1: | ||
1400 | return err; | ||
1401 | |||
1388 | } /* End pc_init */ | 1402 | } /* End pc_init */ |
1389 | 1403 | ||
1390 | /* ------------------ Begin post_fep_init ---------------------- */ | 1404 | /* ------------------ Begin post_fep_init ---------------------- */ |
diff --git a/drivers/char/ftape/zftape/zftape-buffers.c b/drivers/char/ftape/zftape/zftape-buffers.c index da06f138334e..7ebce2ec7897 100644 --- a/drivers/char/ftape/zftape/zftape-buffers.c +++ b/drivers/char/ftape/zftape/zftape-buffers.c | |||
@@ -85,7 +85,7 @@ int zft_vmalloc_once(void *new, size_t size) | |||
85 | peak_memory = used_memory; | 85 | peak_memory = used_memory; |
86 | } | 86 | } |
87 | TRACE_ABORT(0, ft_t_noise, | 87 | TRACE_ABORT(0, ft_t_noise, |
88 | "allocated buffer @ %p, %d bytes", *(void **)new, size); | 88 | "allocated buffer @ %p, %zd bytes", *(void **)new, size); |
89 | } | 89 | } |
90 | int zft_vmalloc_always(void *new, size_t size) | 90 | int zft_vmalloc_always(void *new, size_t size) |
91 | { | 91 | { |
@@ -101,7 +101,7 @@ void zft_vfree(void *old, size_t size) | |||
101 | if (*(void **)old) { | 101 | if (*(void **)old) { |
102 | vfree(*(void **)old); | 102 | vfree(*(void **)old); |
103 | used_memory -= size; | 103 | used_memory -= size; |
104 | TRACE(ft_t_noise, "released buffer @ %p, %d bytes", | 104 | TRACE(ft_t_noise, "released buffer @ %p, %zd bytes", |
105 | *(void **)old, size); | 105 | *(void **)old, size); |
106 | *(void **)old = NULL; | 106 | *(void **)old = NULL; |
107 | } | 107 | } |
diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c index fc944d375be7..54d93f0345e8 100644 --- a/drivers/char/ip2/i2lib.c +++ b/drivers/char/ip2/i2lib.c | |||
@@ -1007,7 +1007,7 @@ i2InputAvailable(i2ChanStrPtr pCh) | |||
1007 | // applications that one cannot break out of. | 1007 | // applications that one cannot break out of. |
1008 | //****************************************************************************** | 1008 | //****************************************************************************** |
1009 | static int | 1009 | static int |
1010 | i2Output(i2ChanStrPtr pCh, const char *pSource, int count, int user ) | 1010 | i2Output(i2ChanStrPtr pCh, const char *pSource, int count) |
1011 | { | 1011 | { |
1012 | i2eBordStrPtr pB; | 1012 | i2eBordStrPtr pB; |
1013 | unsigned char *pInsert; | 1013 | unsigned char *pInsert; |
@@ -1020,7 +1020,7 @@ i2Output(i2ChanStrPtr pCh, const char *pSource, int count, int user ) | |||
1020 | 1020 | ||
1021 | int bailout = 10; | 1021 | int bailout = 10; |
1022 | 1022 | ||
1023 | ip2trace (CHANN, ITRC_OUTPUT, ITRC_ENTER, 2, count, user ); | 1023 | ip2trace (CHANN, ITRC_OUTPUT, ITRC_ENTER, 2, count, 0 ); |
1024 | 1024 | ||
1025 | // Ensure channel structure seems real | 1025 | // Ensure channel structure seems real |
1026 | if ( !i2Validate ( pCh ) ) | 1026 | if ( !i2Validate ( pCh ) ) |
@@ -1087,12 +1087,7 @@ i2Output(i2ChanStrPtr pCh, const char *pSource, int count, int user ) | |||
1087 | DATA_COUNT_OF(pInsert) = amountToMove; | 1087 | DATA_COUNT_OF(pInsert) = amountToMove; |
1088 | 1088 | ||
1089 | // Move the data | 1089 | // Move the data |
1090 | if ( user ) { | 1090 | memcpy( (char*)(DATA_OF(pInsert)), pSource, amountToMove ); |
1091 | rc = copy_from_user((char*)(DATA_OF(pInsert)), pSource, | ||
1092 | amountToMove ); | ||
1093 | } else { | ||
1094 | memcpy( (char*)(DATA_OF(pInsert)), pSource, amountToMove ); | ||
1095 | } | ||
1096 | // Adjust pointers and indices | 1091 | // Adjust pointers and indices |
1097 | pSource += amountToMove; | 1092 | pSource += amountToMove; |
1098 | pCh->Obuf_char_count += amountToMove; | 1093 | pCh->Obuf_char_count += amountToMove; |
diff --git a/drivers/char/ip2/i2lib.h b/drivers/char/ip2/i2lib.h index 952e113ccd8a..e559e9bac06d 100644 --- a/drivers/char/ip2/i2lib.h +++ b/drivers/char/ip2/i2lib.h | |||
@@ -332,7 +332,7 @@ static int i2QueueCommands(int, i2ChanStrPtr, int, int, cmdSyntaxPtr,...); | |||
332 | static int i2GetStatus(i2ChanStrPtr, int); | 332 | static int i2GetStatus(i2ChanStrPtr, int); |
333 | static int i2Input(i2ChanStrPtr); | 333 | static int i2Input(i2ChanStrPtr); |
334 | static int i2InputFlush(i2ChanStrPtr); | 334 | static int i2InputFlush(i2ChanStrPtr); |
335 | static int i2Output(i2ChanStrPtr, const char *, int, int); | 335 | static int i2Output(i2ChanStrPtr, const char *, int); |
336 | static int i2OutputFree(i2ChanStrPtr); | 336 | static int i2OutputFree(i2ChanStrPtr); |
337 | static int i2ServiceBoard(i2eBordStrPtr); | 337 | static int i2ServiceBoard(i2eBordStrPtr); |
338 | static void i2DrainOutput(i2ChanStrPtr, int); | 338 | static void i2DrainOutput(i2ChanStrPtr, int); |
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 858ba5432c99..a3f32d46d2f8 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c | |||
@@ -1704,7 +1704,7 @@ ip2_write( PTTY tty, const unsigned char *pData, int count) | |||
1704 | 1704 | ||
1705 | /* This is the actual move bit. Make sure it does what we need!!!!! */ | 1705 | /* This is the actual move bit. Make sure it does what we need!!!!! */ |
1706 | WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags); | 1706 | WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags); |
1707 | bytesSent = i2Output( pCh, pData, count, 0 ); | 1707 | bytesSent = i2Output( pCh, pData, count); |
1708 | WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); | 1708 | WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); |
1709 | 1709 | ||
1710 | ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent ); | 1710 | ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent ); |
@@ -1764,7 +1764,7 @@ ip2_flush_chars( PTTY tty ) | |||
1764 | // | 1764 | // |
1765 | // We may need to restart i2Output if it does not fullfill this request | 1765 | // We may need to restart i2Output if it does not fullfill this request |
1766 | // | 1766 | // |
1767 | strip = i2Output( pCh, pCh->Pbuf, pCh->Pbuf_stuff, 0 ); | 1767 | strip = i2Output( pCh, pCh->Pbuf, pCh->Pbuf_stuff); |
1768 | if ( strip != pCh->Pbuf_stuff ) { | 1768 | if ( strip != pCh->Pbuf_stuff ) { |
1769 | memmove( pCh->Pbuf, &pCh->Pbuf[strip], pCh->Pbuf_stuff - strip ); | 1769 | memmove( pCh->Pbuf, &pCh->Pbuf[strip], pCh->Pbuf_stuff - strip ); |
1770 | } | 1770 | } |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 2455e8d478ac..c47add8e47df 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -376,13 +376,23 @@ static void free_recv_msg_list(struct list_head *q) | |||
376 | } | 376 | } |
377 | } | 377 | } |
378 | 378 | ||
379 | static void free_smi_msg_list(struct list_head *q) | ||
380 | { | ||
381 | struct ipmi_smi_msg *msg, *msg2; | ||
382 | |||
383 | list_for_each_entry_safe(msg, msg2, q, link) { | ||
384 | list_del(&msg->link); | ||
385 | ipmi_free_smi_msg(msg); | ||
386 | } | ||
387 | } | ||
388 | |||
379 | static void clean_up_interface_data(ipmi_smi_t intf) | 389 | static void clean_up_interface_data(ipmi_smi_t intf) |
380 | { | 390 | { |
381 | int i; | 391 | int i; |
382 | struct cmd_rcvr *rcvr, *rcvr2; | 392 | struct cmd_rcvr *rcvr, *rcvr2; |
383 | struct list_head list; | 393 | struct list_head list; |
384 | 394 | ||
385 | free_recv_msg_list(&intf->waiting_msgs); | 395 | free_smi_msg_list(&intf->waiting_msgs); |
386 | free_recv_msg_list(&intf->waiting_events); | 396 | free_recv_msg_list(&intf->waiting_events); |
387 | 397 | ||
388 | /* Wholesale remove all the entries from the list in the | 398 | /* Wholesale remove all the entries from the list in the |
@@ -1844,7 +1854,7 @@ static ssize_t provides_dev_sdrs_show(struct device *dev, | |||
1844 | struct bmc_device *bmc = dev_get_drvdata(dev); | 1854 | struct bmc_device *bmc = dev_get_drvdata(dev); |
1845 | 1855 | ||
1846 | return snprintf(buf, 10, "%u\n", | 1856 | return snprintf(buf, 10, "%u\n", |
1847 | bmc->id.device_revision && 0x80 >> 7); | 1857 | (bmc->id.device_revision & 0x80) >> 7); |
1848 | } | 1858 | } |
1849 | 1859 | ||
1850 | static ssize_t revision_show(struct device *dev, struct device_attribute *attr, | 1860 | static ssize_t revision_show(struct device *dev, struct device_attribute *attr, |
@@ -1853,7 +1863,7 @@ static ssize_t revision_show(struct device *dev, struct device_attribute *attr, | |||
1853 | struct bmc_device *bmc = dev_get_drvdata(dev); | 1863 | struct bmc_device *bmc = dev_get_drvdata(dev); |
1854 | 1864 | ||
1855 | return snprintf(buf, 20, "%u\n", | 1865 | return snprintf(buf, 20, "%u\n", |
1856 | bmc->id.device_revision && 0x0F); | 1866 | bmc->id.device_revision & 0x0F); |
1857 | } | 1867 | } |
1858 | 1868 | ||
1859 | static ssize_t firmware_rev_show(struct device *dev, | 1869 | static ssize_t firmware_rev_show(struct device *dev, |
@@ -1928,13 +1938,8 @@ static ssize_t guid_show(struct device *dev, struct device_attribute *attr, | |||
1928 | (long long) bmc->guid[8]); | 1938 | (long long) bmc->guid[8]); |
1929 | } | 1939 | } |
1930 | 1940 | ||
1931 | static void | 1941 | static void remove_files(struct bmc_device *bmc) |
1932 | cleanup_bmc_device(struct kref *ref) | ||
1933 | { | 1942 | { |
1934 | struct bmc_device *bmc; | ||
1935 | |||
1936 | bmc = container_of(ref, struct bmc_device, refcount); | ||
1937 | |||
1938 | device_remove_file(&bmc->dev->dev, | 1943 | device_remove_file(&bmc->dev->dev, |
1939 | &bmc->device_id_attr); | 1944 | &bmc->device_id_attr); |
1940 | device_remove_file(&bmc->dev->dev, | 1945 | device_remove_file(&bmc->dev->dev, |
@@ -1951,12 +1956,23 @@ cleanup_bmc_device(struct kref *ref) | |||
1951 | &bmc->manufacturer_id_attr); | 1956 | &bmc->manufacturer_id_attr); |
1952 | device_remove_file(&bmc->dev->dev, | 1957 | device_remove_file(&bmc->dev->dev, |
1953 | &bmc->product_id_attr); | 1958 | &bmc->product_id_attr); |
1959 | |||
1954 | if (bmc->id.aux_firmware_revision_set) | 1960 | if (bmc->id.aux_firmware_revision_set) |
1955 | device_remove_file(&bmc->dev->dev, | 1961 | device_remove_file(&bmc->dev->dev, |
1956 | &bmc->aux_firmware_rev_attr); | 1962 | &bmc->aux_firmware_rev_attr); |
1957 | if (bmc->guid_set) | 1963 | if (bmc->guid_set) |
1958 | device_remove_file(&bmc->dev->dev, | 1964 | device_remove_file(&bmc->dev->dev, |
1959 | &bmc->guid_attr); | 1965 | &bmc->guid_attr); |
1966 | } | ||
1967 | |||
1968 | static void | ||
1969 | cleanup_bmc_device(struct kref *ref) | ||
1970 | { | ||
1971 | struct bmc_device *bmc; | ||
1972 | |||
1973 | bmc = container_of(ref, struct bmc_device, refcount); | ||
1974 | |||
1975 | remove_files(bmc); | ||
1960 | platform_device_unregister(bmc->dev); | 1976 | platform_device_unregister(bmc->dev); |
1961 | kfree(bmc); | 1977 | kfree(bmc); |
1962 | } | 1978 | } |
@@ -1977,6 +1993,79 @@ static void ipmi_bmc_unregister(ipmi_smi_t intf) | |||
1977 | mutex_unlock(&ipmidriver_mutex); | 1993 | mutex_unlock(&ipmidriver_mutex); |
1978 | } | 1994 | } |
1979 | 1995 | ||
1996 | static int create_files(struct bmc_device *bmc) | ||
1997 | { | ||
1998 | int err; | ||
1999 | |||
2000 | err = device_create_file(&bmc->dev->dev, | ||
2001 | &bmc->device_id_attr); | ||
2002 | if (err) goto out; | ||
2003 | err = device_create_file(&bmc->dev->dev, | ||
2004 | &bmc->provides_dev_sdrs_attr); | ||
2005 | if (err) goto out_devid; | ||
2006 | err = device_create_file(&bmc->dev->dev, | ||
2007 | &bmc->revision_attr); | ||
2008 | if (err) goto out_sdrs; | ||
2009 | err = device_create_file(&bmc->dev->dev, | ||
2010 | &bmc->firmware_rev_attr); | ||
2011 | if (err) goto out_rev; | ||
2012 | err = device_create_file(&bmc->dev->dev, | ||
2013 | &bmc->version_attr); | ||
2014 | if (err) goto out_firm; | ||
2015 | err = device_create_file(&bmc->dev->dev, | ||
2016 | &bmc->add_dev_support_attr); | ||
2017 | if (err) goto out_version; | ||
2018 | err = device_create_file(&bmc->dev->dev, | ||
2019 | &bmc->manufacturer_id_attr); | ||
2020 | if (err) goto out_add_dev; | ||
2021 | err = device_create_file(&bmc->dev->dev, | ||
2022 | &bmc->product_id_attr); | ||
2023 | if (err) goto out_manu; | ||
2024 | if (bmc->id.aux_firmware_revision_set) { | ||
2025 | err = device_create_file(&bmc->dev->dev, | ||
2026 | &bmc->aux_firmware_rev_attr); | ||
2027 | if (err) goto out_prod_id; | ||
2028 | } | ||
2029 | if (bmc->guid_set) { | ||
2030 | err = device_create_file(&bmc->dev->dev, | ||
2031 | &bmc->guid_attr); | ||
2032 | if (err) goto out_aux_firm; | ||
2033 | } | ||
2034 | |||
2035 | return 0; | ||
2036 | |||
2037 | out_aux_firm: | ||
2038 | if (bmc->id.aux_firmware_revision_set) | ||
2039 | device_remove_file(&bmc->dev->dev, | ||
2040 | &bmc->aux_firmware_rev_attr); | ||
2041 | out_prod_id: | ||
2042 | device_remove_file(&bmc->dev->dev, | ||
2043 | &bmc->product_id_attr); | ||
2044 | out_manu: | ||
2045 | device_remove_file(&bmc->dev->dev, | ||
2046 | &bmc->manufacturer_id_attr); | ||
2047 | out_add_dev: | ||
2048 | device_remove_file(&bmc->dev->dev, | ||
2049 | &bmc->add_dev_support_attr); | ||
2050 | out_version: | ||
2051 | device_remove_file(&bmc->dev->dev, | ||
2052 | &bmc->version_attr); | ||
2053 | out_firm: | ||
2054 | device_remove_file(&bmc->dev->dev, | ||
2055 | &bmc->firmware_rev_attr); | ||
2056 | out_rev: | ||
2057 | device_remove_file(&bmc->dev->dev, | ||
2058 | &bmc->revision_attr); | ||
2059 | out_sdrs: | ||
2060 | device_remove_file(&bmc->dev->dev, | ||
2061 | &bmc->provides_dev_sdrs_attr); | ||
2062 | out_devid: | ||
2063 | device_remove_file(&bmc->dev->dev, | ||
2064 | &bmc->device_id_attr); | ||
2065 | out: | ||
2066 | return err; | ||
2067 | } | ||
2068 | |||
1980 | static int ipmi_bmc_register(ipmi_smi_t intf) | 2069 | static int ipmi_bmc_register(ipmi_smi_t intf) |
1981 | { | 2070 | { |
1982 | int rv; | 2071 | int rv; |
@@ -2029,7 +2118,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf) | |||
2029 | dev_set_drvdata(&bmc->dev->dev, bmc); | 2118 | dev_set_drvdata(&bmc->dev->dev, bmc); |
2030 | kref_init(&bmc->refcount); | 2119 | kref_init(&bmc->refcount); |
2031 | 2120 | ||
2032 | rv = platform_device_register(bmc->dev); | 2121 | rv = platform_device_add(bmc->dev); |
2033 | mutex_unlock(&ipmidriver_mutex); | 2122 | mutex_unlock(&ipmidriver_mutex); |
2034 | if (rv) { | 2123 | if (rv) { |
2035 | printk(KERN_ERR | 2124 | printk(KERN_ERR |
@@ -2051,7 +2140,6 @@ static int ipmi_bmc_register(ipmi_smi_t intf) | |||
2051 | bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO; | 2140 | bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO; |
2052 | bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show; | 2141 | bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show; |
2053 | 2142 | ||
2054 | |||
2055 | bmc->revision_attr.attr.name = "revision"; | 2143 | bmc->revision_attr.attr.name = "revision"; |
2056 | bmc->revision_attr.attr.owner = THIS_MODULE; | 2144 | bmc->revision_attr.attr.owner = THIS_MODULE; |
2057 | bmc->revision_attr.attr.mode = S_IRUGO; | 2145 | bmc->revision_attr.attr.mode = S_IRUGO; |
@@ -2093,28 +2181,14 @@ static int ipmi_bmc_register(ipmi_smi_t intf) | |||
2093 | bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO; | 2181 | bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO; |
2094 | bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show; | 2182 | bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show; |
2095 | 2183 | ||
2096 | device_create_file(&bmc->dev->dev, | 2184 | rv = create_files(bmc); |
2097 | &bmc->device_id_attr); | 2185 | if (rv) { |
2098 | device_create_file(&bmc->dev->dev, | 2186 | mutex_lock(&ipmidriver_mutex); |
2099 | &bmc->provides_dev_sdrs_attr); | 2187 | platform_device_unregister(bmc->dev); |
2100 | device_create_file(&bmc->dev->dev, | 2188 | mutex_unlock(&ipmidriver_mutex); |
2101 | &bmc->revision_attr); | 2189 | |
2102 | device_create_file(&bmc->dev->dev, | 2190 | return rv; |
2103 | &bmc->firmware_rev_attr); | 2191 | } |
2104 | device_create_file(&bmc->dev->dev, | ||
2105 | &bmc->version_attr); | ||
2106 | device_create_file(&bmc->dev->dev, | ||
2107 | &bmc->add_dev_support_attr); | ||
2108 | device_create_file(&bmc->dev->dev, | ||
2109 | &bmc->manufacturer_id_attr); | ||
2110 | device_create_file(&bmc->dev->dev, | ||
2111 | &bmc->product_id_attr); | ||
2112 | if (bmc->id.aux_firmware_revision_set) | ||
2113 | device_create_file(&bmc->dev->dev, | ||
2114 | &bmc->aux_firmware_rev_attr); | ||
2115 | if (bmc->guid_set) | ||
2116 | device_create_file(&bmc->dev->dev, | ||
2117 | &bmc->guid_attr); | ||
2118 | 2192 | ||
2119 | printk(KERN_INFO | 2193 | printk(KERN_INFO |
2120 | "ipmi: Found new BMC (man_id: 0x%6.6x, " | 2194 | "ipmi: Found new BMC (man_id: 0x%6.6x, " |
@@ -3168,7 +3242,9 @@ void ipmi_smi_msg_received(ipmi_smi_t intf, | |||
3168 | report the error immediately. */ | 3242 | report the error immediately. */ |
3169 | if ((msg->rsp_size >= 3) && (msg->rsp[2] != 0) | 3243 | if ((msg->rsp_size >= 3) && (msg->rsp[2] != 0) |
3170 | && (msg->rsp[2] != IPMI_NODE_BUSY_ERR) | 3244 | && (msg->rsp[2] != IPMI_NODE_BUSY_ERR) |
3171 | && (msg->rsp[2] != IPMI_LOST_ARBITRATION_ERR)) | 3245 | && (msg->rsp[2] != IPMI_LOST_ARBITRATION_ERR) |
3246 | && (msg->rsp[2] != IPMI_BUS_ERR) | ||
3247 | && (msg->rsp[2] != IPMI_NAK_ON_WRITE_ERR)) | ||
3172 | { | 3248 | { |
3173 | int chan = msg->rsp[3] & 0xf; | 3249 | int chan = msg->rsp[3] & 0xf; |
3174 | 3250 | ||
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 24825bdca8f4..bb1fac104fda 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -1211,7 +1211,7 @@ static void intf_mem_outb(struct si_sm_io *io, unsigned int offset, | |||
1211 | static unsigned char intf_mem_inw(struct si_sm_io *io, unsigned int offset) | 1211 | static unsigned char intf_mem_inw(struct si_sm_io *io, unsigned int offset) |
1212 | { | 1212 | { |
1213 | return (readw((io->addr)+(offset * io->regspacing)) >> io->regshift) | 1213 | return (readw((io->addr)+(offset * io->regspacing)) >> io->regshift) |
1214 | && 0xff; | 1214 | & 0xff; |
1215 | } | 1215 | } |
1216 | 1216 | ||
1217 | static void intf_mem_outw(struct si_sm_io *io, unsigned int offset, | 1217 | static void intf_mem_outw(struct si_sm_io *io, unsigned int offset, |
@@ -1223,7 +1223,7 @@ static void intf_mem_outw(struct si_sm_io *io, unsigned int offset, | |||
1223 | static unsigned char intf_mem_inl(struct si_sm_io *io, unsigned int offset) | 1223 | static unsigned char intf_mem_inl(struct si_sm_io *io, unsigned int offset) |
1224 | { | 1224 | { |
1225 | return (readl((io->addr)+(offset * io->regspacing)) >> io->regshift) | 1225 | return (readl((io->addr)+(offset * io->regspacing)) >> io->regshift) |
1226 | && 0xff; | 1226 | & 0xff; |
1227 | } | 1227 | } |
1228 | 1228 | ||
1229 | static void intf_mem_outl(struct si_sm_io *io, unsigned int offset, | 1229 | static void intf_mem_outl(struct si_sm_io *io, unsigned int offset, |
@@ -1236,7 +1236,7 @@ static void intf_mem_outl(struct si_sm_io *io, unsigned int offset, | |||
1236 | static unsigned char mem_inq(struct si_sm_io *io, unsigned int offset) | 1236 | static unsigned char mem_inq(struct si_sm_io *io, unsigned int offset) |
1237 | { | 1237 | { |
1238 | return (readq((io->addr)+(offset * io->regspacing)) >> io->regshift) | 1238 | return (readq((io->addr)+(offset * io->regspacing)) >> io->regshift) |
1239 | && 0xff; | 1239 | & 0xff; |
1240 | } | 1240 | } |
1241 | 1241 | ||
1242 | static void mem_outq(struct si_sm_io *io, unsigned int offset, | 1242 | static void mem_outq(struct si_sm_io *io, unsigned int offset, |
@@ -1789,7 +1789,7 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, | |||
1789 | 1789 | ||
1790 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 1790 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
1791 | if (!info) | 1791 | if (!info) |
1792 | return ENOMEM; | 1792 | return -ENOMEM; |
1793 | 1793 | ||
1794 | info->addr_source = "PCI"; | 1794 | info->addr_source = "PCI"; |
1795 | 1795 | ||
@@ -1810,7 +1810,7 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, | |||
1810 | kfree(info); | 1810 | kfree(info); |
1811 | printk(KERN_INFO "ipmi_si: %s: Unknown IPMI type: %d\n", | 1811 | printk(KERN_INFO "ipmi_si: %s: Unknown IPMI type: %d\n", |
1812 | pci_name(pdev), class_type); | 1812 | pci_name(pdev), class_type); |
1813 | return ENOMEM; | 1813 | return -ENOMEM; |
1814 | } | 1814 | } |
1815 | 1815 | ||
1816 | rv = pci_enable_device(pdev); | 1816 | rv = pci_enable_device(pdev); |
@@ -1867,7 +1867,7 @@ static int ipmi_pci_resume(struct pci_dev *pdev) | |||
1867 | 1867 | ||
1868 | static struct pci_device_id ipmi_pci_devices[] = { | 1868 | static struct pci_device_id ipmi_pci_devices[] = { |
1869 | { PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) }, | 1869 | { PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) }, |
1870 | { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE) } | 1870 | { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) } |
1871 | }; | 1871 | }; |
1872 | MODULE_DEVICE_TABLE(pci, ipmi_pci_devices); | 1872 | MODULE_DEVICE_TABLE(pci, ipmi_pci_devices); |
1873 | 1873 | ||
@@ -2346,7 +2346,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2346 | new_smi->dev = &new_smi->pdev->dev; | 2346 | new_smi->dev = &new_smi->pdev->dev; |
2347 | new_smi->dev->driver = &ipmi_driver; | 2347 | new_smi->dev->driver = &ipmi_driver; |
2348 | 2348 | ||
2349 | rv = platform_device_register(new_smi->pdev); | 2349 | rv = platform_device_add(new_smi->pdev); |
2350 | if (rv) { | 2350 | if (rv) { |
2351 | printk(KERN_ERR | 2351 | printk(KERN_ERR |
2352 | "ipmi_si_intf:" | 2352 | "ipmi_si_intf:" |
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index e9e9bf31c369..58c955e390b3 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -1062,11 +1062,12 @@ static void isicom_shutdown_port(struct isi_port *port) | |||
1062 | static void isicom_close(struct tty_struct *tty, struct file *filp) | 1062 | static void isicom_close(struct tty_struct *tty, struct file *filp) |
1063 | { | 1063 | { |
1064 | struct isi_port *port = tty->driver_data; | 1064 | struct isi_port *port = tty->driver_data; |
1065 | struct isi_board *card = port->card; | 1065 | struct isi_board *card; |
1066 | unsigned long flags; | 1066 | unsigned long flags; |
1067 | 1067 | ||
1068 | if (!port) | 1068 | if (!port) |
1069 | return; | 1069 | return; |
1070 | card = port->card; | ||
1070 | if (isicom_paranoia_check(port, tty->name, "isicom_close")) | 1071 | if (isicom_paranoia_check(port, tty->name, "isicom_close")) |
1071 | return; | 1072 | return; |
1072 | 1073 | ||
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 6511012cbdcd..55473371b7c6 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/backing-dev.h> | 26 | #include <linux/backing-dev.h> |
27 | #include <linux/bootmem.h> | 27 | #include <linux/bootmem.h> |
28 | #include <linux/pipe_fs_i.h> | 28 | #include <linux/pipe_fs_i.h> |
29 | #include <linux/pfn.h> | ||
29 | 30 | ||
30 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
31 | #include <asm/io.h> | 32 | #include <asm/io.h> |
@@ -292,8 +293,8 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma) | |||
292 | { | 293 | { |
293 | unsigned long pfn; | 294 | unsigned long pfn; |
294 | 295 | ||
295 | /* Turn a kernel-virtual address into a physical page frame */ | 296 | /* Turn a pfn offset into an absolute pfn */ |
296 | pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT; | 297 | pfn = PFN_DOWN(virt_to_phys((void *)PAGE_OFFSET)) + vma->vm_pgoff; |
297 | 298 | ||
298 | /* | 299 | /* |
299 | * RED-PEN: on some architectures there is more mapped memory | 300 | * RED-PEN: on some architectures there is more mapped memory |
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index b401383808c2..96cb1f07332b 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c | |||
@@ -130,6 +130,7 @@ static moxa_isa_board_conf moxa_isa_boards[] = | |||
130 | typedef struct _moxa_pci_devinfo { | 130 | typedef struct _moxa_pci_devinfo { |
131 | ushort busNum; | 131 | ushort busNum; |
132 | ushort devNum; | 132 | ushort devNum; |
133 | struct pci_dev *pdev; | ||
133 | } moxa_pci_devinfo; | 134 | } moxa_pci_devinfo; |
134 | 135 | ||
135 | typedef struct _moxa_board_conf { | 136 | typedef struct _moxa_board_conf { |
@@ -324,6 +325,9 @@ static int moxa_get_PCI_conf(struct pci_dev *p, int board_type, moxa_board_conf | |||
324 | board->busType = MOXA_BUS_TYPE_PCI; | 325 | board->busType = MOXA_BUS_TYPE_PCI; |
325 | board->pciInfo.busNum = p->bus->number; | 326 | board->pciInfo.busNum = p->bus->number; |
326 | board->pciInfo.devNum = p->devfn >> 3; | 327 | board->pciInfo.devNum = p->devfn >> 3; |
328 | board->pciInfo.pdev = p; | ||
329 | /* don't lose the reference in the next pci_get_device iteration */ | ||
330 | pci_dev_get(p); | ||
327 | 331 | ||
328 | return (0); | 332 | return (0); |
329 | } | 333 | } |
@@ -493,6 +497,11 @@ static void __exit moxa_exit(void) | |||
493 | if (tty_unregister_driver(moxaDriver)) | 497 | if (tty_unregister_driver(moxaDriver)) |
494 | printk("Couldn't unregister MOXA Intellio family serial driver\n"); | 498 | printk("Couldn't unregister MOXA Intellio family serial driver\n"); |
495 | put_tty_driver(moxaDriver); | 499 | put_tty_driver(moxaDriver); |
500 | |||
501 | for (i = 0; i < MAX_BOARDS; i++) | ||
502 | if (moxa_boards[i].busType == MOXA_BUS_TYPE_PCI) | ||
503 | pci_dev_put(moxa_boards[i].pciInfo.pdev); | ||
504 | |||
496 | if (verbose) | 505 | if (verbose) |
497 | printk("Done\n"); | 506 | printk("Done\n"); |
498 | } | 507 | } |
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c index 5c0dec39cf6c..235e89226112 100644 --- a/drivers/char/mspec.c +++ b/drivers/char/mspec.c | |||
@@ -72,7 +72,11 @@ enum { | |||
72 | MSPEC_UNCACHED | 72 | MSPEC_UNCACHED |
73 | }; | 73 | }; |
74 | 74 | ||
75 | #ifdef CONFIG_SGI_SN | ||
75 | static int is_sn2; | 76 | static int is_sn2; |
77 | #else | ||
78 | #define is_sn2 0 | ||
79 | #endif | ||
76 | 80 | ||
77 | /* | 81 | /* |
78 | * One of these structures is allocated when an mspec region is mmaped. The | 82 | * One of these structures is allocated when an mspec region is mmaped. The |
@@ -211,7 +215,7 @@ mspec_nopfn(struct vm_area_struct *vma, unsigned long address) | |||
211 | if (vdata->type == MSPEC_FETCHOP) | 215 | if (vdata->type == MSPEC_FETCHOP) |
212 | paddr = TO_AMO(maddr); | 216 | paddr = TO_AMO(maddr); |
213 | else | 217 | else |
214 | paddr = __pa(TO_CAC(maddr)); | 218 | paddr = maddr & ~__IA64_UNCACHED_OFFSET; |
215 | 219 | ||
216 | pfn = paddr >> PAGE_SHIFT; | 220 | pfn = paddr >> PAGE_SHIFT; |
217 | 221 | ||
@@ -335,6 +339,7 @@ mspec_init(void) | |||
335 | * The fetchop device only works on SN2 hardware, uncached and cached | 339 | * The fetchop device only works on SN2 hardware, uncached and cached |
336 | * memory drivers should both be valid on all ia64 hardware | 340 | * memory drivers should both be valid on all ia64 hardware |
337 | */ | 341 | */ |
342 | #ifdef CONFIG_SGI_SN | ||
338 | if (ia64_platform_is("sn2")) { | 343 | if (ia64_platform_is("sn2")) { |
339 | is_sn2 = 1; | 344 | is_sn2 = 1; |
340 | if (is_shub2()) { | 345 | if (is_shub2()) { |
@@ -363,6 +368,7 @@ mspec_init(void) | |||
363 | goto free_scratch_pages; | 368 | goto free_scratch_pages; |
364 | } | 369 | } |
365 | } | 370 | } |
371 | #endif | ||
366 | ret = misc_register(&cached_miscdev); | 372 | ret = misc_register(&cached_miscdev); |
367 | if (ret) { | 373 | if (ret) { |
368 | printk(KERN_ERR "%s: failed to register device %i\n", | 374 | printk(KERN_ERR "%s: failed to register device %i\n", |
diff --git a/drivers/char/random.c b/drivers/char/random.c index 07f47a0208a7..eb6b13f4211a 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -645,6 +645,7 @@ void add_input_randomness(unsigned int type, unsigned int code, | |||
645 | add_timer_randomness(&input_timer_state, | 645 | add_timer_randomness(&input_timer_state, |
646 | (type << 4) ^ code ^ (code >> 4) ^ value); | 646 | (type << 4) ^ code ^ (code >> 4) ^ value); |
647 | } | 647 | } |
648 | EXPORT_SYMBOL_GPL(add_input_randomness); | ||
648 | 649 | ||
649 | void add_interrupt_randomness(int irq) | 650 | void add_interrupt_randomness(int irq) |
650 | { | 651 | { |
diff --git a/drivers/char/rio/host.h b/drivers/char/rio/host.h index ee2ddea7a63a..23d0681fe491 100644 --- a/drivers/char/rio/host.h +++ b/drivers/char/rio/host.h | |||
@@ -44,6 +44,7 @@ | |||
44 | ** the host. | 44 | ** the host. |
45 | */ | 45 | */ |
46 | struct Host { | 46 | struct Host { |
47 | struct pci_dev *pdev; | ||
47 | unsigned char Type; /* RIO_EISA, RIO_MCA, ... */ | 48 | unsigned char Type; /* RIO_EISA, RIO_MCA, ... */ |
48 | unsigned char Ivec; /* POLLED or ivec number */ | 49 | unsigned char Ivec; /* POLLED or ivec number */ |
49 | unsigned char Mode; /* Control stuff */ | 50 | unsigned char Mode; /* Control stuff */ |
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index c382df0f82f6..7ac68cb3bedd 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c | |||
@@ -1017,6 +1017,10 @@ static int __init rio_init(void) | |||
1017 | rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum); | 1017 | rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum); |
1018 | 1018 | ||
1019 | fix_rio_pci(pdev); | 1019 | fix_rio_pci(pdev); |
1020 | |||
1021 | p->RIOHosts[p->RIONumHosts].pdev = pdev; | ||
1022 | pci_dev_get(pdev); | ||
1023 | |||
1020 | p->RIOLastPCISearch = 0; | 1024 | p->RIOLastPCISearch = 0; |
1021 | p->RIONumHosts++; | 1025 | p->RIONumHosts++; |
1022 | found++; | 1026 | found++; |
@@ -1066,6 +1070,9 @@ static int __init rio_init(void) | |||
1066 | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24); | 1070 | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24); |
1067 | rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum); | 1071 | rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum); |
1068 | 1072 | ||
1073 | p->RIOHosts[p->RIONumHosts].pdev = pdev; | ||
1074 | pci_dev_get(pdev); | ||
1075 | |||
1069 | p->RIOLastPCISearch = 0; | 1076 | p->RIOLastPCISearch = 0; |
1070 | p->RIONumHosts++; | 1077 | p->RIONumHosts++; |
1071 | found++; | 1078 | found++; |
@@ -1181,6 +1188,8 @@ static void __exit rio_exit(void) | |||
1181 | } | 1188 | } |
1182 | /* It is safe/allowed to del_timer a non-active timer */ | 1189 | /* It is safe/allowed to del_timer a non-active timer */ |
1183 | del_timer(&hp->timer); | 1190 | del_timer(&hp->timer); |
1191 | if (hp->Type == RIO_PCI) | ||
1192 | pci_dev_put(hp->pdev); | ||
1184 | } | 1193 | } |
1185 | 1194 | ||
1186 | if (misc_deregister(&rio_fw_device) < 0) { | 1195 | if (misc_deregister(&rio_fw_device) < 0) { |
diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c index 052e8120a471..7ce77619707c 100644 --- a/drivers/char/rio/rioctrl.c +++ b/drivers/char/rio/rioctrl.c | |||
@@ -662,7 +662,7 @@ int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su | |||
662 | p->RIOError.Error = COPYIN_FAILED; | 662 | p->RIOError.Error = COPYIN_FAILED; |
663 | return -EFAULT; | 663 | return -EFAULT; |
664 | } | 664 | } |
665 | if (portStats.port >= RIO_PORTS) { | 665 | if (portStats.port < 0 || portStats.port >= RIO_PORTS) { |
666 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | 666 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; |
667 | return -ENXIO; | 667 | return -ENXIO; |
668 | } | 668 | } |
@@ -702,7 +702,7 @@ int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su | |||
702 | p->RIOError.Error = COPYIN_FAILED; | 702 | p->RIOError.Error = COPYIN_FAILED; |
703 | return -EFAULT; | 703 | return -EFAULT; |
704 | } | 704 | } |
705 | if (portStats.port >= RIO_PORTS) { | 705 | if (portStats.port < 0 || portStats.port >= RIO_PORTS) { |
706 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | 706 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; |
707 | return -ENXIO; | 707 | return -ENXIO; |
708 | } | 708 | } |
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 461bfe0234c9..3af7f0958c5d 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c | |||
@@ -839,7 +839,7 @@ shutdown(struct cyclades_port * info) | |||
839 | local_irq_save(flags); | 839 | local_irq_save(flags); |
840 | if (info->xmit_buf){ | 840 | if (info->xmit_buf){ |
841 | free_page((unsigned long) info->xmit_buf); | 841 | free_page((unsigned long) info->xmit_buf); |
842 | info->xmit_buf = 0; | 842 | info->xmit_buf = NULL; |
843 | } | 843 | } |
844 | 844 | ||
845 | base_addr[CyCAR] = (u_char)channel; | 845 | base_addr[CyCAR] = (u_char)channel; |
@@ -1354,7 +1354,7 @@ cy_unthrottle(struct tty_struct * tty) | |||
1354 | 1354 | ||
1355 | static int | 1355 | static int |
1356 | get_serial_info(struct cyclades_port * info, | 1356 | get_serial_info(struct cyclades_port * info, |
1357 | struct serial_struct * retinfo) | 1357 | struct serial_struct __user * retinfo) |
1358 | { | 1358 | { |
1359 | struct serial_struct tmp; | 1359 | struct serial_struct tmp; |
1360 | 1360 | ||
@@ -1376,7 +1376,7 @@ get_serial_info(struct cyclades_port * info, | |||
1376 | 1376 | ||
1377 | static int | 1377 | static int |
1378 | set_serial_info(struct cyclades_port * info, | 1378 | set_serial_info(struct cyclades_port * info, |
1379 | struct serial_struct * new_info) | 1379 | struct serial_struct __user * new_info) |
1380 | { | 1380 | { |
1381 | struct serial_struct new_serial; | 1381 | struct serial_struct new_serial; |
1382 | struct cyclades_port old_info; | 1382 | struct cyclades_port old_info; |
@@ -1503,7 +1503,7 @@ send_break( struct cyclades_port * info, int duration) | |||
1503 | } /* send_break */ | 1503 | } /* send_break */ |
1504 | 1504 | ||
1505 | static int | 1505 | static int |
1506 | get_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon) | 1506 | get_mon_info(struct cyclades_port * info, struct cyclades_monitor __user * mon) |
1507 | { | 1507 | { |
1508 | 1508 | ||
1509 | if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor))) | 1509 | if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor))) |
@@ -1516,7 +1516,7 @@ get_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon) | |||
1516 | } | 1516 | } |
1517 | 1517 | ||
1518 | static int | 1518 | static int |
1519 | set_threshold(struct cyclades_port * info, unsigned long *arg) | 1519 | set_threshold(struct cyclades_port * info, unsigned long __user *arg) |
1520 | { | 1520 | { |
1521 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 1521 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; |
1522 | unsigned long value; | 1522 | unsigned long value; |
@@ -1533,7 +1533,7 @@ set_threshold(struct cyclades_port * info, unsigned long *arg) | |||
1533 | } | 1533 | } |
1534 | 1534 | ||
1535 | static int | 1535 | static int |
1536 | get_threshold(struct cyclades_port * info, unsigned long *value) | 1536 | get_threshold(struct cyclades_port * info, unsigned long __user *value) |
1537 | { | 1537 | { |
1538 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 1538 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; |
1539 | int channel; | 1539 | int channel; |
@@ -1546,7 +1546,7 @@ get_threshold(struct cyclades_port * info, unsigned long *value) | |||
1546 | } | 1546 | } |
1547 | 1547 | ||
1548 | static int | 1548 | static int |
1549 | set_default_threshold(struct cyclades_port * info, unsigned long *arg) | 1549 | set_default_threshold(struct cyclades_port * info, unsigned long __user *arg) |
1550 | { | 1550 | { |
1551 | unsigned long value; | 1551 | unsigned long value; |
1552 | 1552 | ||
@@ -1558,13 +1558,13 @@ set_default_threshold(struct cyclades_port * info, unsigned long *arg) | |||
1558 | } | 1558 | } |
1559 | 1559 | ||
1560 | static int | 1560 | static int |
1561 | get_default_threshold(struct cyclades_port * info, unsigned long *value) | 1561 | get_default_threshold(struct cyclades_port * info, unsigned long __user *value) |
1562 | { | 1562 | { |
1563 | return put_user(info->default_threshold,value); | 1563 | return put_user(info->default_threshold,value); |
1564 | } | 1564 | } |
1565 | 1565 | ||
1566 | static int | 1566 | static int |
1567 | set_timeout(struct cyclades_port * info, unsigned long *arg) | 1567 | set_timeout(struct cyclades_port * info, unsigned long __user *arg) |
1568 | { | 1568 | { |
1569 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 1569 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; |
1570 | int channel; | 1570 | int channel; |
@@ -1581,7 +1581,7 @@ set_timeout(struct cyclades_port * info, unsigned long *arg) | |||
1581 | } | 1581 | } |
1582 | 1582 | ||
1583 | static int | 1583 | static int |
1584 | get_timeout(struct cyclades_port * info, unsigned long *value) | 1584 | get_timeout(struct cyclades_port * info, unsigned long __user *value) |
1585 | { | 1585 | { |
1586 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 1586 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; |
1587 | int channel; | 1587 | int channel; |
@@ -1601,7 +1601,7 @@ set_default_timeout(struct cyclades_port * info, unsigned long value) | |||
1601 | } | 1601 | } |
1602 | 1602 | ||
1603 | static int | 1603 | static int |
1604 | get_default_timeout(struct cyclades_port * info, unsigned long *value) | 1604 | get_default_timeout(struct cyclades_port * info, unsigned long __user *value) |
1605 | { | 1605 | { |
1606 | return put_user(info->default_timeout,value); | 1606 | return put_user(info->default_timeout,value); |
1607 | } | 1607 | } |
@@ -1613,6 +1613,7 @@ cy_ioctl(struct tty_struct *tty, struct file * file, | |||
1613 | unsigned long val; | 1613 | unsigned long val; |
1614 | struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; | 1614 | struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; |
1615 | int ret_val = 0; | 1615 | int ret_val = 0; |
1616 | void __user *argp = (void __user *)arg; | ||
1616 | 1617 | ||
1617 | #ifdef SERIAL_DEBUG_OTHER | 1618 | #ifdef SERIAL_DEBUG_OTHER |
1618 | printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */ | 1619 | printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */ |
@@ -1620,28 +1621,28 @@ cy_ioctl(struct tty_struct *tty, struct file * file, | |||
1620 | 1621 | ||
1621 | switch (cmd) { | 1622 | switch (cmd) { |
1622 | case CYGETMON: | 1623 | case CYGETMON: |
1623 | ret_val = get_mon_info(info, (struct cyclades_monitor *)arg); | 1624 | ret_val = get_mon_info(info, argp); |
1624 | break; | 1625 | break; |
1625 | case CYGETTHRESH: | 1626 | case CYGETTHRESH: |
1626 | ret_val = get_threshold(info, (unsigned long *)arg); | 1627 | ret_val = get_threshold(info, argp); |
1627 | break; | 1628 | break; |
1628 | case CYSETTHRESH: | 1629 | case CYSETTHRESH: |
1629 | ret_val = set_threshold(info, (unsigned long *)arg); | 1630 | ret_val = set_threshold(info, argp); |
1630 | break; | 1631 | break; |
1631 | case CYGETDEFTHRESH: | 1632 | case CYGETDEFTHRESH: |
1632 | ret_val = get_default_threshold(info, (unsigned long *)arg); | 1633 | ret_val = get_default_threshold(info, argp); |
1633 | break; | 1634 | break; |
1634 | case CYSETDEFTHRESH: | 1635 | case CYSETDEFTHRESH: |
1635 | ret_val = set_default_threshold(info, (unsigned long *)arg); | 1636 | ret_val = set_default_threshold(info, argp); |
1636 | break; | 1637 | break; |
1637 | case CYGETTIMEOUT: | 1638 | case CYGETTIMEOUT: |
1638 | ret_val = get_timeout(info, (unsigned long *)arg); | 1639 | ret_val = get_timeout(info, argp); |
1639 | break; | 1640 | break; |
1640 | case CYSETTIMEOUT: | 1641 | case CYSETTIMEOUT: |
1641 | ret_val = set_timeout(info, (unsigned long *)arg); | 1642 | ret_val = set_timeout(info, argp); |
1642 | break; | 1643 | break; |
1643 | case CYGETDEFTIMEOUT: | 1644 | case CYGETDEFTIMEOUT: |
1644 | ret_val = get_default_timeout(info, (unsigned long *)arg); | 1645 | ret_val = get_default_timeout(info, argp); |
1645 | break; | 1646 | break; |
1646 | case CYSETDEFTIMEOUT: | 1647 | case CYSETDEFTIMEOUT: |
1647 | ret_val = set_default_timeout(info, (unsigned long)arg); | 1648 | ret_val = set_default_timeout(info, (unsigned long)arg); |
@@ -1664,21 +1665,20 @@ cy_ioctl(struct tty_struct *tty, struct file * file, | |||
1664 | 1665 | ||
1665 | /* The following commands are incompletely implemented!!! */ | 1666 | /* The following commands are incompletely implemented!!! */ |
1666 | case TIOCGSOFTCAR: | 1667 | case TIOCGSOFTCAR: |
1667 | ret_val = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg); | 1668 | ret_val = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) argp); |
1668 | break; | 1669 | break; |
1669 | case TIOCSSOFTCAR: | 1670 | case TIOCSSOFTCAR: |
1670 | ret_val = get_user(val, (unsigned long *) arg); | 1671 | ret_val = get_user(val, (unsigned long __user *) argp); |
1671 | if (ret_val) | 1672 | if (ret_val) |
1672 | break; | 1673 | break; |
1673 | tty->termios->c_cflag = | 1674 | tty->termios->c_cflag = |
1674 | ((tty->termios->c_cflag & ~CLOCAL) | (val ? CLOCAL : 0)); | 1675 | ((tty->termios->c_cflag & ~CLOCAL) | (val ? CLOCAL : 0)); |
1675 | break; | 1676 | break; |
1676 | case TIOCGSERIAL: | 1677 | case TIOCGSERIAL: |
1677 | ret_val = get_serial_info(info, (struct serial_struct *) arg); | 1678 | ret_val = get_serial_info(info, argp); |
1678 | break; | 1679 | break; |
1679 | case TIOCSSERIAL: | 1680 | case TIOCSSERIAL: |
1680 | ret_val = set_serial_info(info, | 1681 | ret_val = set_serial_info(info, argp); |
1681 | (struct serial_struct *) arg); | ||
1682 | break; | 1682 | break; |
1683 | default: | 1683 | default: |
1684 | ret_val = -ENOIOCTLCMD; | 1684 | ret_val = -ENOIOCTLCMD; |
@@ -1773,7 +1773,7 @@ cy_close(struct tty_struct * tty, struct file * filp) | |||
1773 | tty->driver->flush_buffer(tty); | 1773 | tty->driver->flush_buffer(tty); |
1774 | tty_ldisc_flush(tty); | 1774 | tty_ldisc_flush(tty); |
1775 | info->event = 0; | 1775 | info->event = 0; |
1776 | info->tty = 0; | 1776 | info->tty = NULL; |
1777 | if (info->blocked_open) { | 1777 | if (info->blocked_open) { |
1778 | if (info->close_delay) { | 1778 | if (info->close_delay) { |
1779 | msleep_interruptible(jiffies_to_msecs(info->close_delay)); | 1779 | msleep_interruptible(jiffies_to_msecs(info->close_delay)); |
@@ -2250,7 +2250,7 @@ scrn[1] = '\0'; | |||
2250 | info->card = index; | 2250 | info->card = index; |
2251 | info->line = port_num; | 2251 | info->line = port_num; |
2252 | info->flags = STD_COM_FLAGS; | 2252 | info->flags = STD_COM_FLAGS; |
2253 | info->tty = 0; | 2253 | info->tty = NULL; |
2254 | info->xmit_fifo_size = 12; | 2254 | info->xmit_fifo_size = 12; |
2255 | info->cor1 = CyPARITY_NONE|Cy_8_BITS; | 2255 | info->cor1 = CyPARITY_NONE|Cy_8_BITS; |
2256 | info->cor2 = CyETC; | 2256 | info->cor2 = CyETC; |
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index d0b88d0e87fd..7e1bd9562c2a 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c | |||
@@ -183,11 +183,6 @@ static int sx_poll = HZ; | |||
183 | 183 | ||
184 | static struct tty_driver *specialix_driver; | 184 | static struct tty_driver *specialix_driver; |
185 | 185 | ||
186 | static unsigned long baud_table[] = { | ||
187 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, | ||
188 | 9600, 19200, 38400, 57600, 115200, 0, | ||
189 | }; | ||
190 | |||
191 | static struct specialix_board sx_board[SX_NBOARD] = { | 186 | static struct specialix_board sx_board[SX_NBOARD] = { |
192 | { 0, SX_IOBASE1, 9, }, | 187 | { 0, SX_IOBASE1, 9, }, |
193 | { 0, SX_IOBASE2, 11, }, | 188 | { 0, SX_IOBASE2, 11, }, |
@@ -1090,9 +1085,9 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1090 | 1085 | ||
1091 | if (baud == 38400) { | 1086 | if (baud == 38400) { |
1092 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) | 1087 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) |
1093 | baud ++; | 1088 | baud = 57600; |
1094 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) | 1089 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) |
1095 | baud += 2; | 1090 | baud = 115200; |
1096 | } | 1091 | } |
1097 | 1092 | ||
1098 | if (!baud) { | 1093 | if (!baud) { |
@@ -1150,11 +1145,9 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1150 | sx_out(bp, CD186x_RBPRL, tmp & 0xff); | 1145 | sx_out(bp, CD186x_RBPRL, tmp & 0xff); |
1151 | sx_out(bp, CD186x_TBPRL, tmp & 0xff); | 1146 | sx_out(bp, CD186x_TBPRL, tmp & 0xff); |
1152 | spin_unlock_irqrestore(&bp->lock, flags); | 1147 | spin_unlock_irqrestore(&bp->lock, flags); |
1153 | if (port->custom_divisor) { | 1148 | if (port->custom_divisor) |
1154 | baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor; | 1149 | baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor; |
1155 | baud = ( baud + 5 ) / 10; | 1150 | baud = (baud + 5) / 10; /* Estimated CPS */ |
1156 | } else | ||
1157 | baud = (baud_table[baud] + 5) / 10; /* Estimated CPS */ | ||
1158 | 1151 | ||
1159 | /* Two timer ticks seems enough to wakeup something like SLIP driver */ | 1152 | /* Two timer ticks seems enough to wakeup something like SLIP driver */ |
1160 | tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO; | 1153 | tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO; |
diff --git a/drivers/char/sx.c b/drivers/char/sx.c index 5fec626598cd..cc10af08cb05 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c | |||
@@ -2602,7 +2602,7 @@ static void __exit sx_exit (void) | |||
2602 | } | 2602 | } |
2603 | } | 2603 | } |
2604 | if (misc_deregister(&sx_fw_device) < 0) { | 2604 | if (misc_deregister(&sx_fw_device) < 0) { |
2605 | printk (KERN_INFO "sx: couldn't deregister firmware loader devic\n"); | 2605 | printk (KERN_INFO "sx: couldn't deregister firmware loader device\n"); |
2606 | } | 2606 | } |
2607 | sx_dprintk (SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n", sx_initialized); | 2607 | sx_dprintk (SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n", sx_initialized); |
2608 | if (sx_initialized) | 2608 | if (sx_initialized) |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index f2864cc64240..06784adcc35c 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -133,8 +133,8 @@ static MGSL_PARAMS default_params = { | |||
133 | }; | 133 | }; |
134 | 134 | ||
135 | #define SHARED_MEM_ADDRESS_SIZE 0x40000 | 135 | #define SHARED_MEM_ADDRESS_SIZE 0x40000 |
136 | #define BUFFERLISTSIZE (PAGE_SIZE) | 136 | #define BUFFERLISTSIZE 4096 |
137 | #define DMABUFFERSIZE (PAGE_SIZE) | 137 | #define DMABUFFERSIZE 4096 |
138 | #define MAXRXFRAMES 7 | 138 | #define MAXRXFRAMES 7 |
139 | 139 | ||
140 | typedef struct _DMABUFFERENTRY | 140 | typedef struct _DMABUFFERENTRY |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index a082a2e34252..6ad2d3bb945c 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -1153,7 +1153,14 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend | |||
1153 | 1153 | ||
1154 | spin_unlock(&driver_lock); | 1154 | spin_unlock(&driver_lock); |
1155 | 1155 | ||
1156 | sysfs_create_group(&dev->kobj, chip->vendor.attr_group); | 1156 | if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) { |
1157 | list_del(&chip->list); | ||
1158 | put_device(dev); | ||
1159 | clear_bit(chip->dev_num, dev_mask); | ||
1160 | kfree(chip); | ||
1161 | kfree(devname); | ||
1162 | return NULL; | ||
1163 | } | ||
1157 | 1164 | ||
1158 | chip->bios_dir = tpm_bios_log_setup(devname); | 1165 | chip->bios_dir = tpm_bios_log_setup(devname); |
1159 | 1166 | ||
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index ad8ffe49256f..1ab0896070be 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c | |||
@@ -184,7 +184,9 @@ static int __init init_atmel(void) | |||
184 | unsigned long base; | 184 | unsigned long base; |
185 | struct tpm_chip *chip; | 185 | struct tpm_chip *chip; |
186 | 186 | ||
187 | driver_register(&atml_drv); | 187 | rc = driver_register(&atml_drv); |
188 | if (rc) | ||
189 | return rc; | ||
188 | 190 | ||
189 | if ((iobase = atmel_get_base_addr(&base, ®ion_size)) == NULL) { | 191 | if ((iobase = atmel_get_base_addr(&base, ®ion_size)) == NULL) { |
190 | rc = -ENODEV; | 192 | rc = -ENODEV; |
@@ -195,10 +197,8 @@ static int __init init_atmel(void) | |||
195 | (atmel_request_region | 197 | (atmel_request_region |
196 | (tpm_atmel.base, region_size, "tpm_atmel0") == NULL) ? 0 : 1; | 198 | (tpm_atmel.base, region_size, "tpm_atmel0") == NULL) ? 0 : 1; |
197 | 199 | ||
198 | 200 | pdev = platform_device_register_simple("tpm_atmel", -1, NULL, 0); | |
199 | if (IS_ERR | 201 | if (IS_ERR(pdev)) { |
200 | (pdev = | ||
201 | platform_device_register_simple("tpm_atmel", -1, NULL, 0))) { | ||
202 | rc = PTR_ERR(pdev); | 202 | rc = PTR_ERR(pdev); |
203 | goto err_rel_reg; | 203 | goto err_rel_reg; |
204 | } | 204 | } |
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c index 26287aace87d..608f73071bef 100644 --- a/drivers/char/tpm/tpm_nsc.c +++ b/drivers/char/tpm/tpm_nsc.c | |||
@@ -284,7 +284,7 @@ static struct device_driver nsc_drv = { | |||
284 | static int __init init_nsc(void) | 284 | static int __init init_nsc(void) |
285 | { | 285 | { |
286 | int rc = 0; | 286 | int rc = 0; |
287 | int lo, hi; | 287 | int lo, hi, err; |
288 | int nscAddrBase = TPM_ADDR; | 288 | int nscAddrBase = TPM_ADDR; |
289 | struct tpm_chip *chip; | 289 | struct tpm_chip *chip; |
290 | unsigned long base; | 290 | unsigned long base; |
@@ -297,7 +297,9 @@ static int __init init_nsc(void) | |||
297 | return -ENODEV; | 297 | return -ENODEV; |
298 | } | 298 | } |
299 | 299 | ||
300 | driver_register(&nsc_drv); | 300 | err = driver_register(&nsc_drv); |
301 | if (err) | ||
302 | return err; | ||
301 | 303 | ||
302 | hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI); | 304 | hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI); |
303 | lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO); | 305 | lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO); |
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 89e46d6dfc4e..0187b1185323 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig | |||
@@ -13,7 +13,7 @@ config WATCHDOG | |||
13 | subsequently opening the file and then failing to write to it for | 13 | subsequently opening the file and then failing to write to it for |
14 | longer than 1 minute will result in rebooting the machine. This | 14 | longer than 1 minute will result in rebooting the machine. This |
15 | could be useful for a networked machine that needs to come back | 15 | could be useful for a networked machine that needs to come back |
16 | online as fast as possible after a lock-up. There's both a watchdog | 16 | on-line as fast as possible after a lock-up. There's both a watchdog |
17 | implementation entirely in software (which can sometimes fail to | 17 | implementation entirely in software (which can sometimes fail to |
18 | reboot the machine) and a driver for hardware watchdog boards, which | 18 | reboot the machine) and a driver for hardware watchdog boards, which |
19 | are more robust and can also keep track of the temperature inside | 19 | are more robust and can also keep track of the temperature inside |
@@ -60,7 +60,7 @@ config SOFT_WATCHDOG | |||
60 | 60 | ||
61 | # ARM Architecture | 61 | # ARM Architecture |
62 | 62 | ||
63 | config AT91_WATCHDOG | 63 | config AT91RM9200_WATCHDOG |
64 | tristate "AT91RM9200 watchdog" | 64 | tristate "AT91RM9200 watchdog" |
65 | depends on WATCHDOG && ARCH_AT91RM9200 | 65 | depends on WATCHDOG && ARCH_AT91RM9200 |
66 | help | 66 | help |
@@ -71,7 +71,7 @@ config 21285_WATCHDOG | |||
71 | tristate "DC21285 watchdog" | 71 | tristate "DC21285 watchdog" |
72 | depends on WATCHDOG && FOOTBRIDGE | 72 | depends on WATCHDOG && FOOTBRIDGE |
73 | help | 73 | help |
74 | The Intel Footbridge chip contains a builtin watchdog circuit. Say Y | 74 | The Intel Footbridge chip contains a built-in watchdog circuit. Say Y |
75 | here if you wish to use this. Alternatively say M to compile the | 75 | here if you wish to use this. Alternatively say M to compile the |
76 | driver as a module, which will be called wdt285. | 76 | driver as a module, which will be called wdt285. |
77 | 77 | ||
@@ -269,11 +269,11 @@ config IB700_WDT | |||
269 | Most people will say N. | 269 | Most people will say N. |
270 | 270 | ||
271 | config IBMASR | 271 | config IBMASR |
272 | tristate "IBM Automatic Server Restart" | 272 | tristate "IBM Automatic Server Restart" |
273 | depends on WATCHDOG && X86 | 273 | depends on WATCHDOG && X86 |
274 | help | 274 | help |
275 | This is the driver for the IBM Automatic Server Restart watchdog | 275 | This is the driver for the IBM Automatic Server Restart watchdog |
276 | timer builtin into some eServer xSeries machines. | 276 | timer built-in into some eServer xSeries machines. |
277 | 277 | ||
278 | To compile this driver as a module, choose M here: the | 278 | To compile this driver as a module, choose M here: the |
279 | module will be called ibmasr. | 279 | module will be called ibmasr. |
@@ -316,13 +316,16 @@ config I8XX_TCO | |||
316 | To compile this driver as a module, choose M here: the | 316 | To compile this driver as a module, choose M here: the |
317 | module will be called i8xx_tco. | 317 | module will be called i8xx_tco. |
318 | 318 | ||
319 | Note: This driver will be removed in the near future. Please | ||
320 | use the Intel TCO Timer/Watchdog driver. | ||
321 | |||
319 | config ITCO_WDT | 322 | config ITCO_WDT |
320 | tristate "Intel TCO Timer/Watchdog (EXPERIMENTAL)" | 323 | tristate "Intel TCO Timer/Watchdog" |
321 | depends on WATCHDOG && (X86 || IA64) && PCI && EXPERIMENTAL | 324 | depends on WATCHDOG && (X86 || IA64) && PCI |
322 | ---help--- | 325 | ---help--- |
323 | Hardware driver for the intel TCO timer based watchdog devices. | 326 | Hardware driver for the intel TCO timer based watchdog devices. |
324 | These drivers are included in the Intel 82801 I/O Controller | 327 | These drivers are included in the Intel 82801 I/O Controller |
325 | Hub family 'from ICH0 up to ICH7) and in the Intel 6300ESB | 328 | Hub family (from ICH0 up to ICH8) and in the Intel 6300ESB |
326 | controller hub. | 329 | controller hub. |
327 | 330 | ||
328 | The TCO (Total Cost of Ownership) timer is a watchdog timer | 331 | The TCO (Total Cost of Ownership) timer is a watchdog timer |
@@ -395,6 +398,26 @@ config CPU5_WDT | |||
395 | To compile this driver as a module, choose M here: the | 398 | To compile this driver as a module, choose M here: the |
396 | module will be called cpu5wdt. | 399 | module will be called cpu5wdt. |
397 | 400 | ||
401 | config SMSC37B787_WDT | ||
402 | tristate "Winbond SMsC37B787 Watchdog Timer" | ||
403 | depends on WATCHDOG && X86 | ||
404 | ---help--- | ||
405 | This is the driver for the hardware watchdog component on the | ||
406 | Winbond SMsC37B787 chipset as used on the NetRunner Mainboard | ||
407 | from Vision Systems and maybe others. | ||
408 | |||
409 | This watchdog simply watches your kernel to make sure it doesn't | ||
410 | freeze, and if it does, it reboots your computer after a certain | ||
411 | amount of time. | ||
412 | |||
413 | Usually a userspace daemon will notify the kernel WDT driver that | ||
414 | userspace is still alive, at regular intervals. | ||
415 | |||
416 | To compile this driver as a module, choose M here: the | ||
417 | module will be called smsc37b787_wdt. | ||
418 | |||
419 | Most people will say N. | ||
420 | |||
398 | config W83627HF_WDT | 421 | config W83627HF_WDT |
399 | tristate "W83627HF Watchdog Timer" | 422 | tristate "W83627HF Watchdog Timer" |
400 | depends on WATCHDOG && X86 | 423 | depends on WATCHDOG && X86 |
@@ -410,6 +433,21 @@ config W83627HF_WDT | |||
410 | 433 | ||
411 | Most people will say N. | 434 | Most people will say N. |
412 | 435 | ||
436 | config W83697HF_WDT | ||
437 | tristate "W83697HF/W83697HG Watchdog Timer" | ||
438 | depends on WATCHDOG && X86 | ||
439 | ---help--- | ||
440 | This is the driver for the hardware watchdog on the W83697HF/HG | ||
441 | chipset as used in Dedibox/VIA motherboards (and likely others). | ||
442 | This watchdog simply watches your kernel to make sure it doesn't | ||
443 | freeze, and if it does, it reboots your computer after a certain | ||
444 | amount of time. | ||
445 | |||
446 | To compile this driver as a module, choose M here: the | ||
447 | module will be called w83697hf_wdt. | ||
448 | |||
449 | Most people will say N. | ||
450 | |||
413 | config W83877F_WDT | 451 | config W83877F_WDT |
414 | tristate "W83877F (EMACS) Watchdog Timer" | 452 | tristate "W83877F (EMACS) Watchdog Timer" |
415 | depends on WATCHDOG && X86 | 453 | depends on WATCHDOG && X86 |
@@ -443,7 +481,7 @@ config MACHZ_WDT | |||
443 | depends on WATCHDOG && X86 | 481 | depends on WATCHDOG && X86 |
444 | ---help--- | 482 | ---help--- |
445 | If you are using a ZF Micro MachZ processor, say Y here, otherwise | 483 | If you are using a ZF Micro MachZ processor, say Y here, otherwise |
446 | N. This is the driver for the watchdog timer builtin on that | 484 | N. This is the driver for the watchdog timer built-in on that |
447 | processor using ZF-Logic interface. This watchdog simply watches | 485 | processor using ZF-Logic interface. This watchdog simply watches |
448 | your kernel to make sure it doesn't freeze, and if it does, it | 486 | your kernel to make sure it doesn't freeze, and if it does, it |
449 | reboots your computer after a certain amount of time. | 487 | reboots your computer after a certain amount of time. |
@@ -472,7 +510,6 @@ config SBC_EPX_C3_WATCHDOG | |||
472 | To compile this driver as a module, choose M here: the | 510 | To compile this driver as a module, choose M here: the |
473 | module will be called sbc_epx_c3. | 511 | module will be called sbc_epx_c3. |
474 | 512 | ||
475 | |||
476 | # PowerPC Architecture | 513 | # PowerPC Architecture |
477 | 514 | ||
478 | config 8xx_WDT | 515 | config 8xx_WDT |
@@ -502,7 +539,7 @@ config WATCHDOG_RTAS | |||
502 | help | 539 | help |
503 | This driver adds watchdog support for the RTAS watchdog. | 540 | This driver adds watchdog support for the RTAS watchdog. |
504 | 541 | ||
505 | To compile this driver as a module, choose M here. The module | 542 | To compile this driver as a module, choose M here. The module |
506 | will be called wdrtas. | 543 | will be called wdrtas. |
507 | 544 | ||
508 | # MIPS Architecture | 545 | # MIPS Architecture |
@@ -556,7 +593,7 @@ config SH_WDT_MMAP | |||
556 | help | 593 | help |
557 | If you say Y here, user applications will be able to mmap the | 594 | If you say Y here, user applications will be able to mmap the |
558 | WDT/CPG registers. | 595 | WDT/CPG registers. |
559 | # | 596 | |
560 | # SPARC64 Architecture | 597 | # SPARC64 Architecture |
561 | 598 | ||
562 | config WATCHDOG_CP1XXX | 599 | config WATCHDOG_CP1XXX |
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index 7f70abad465a..36440497047c 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile | |||
@@ -23,7 +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_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o |
27 | obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o | 27 | obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o |
28 | obj-$(CONFIG_21285_WATCHDOG) += wdt285.o | 28 | obj-$(CONFIG_21285_WATCHDOG) += wdt285.o |
29 | obj-$(CONFIG_977_WATCHDOG) += wdt977.o | 29 | obj-$(CONFIG_977_WATCHDOG) += wdt977.o |
@@ -53,7 +53,9 @@ obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o | |||
53 | obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o | 53 | obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o |
54 | obj-$(CONFIG_SBC8360_WDT) += sbc8360.o | 54 | obj-$(CONFIG_SBC8360_WDT) += sbc8360.o |
55 | obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o | 55 | obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o |
56 | obj-$(CONFIG_SMSC37B787_WDT) += smsc37b787_wdt.o | ||
56 | obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o | 57 | obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o |
58 | obj-$(CONFIG_W83697HF_WDT) += w83697hf_wdt.o | ||
57 | obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o | 59 | obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o |
58 | obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o | 60 | obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o |
59 | obj-$(CONFIG_MACHZ_WDT) += machzwd.o | 61 | obj-$(CONFIG_MACHZ_WDT) += machzwd.o |
diff --git a/drivers/char/watchdog/alim7101_wdt.c b/drivers/char/watchdog/alim7101_wdt.c index 5948863b592b..bf25d0a55a99 100644 --- a/drivers/char/watchdog/alim7101_wdt.c +++ b/drivers/char/watchdog/alim7101_wdt.c | |||
@@ -77,7 +77,8 @@ static struct pci_dev *alim7101_pmu; | |||
77 | 77 | ||
78 | static int nowayout = WATCHDOG_NOWAYOUT; | 78 | static int nowayout = WATCHDOG_NOWAYOUT; |
79 | module_param(nowayout, int, 0); | 79 | module_param(nowayout, int, 0); |
80 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 80 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" |
81 | __stringify(CONFIG_WATCHDOG_NOWAYOUT) ")"); | ||
81 | 82 | ||
82 | /* | 83 | /* |
83 | * Whack the dog | 84 | * Whack the dog |
@@ -415,6 +416,16 @@ err_out: | |||
415 | module_init(alim7101_wdt_init); | 416 | module_init(alim7101_wdt_init); |
416 | module_exit(alim7101_wdt_unload); | 417 | module_exit(alim7101_wdt_unload); |
417 | 418 | ||
419 | static struct pci_device_id alim7101_pci_tbl[] __devinitdata = { | ||
420 | { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, | ||
421 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
422 | { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, | ||
423 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
424 | { } | ||
425 | }; | ||
426 | |||
427 | MODULE_DEVICE_TABLE(pci, alim7101_pci_tbl); | ||
428 | |||
418 | MODULE_AUTHOR("Steve Hill"); | 429 | MODULE_AUTHOR("Steve Hill"); |
419 | MODULE_DESCRIPTION("ALi M7101 PMU Computer Watchdog Timer driver"); | 430 | MODULE_DESCRIPTION("ALi M7101 PMU Computer Watchdog Timer driver"); |
420 | MODULE_LICENSE("GPL"); | 431 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/char/watchdog/at91_wdt.c b/drivers/char/watchdog/at91rm9200_wdt.c index 4e7a1145e78f..4e7a1145e78f 100644 --- a/drivers/char/watchdog/at91_wdt.c +++ b/drivers/char/watchdog/at91rm9200_wdt.c | |||
diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c index aaac94db0d8b..b6f29cb8bd39 100644 --- a/drivers/char/watchdog/iTCO_wdt.c +++ b/drivers/char/watchdog/iTCO_wdt.c | |||
@@ -35,6 +35,10 @@ | |||
35 | * 82801GDH (ICH7DH) : document number 307013-002, 307014-009, | 35 | * 82801GDH (ICH7DH) : document number 307013-002, 307014-009, |
36 | * 82801GBM (ICH7-M) : document number 307013-002, 307014-009, | 36 | * 82801GBM (ICH7-M) : document number 307013-002, 307014-009, |
37 | * 82801GHM (ICH7-M DH) : document number 307013-002, 307014-009, | 37 | * 82801GHM (ICH7-M DH) : document number 307013-002, 307014-009, |
38 | * 82801HB (ICH8) : document number 313056-002, 313057-004, | ||
39 | * 82801HR (ICH8R) : document number 313056-002, 313057-004, | ||
40 | * 82801HH (ICH8DH) : document number 313056-002, 313057-004, | ||
41 | * 82801HO (ICH8DO) : document number 313056-002, 313057-004, | ||
38 | * 6300ESB (6300ESB) : document number 300641-003 | 42 | * 6300ESB (6300ESB) : document number 300641-003 |
39 | */ | 43 | */ |
40 | 44 | ||
@@ -45,7 +49,7 @@ | |||
45 | /* Module and version information */ | 49 | /* Module and version information */ |
46 | #define DRV_NAME "iTCO_wdt" | 50 | #define DRV_NAME "iTCO_wdt" |
47 | #define DRV_VERSION "1.00" | 51 | #define DRV_VERSION "1.00" |
48 | #define DRV_RELDATE "30-Jul-2006" | 52 | #define DRV_RELDATE "08-Oct-2006" |
49 | #define PFX DRV_NAME ": " | 53 | #define PFX DRV_NAME ": " |
50 | 54 | ||
51 | /* Includes */ | 55 | /* Includes */ |
@@ -85,6 +89,9 @@ enum iTCO_chipsets { | |||
85 | TCO_ICH7, /* ICH7 & ICH7R */ | 89 | TCO_ICH7, /* ICH7 & ICH7R */ |
86 | TCO_ICH7M, /* ICH7-M */ | 90 | TCO_ICH7M, /* ICH7-M */ |
87 | TCO_ICH7MDH, /* ICH7-M DH */ | 91 | TCO_ICH7MDH, /* ICH7-M DH */ |
92 | TCO_ICH8, /* ICH8 & ICH8R */ | ||
93 | TCO_ICH8DH, /* ICH8DH */ | ||
94 | TCO_ICH8DO, /* ICH8DO */ | ||
88 | }; | 95 | }; |
89 | 96 | ||
90 | static struct { | 97 | static struct { |
@@ -108,6 +115,9 @@ static struct { | |||
108 | {"ICH7 or ICH7R", 2}, | 115 | {"ICH7 or ICH7R", 2}, |
109 | {"ICH7-M", 2}, | 116 | {"ICH7-M", 2}, |
110 | {"ICH7-M DH", 2}, | 117 | {"ICH7-M DH", 2}, |
118 | {"ICH8 or ICH8R", 2}, | ||
119 | {"ICH8DH", 2}, | ||
120 | {"ICH8DO", 2}, | ||
111 | {NULL,0} | 121 | {NULL,0} |
112 | }; | 122 | }; |
113 | 123 | ||
@@ -135,6 +145,9 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { | |||
135 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7 }, | 145 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7 }, |
136 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7M }, | 146 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7M }, |
137 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7MDH }, | 147 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7MDH }, |
148 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8 }, | ||
149 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DH }, | ||
150 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DO }, | ||
138 | { 0, }, /* End of list */ | 151 | { 0, }, /* End of list */ |
139 | }; | 152 | }; |
140 | MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl); | 153 | MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl); |
@@ -355,7 +368,8 @@ static int iTCO_wdt_get_timeleft (int *time_left) | |||
355 | spin_unlock(&iTCO_wdt_private.io_lock); | 368 | spin_unlock(&iTCO_wdt_private.io_lock); |
356 | 369 | ||
357 | *time_left = (val8 * 6) / 10; | 370 | *time_left = (val8 * 6) / 10; |
358 | } | 371 | } else |
372 | return -EINVAL; | ||
359 | return 0; | 373 | return 0; |
360 | } | 374 | } |
361 | 375 | ||
@@ -426,7 +440,6 @@ static int iTCO_wdt_ioctl (struct inode *inode, struct file *file, | |||
426 | { | 440 | { |
427 | int new_options, retval = -EINVAL; | 441 | int new_options, retval = -EINVAL; |
428 | int new_heartbeat; | 442 | int new_heartbeat; |
429 | int time_left; | ||
430 | void __user *argp = (void __user *)arg; | 443 | void __user *argp = (void __user *)arg; |
431 | int __user *p = argp; | 444 | int __user *p = argp; |
432 | static struct watchdog_info ident = { | 445 | static struct watchdog_info ident = { |
@@ -486,6 +499,8 @@ static int iTCO_wdt_ioctl (struct inode *inode, struct file *file, | |||
486 | 499 | ||
487 | case WDIOC_GETTIMELEFT: | 500 | case WDIOC_GETTIMELEFT: |
488 | { | 501 | { |
502 | int time_left; | ||
503 | |||
489 | if (iTCO_wdt_get_timeleft(&time_left)) | 504 | if (iTCO_wdt_get_timeleft(&time_left)) |
490 | return -EINVAL; | 505 | return -EINVAL; |
491 | 506 | ||
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c index 68b1ca976d53..18cb050c3862 100644 --- a/drivers/char/watchdog/s3c2410_wdt.c +++ b/drivers/char/watchdog/s3c2410_wdt.c | |||
@@ -380,18 +380,21 @@ static int s3c2410wdt_probe(struct platform_device *pdev) | |||
380 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 380 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
381 | if (res == NULL) { | 381 | if (res == NULL) { |
382 | printk(KERN_INFO PFX "failed to get irq resource\n"); | 382 | printk(KERN_INFO PFX "failed to get irq resource\n"); |
383 | iounmap(wdt_base); | ||
383 | return -ENOENT; | 384 | return -ENOENT; |
384 | } | 385 | } |
385 | 386 | ||
386 | ret = request_irq(res->start, s3c2410wdt_irq, 0, pdev->name, pdev); | 387 | ret = request_irq(res->start, s3c2410wdt_irq, 0, pdev->name, pdev); |
387 | if (ret != 0) { | 388 | if (ret != 0) { |
388 | printk(KERN_INFO PFX "failed to install irq (%d)\n", ret); | 389 | printk(KERN_INFO PFX "failed to install irq (%d)\n", ret); |
390 | iounmap(wdt_base); | ||
389 | return ret; | 391 | return ret; |
390 | } | 392 | } |
391 | 393 | ||
392 | wdt_clock = clk_get(&pdev->dev, "watchdog"); | 394 | wdt_clock = clk_get(&pdev->dev, "watchdog"); |
393 | if (wdt_clock == NULL) { | 395 | if (wdt_clock == NULL) { |
394 | printk(KERN_INFO PFX "failed to find watchdog clock source\n"); | 396 | printk(KERN_INFO PFX "failed to find watchdog clock source\n"); |
397 | iounmap(wdt_base); | ||
395 | return -ENOENT; | 398 | return -ENOENT; |
396 | } | 399 | } |
397 | 400 | ||
@@ -415,6 +418,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev) | |||
415 | if (ret) { | 418 | if (ret) { |
416 | printk (KERN_ERR PFX "cannot register miscdev on minor=%d (%d)\n", | 419 | printk (KERN_ERR PFX "cannot register miscdev on minor=%d (%d)\n", |
417 | WATCHDOG_MINOR, ret); | 420 | WATCHDOG_MINOR, ret); |
421 | iounmap(wdt_base); | ||
418 | return ret; | 422 | return ret; |
419 | } | 423 | } |
420 | 424 | ||
@@ -451,6 +455,7 @@ static int s3c2410wdt_remove(struct platform_device *dev) | |||
451 | wdt_clock = NULL; | 455 | wdt_clock = NULL; |
452 | } | 456 | } |
453 | 457 | ||
458 | iounmap(wdt_base); | ||
454 | misc_deregister(&s3c2410wdt_miscdev); | 459 | misc_deregister(&s3c2410wdt_miscdev); |
455 | return 0; | 460 | return 0; |
456 | } | 461 | } |
diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c index d8d0f28e0acf..e3239833e4b0 100644 --- a/drivers/char/watchdog/sc1200wdt.c +++ b/drivers/char/watchdog/sc1200wdt.c | |||
@@ -392,7 +392,7 @@ static int __init sc1200wdt_init(void) | |||
392 | if (io == -1) { | 392 | if (io == -1) { |
393 | printk(KERN_ERR PFX "io parameter must be specified\n"); | 393 | printk(KERN_ERR PFX "io parameter must be specified\n"); |
394 | ret = -EINVAL; | 394 | ret = -EINVAL; |
395 | goto out_clean; | 395 | goto out_pnp; |
396 | } | 396 | } |
397 | 397 | ||
398 | #if defined CONFIG_PNP | 398 | #if defined CONFIG_PNP |
@@ -405,7 +405,7 @@ static int __init sc1200wdt_init(void) | |||
405 | if (!request_region(io, io_len, SC1200_MODULE_NAME)) { | 405 | if (!request_region(io, io_len, SC1200_MODULE_NAME)) { |
406 | printk(KERN_ERR PFX "Unable to register IO port %#x\n", io); | 406 | printk(KERN_ERR PFX "Unable to register IO port %#x\n", io); |
407 | ret = -EBUSY; | 407 | ret = -EBUSY; |
408 | goto out_clean; | 408 | goto out_pnp; |
409 | } | 409 | } |
410 | 410 | ||
411 | ret = sc1200wdt_probe(); | 411 | ret = sc1200wdt_probe(); |
@@ -435,6 +435,11 @@ out_rbt: | |||
435 | out_io: | 435 | out_io: |
436 | release_region(io, io_len); | 436 | release_region(io, io_len); |
437 | 437 | ||
438 | out_pnp: | ||
439 | #if defined CONFIG_PNP | ||
440 | if (isapnp) | ||
441 | pnp_unregister_driver(&scl200wdt_pnp_driver); | ||
442 | #endif | ||
438 | goto out_clean; | 443 | goto out_clean; |
439 | } | 444 | } |
440 | 445 | ||
diff --git a/drivers/char/watchdog/smsc37b787_wdt.c b/drivers/char/watchdog/smsc37b787_wdt.c new file mode 100644 index 000000000000..9f56913b484f --- /dev/null +++ b/drivers/char/watchdog/smsc37b787_wdt.c | |||
@@ -0,0 +1,627 @@ | |||
1 | /* | ||
2 | * SMsC 37B787 Watchdog Timer driver for Linux 2.6.x.x | ||
3 | * | ||
4 | * Based on acquirewdt.c by Alan Cox <alan@redhat.com> | ||
5 | * and some other existing drivers | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * The authors do NOT admit liability nor provide warranty for | ||
13 | * any of this software. This material is provided "AS-IS" in | ||
14 | * the hope that it may be useful for others. | ||
15 | * | ||
16 | * (C) Copyright 2003-2006 Sven Anders <anders@anduras.de> | ||
17 | * | ||
18 | * History: | ||
19 | * 2003 - Created version 1.0 for Linux 2.4.x. | ||
20 | * 2006 - Ported to Linux 2.6, added nowayout and MAGICCLOSE | ||
21 | * features. Released version 1.1 | ||
22 | * | ||
23 | * Theory of operation: | ||
24 | * | ||
25 | * A Watchdog Timer (WDT) is a hardware circuit that can | ||
26 | * reset the computer system in case of a software fault. | ||
27 | * You probably knew that already. | ||
28 | * | ||
29 | * Usually a userspace daemon will notify the kernel WDT driver | ||
30 | * via the /dev/watchdog special device file that userspace is | ||
31 | * still alive, at regular intervals. When such a notification | ||
32 | * occurs, the driver will usually tell the hardware watchdog | ||
33 | * that everything is in order, and that the watchdog should wait | ||
34 | * for yet another little while to reset the system. | ||
35 | * If userspace fails (RAM error, kernel bug, whatever), the | ||
36 | * notifications cease to occur, and the hardware watchdog will | ||
37 | * reset the system (causing a reboot) after the timeout occurs. | ||
38 | * | ||
39 | * Create device with: | ||
40 | * mknod /dev/watchdog c 10 130 | ||
41 | * | ||
42 | * For an example userspace keep-alive daemon, see: | ||
43 | * Documentation/watchdog/watchdog.txt | ||
44 | */ | ||
45 | |||
46 | #include <linux/module.h> | ||
47 | #include <linux/moduleparam.h> | ||
48 | #include <linux/types.h> | ||
49 | #include <linux/miscdevice.h> | ||
50 | #include <linux/watchdog.h> | ||
51 | #include <linux/delay.h> | ||
52 | #include <linux/fs.h> | ||
53 | #include <linux/ioport.h> | ||
54 | #include <linux/notifier.h> | ||
55 | #include <linux/reboot.h> | ||
56 | #include <linux/init.h> | ||
57 | #include <linux/spinlock.h> | ||
58 | |||
59 | #include <asm/io.h> | ||
60 | #include <asm/uaccess.h> | ||
61 | #include <asm/system.h> | ||
62 | |||
63 | /* enable support for minutes as units? */ | ||
64 | /* (does not always work correctly, so disabled by default!) */ | ||
65 | #define SMSC_SUPPORT_MINUTES | ||
66 | #undef SMSC_SUPPORT_MINUTES | ||
67 | |||
68 | #define MAX_TIMEOUT 255 | ||
69 | |||
70 | #define UNIT_SECOND 0 | ||
71 | #define UNIT_MINUTE 1 | ||
72 | |||
73 | #define MODNAME "smsc37b787_wdt: " | ||
74 | #define VERSION "1.1" | ||
75 | |||
76 | #define IOPORT 0x3F0 | ||
77 | #define IOPORT_SIZE 2 | ||
78 | #define IODEV_NO 8 | ||
79 | |||
80 | static int unit = UNIT_SECOND; /* timer's unit */ | ||
81 | static int timeout = 60; /* timeout value: default is 60 "units" */ | ||
82 | static unsigned long timer_enabled = 0; /* is the timer enabled? */ | ||
83 | |||
84 | static char expect_close; /* is the close expected? */ | ||
85 | |||
86 | static spinlock_t io_lock; /* to guard the watchdog from io races */ | ||
87 | |||
88 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
89 | |||
90 | /* -- Low level function ----------------------------------------*/ | ||
91 | |||
92 | /* unlock the IO chip */ | ||
93 | |||
94 | static inline void open_io_config(void) | ||
95 | { | ||
96 | outb(0x55, IOPORT); | ||
97 | mdelay(1); | ||
98 | outb(0x55, IOPORT); | ||
99 | } | ||
100 | |||
101 | /* lock the IO chip */ | ||
102 | static inline void close_io_config(void) | ||
103 | { | ||
104 | outb(0xAA, IOPORT); | ||
105 | } | ||
106 | |||
107 | /* select the IO device */ | ||
108 | static inline void select_io_device(unsigned char devno) | ||
109 | { | ||
110 | outb(0x07, IOPORT); | ||
111 | outb(devno, IOPORT+1); | ||
112 | } | ||
113 | |||
114 | /* write to the control register */ | ||
115 | static inline void write_io_cr(unsigned char reg, unsigned char data) | ||
116 | { | ||
117 | outb(reg, IOPORT); | ||
118 | outb(data, IOPORT+1); | ||
119 | } | ||
120 | |||
121 | /* read from the control register */ | ||
122 | static inline char read_io_cr(unsigned char reg) | ||
123 | { | ||
124 | outb(reg, IOPORT); | ||
125 | return inb(IOPORT+1); | ||
126 | } | ||
127 | |||
128 | /* -- Medium level functions ------------------------------------*/ | ||
129 | |||
130 | static inline void gpio_bit12(unsigned char reg) | ||
131 | { | ||
132 | // -- General Purpose I/O Bit 1.2 -- | ||
133 | // Bit 0, In/Out: 0 = Output, 1 = Input | ||
134 | // Bit 1, Polarity: 0 = No Invert, 1 = Invert | ||
135 | // Bit 2, Group Enable Intr.: 0 = Disable, 1 = Enable | ||
136 | // Bit 3/4, Function select: 00 = GPI/O, 01 = WDT, 10 = P17, | ||
137 | // 11 = Either Edge Triggered Intr. 2 | ||
138 | // Bit 5/6 (Reserved) | ||
139 | // Bit 7, Output Type: 0 = Push Pull Bit, 1 = Open Drain | ||
140 | write_io_cr(0xE2, reg); | ||
141 | } | ||
142 | |||
143 | static inline void gpio_bit13(unsigned char reg) | ||
144 | { | ||
145 | // -- General Purpose I/O Bit 1.3 -- | ||
146 | // Bit 0, In/Out: 0 = Output, 1 = Input | ||
147 | // Bit 1, Polarity: 0 = No Invert, 1 = Invert | ||
148 | // Bit 2, Group Enable Intr.: 0 = Disable, 1 = Enable | ||
149 | // Bit 3, Function select: 0 = GPI/O, 1 = LED | ||
150 | // Bit 4-6 (Reserved) | ||
151 | // Bit 7, Output Type: 0 = Push Pull Bit, 1 = Open Drain | ||
152 | write_io_cr(0xE3, reg); | ||
153 | } | ||
154 | |||
155 | static inline void wdt_timer_units(unsigned char new_units) | ||
156 | { | ||
157 | // -- Watchdog timer units -- | ||
158 | // Bit 0-6 (Reserved) | ||
159 | // Bit 7, WDT Time-out Value Units Select | ||
160 | // (0 = Minutes, 1 = Seconds) | ||
161 | write_io_cr(0xF1, new_units); | ||
162 | } | ||
163 | |||
164 | static inline void wdt_timeout_value(unsigned char new_timeout) | ||
165 | { | ||
166 | // -- Watchdog Timer Time-out Value -- | ||
167 | // Bit 0-7 Binary coded units (0=Disabled, 1..255) | ||
168 | write_io_cr(0xF2, new_timeout); | ||
169 | } | ||
170 | |||
171 | static inline void wdt_timer_conf(unsigned char conf) | ||
172 | { | ||
173 | // -- Watchdog timer configuration -- | ||
174 | // Bit 0 Joystick enable: 0* = No Reset, 1 = Reset WDT upon Gameport I/O | ||
175 | // Bit 1 Keyboard enable: 0* = No Reset, 1 = Reset WDT upon KBD Intr. | ||
176 | // Bit 2 Mouse enable: 0* = No Reset, 1 = Reset WDT upon Mouse Intr. | ||
177 | // Bit 3 Reset the timer | ||
178 | // (Wrong in SMsC documentation? Given as: PowerLED Timout Enabled) | ||
179 | // Bit 4-7 WDT Interrupt Mapping: (0000* = Disabled, | ||
180 | // 0001=IRQ1, 0010=(Invalid), 0011=IRQ3 to 1111=IRQ15) | ||
181 | write_io_cr(0xF3, conf); | ||
182 | } | ||
183 | |||
184 | static inline void wdt_timer_ctrl(unsigned char reg) | ||
185 | { | ||
186 | // -- Watchdog timer control -- | ||
187 | // Bit 0 Status Bit: 0 = Timer counting, 1 = Timeout occured | ||
188 | // Bit 1 Power LED Toggle: 0 = Disable Toggle, 1 = Toggle at 1 Hz | ||
189 | // Bit 2 Force Timeout: 1 = Forces WD timeout event (self-cleaning) | ||
190 | // Bit 3 P20 Force Timeout enabled: | ||
191 | // 0 = P20 activity does not generate the WD timeout event | ||
192 | // 1 = P20 Allows rising edge of P20, from the keyboard | ||
193 | // controller, to force the WD timeout event. | ||
194 | // Bit 4 (Reserved) | ||
195 | // -- Soft power management -- | ||
196 | // Bit 5 Stop Counter: 1 = Stop software power down counter | ||
197 | // set via register 0xB8, (self-cleaning) | ||
198 | // (Upon read: 0 = Counter running, 1 = Counter stopped) | ||
199 | // Bit 6 Restart Counter: 1 = Restart software power down counter | ||
200 | // set via register 0xB8, (self-cleaning) | ||
201 | // Bit 7 SPOFF: 1 = Force software power down (self-cleaning) | ||
202 | |||
203 | write_io_cr(0xF4, reg); | ||
204 | } | ||
205 | |||
206 | /* -- Higher level functions ------------------------------------*/ | ||
207 | |||
208 | /* initialize watchdog */ | ||
209 | |||
210 | static void wb_smsc_wdt_initialize(void) | ||
211 | { | ||
212 | unsigned char old; | ||
213 | |||
214 | spin_lock(&io_lock); | ||
215 | open_io_config(); | ||
216 | select_io_device(IODEV_NO); | ||
217 | |||
218 | // enable the watchdog | ||
219 | gpio_bit13(0x08); // Select pin 80 = LED not GPIO | ||
220 | gpio_bit12(0x0A); // Set pin 79 = WDT not GPIO/Output/Polarity=Invert | ||
221 | |||
222 | // disable the timeout | ||
223 | wdt_timeout_value(0); | ||
224 | |||
225 | // reset control register | ||
226 | wdt_timer_ctrl(0x00); | ||
227 | |||
228 | // reset configuration register | ||
229 | wdt_timer_conf(0x00); | ||
230 | |||
231 | // read old (timer units) register | ||
232 | old = read_io_cr(0xF1) & 0x7F; | ||
233 | if (unit == UNIT_SECOND) old |= 0x80; // set to seconds | ||
234 | |||
235 | // set the watchdog timer units | ||
236 | wdt_timer_units(old); | ||
237 | |||
238 | close_io_config(); | ||
239 | spin_unlock(&io_lock); | ||
240 | } | ||
241 | |||
242 | /* shutdown the watchdog */ | ||
243 | |||
244 | static void wb_smsc_wdt_shutdown(void) | ||
245 | { | ||
246 | spin_lock(&io_lock); | ||
247 | open_io_config(); | ||
248 | select_io_device(IODEV_NO); | ||
249 | |||
250 | // disable the watchdog | ||
251 | gpio_bit13(0x09); | ||
252 | gpio_bit12(0x09); | ||
253 | |||
254 | // reset watchdog config register | ||
255 | wdt_timer_conf(0x00); | ||
256 | |||
257 | // reset watchdog control register | ||
258 | wdt_timer_ctrl(0x00); | ||
259 | |||
260 | // disable timeout | ||
261 | wdt_timeout_value(0x00); | ||
262 | |||
263 | close_io_config(); | ||
264 | spin_unlock(&io_lock); | ||
265 | } | ||
266 | |||
267 | /* set timeout => enable watchdog */ | ||
268 | |||
269 | static void wb_smsc_wdt_set_timeout(unsigned char new_timeout) | ||
270 | { | ||
271 | spin_lock(&io_lock); | ||
272 | open_io_config(); | ||
273 | select_io_device(IODEV_NO); | ||
274 | |||
275 | // set Power LED to blink, if we enable the timeout | ||
276 | wdt_timer_ctrl((new_timeout == 0) ? 0x00 : 0x02); | ||
277 | |||
278 | // set timeout value | ||
279 | wdt_timeout_value(new_timeout); | ||
280 | |||
281 | close_io_config(); | ||
282 | spin_unlock(&io_lock); | ||
283 | } | ||
284 | |||
285 | /* get timeout */ | ||
286 | |||
287 | static unsigned char wb_smsc_wdt_get_timeout(void) | ||
288 | { | ||
289 | unsigned char set_timeout; | ||
290 | |||
291 | spin_lock(&io_lock); | ||
292 | open_io_config(); | ||
293 | select_io_device(IODEV_NO); | ||
294 | set_timeout = read_io_cr(0xF2); | ||
295 | close_io_config(); | ||
296 | spin_unlock(&io_lock); | ||
297 | |||
298 | return set_timeout; | ||
299 | } | ||
300 | |||
301 | /* disable watchdog */ | ||
302 | |||
303 | static void wb_smsc_wdt_disable(void) | ||
304 | { | ||
305 | // set the timeout to 0 to disable the watchdog | ||
306 | wb_smsc_wdt_set_timeout(0); | ||
307 | } | ||
308 | |||
309 | /* enable watchdog by setting the current timeout */ | ||
310 | |||
311 | static void wb_smsc_wdt_enable(void) | ||
312 | { | ||
313 | // set the current timeout... | ||
314 | wb_smsc_wdt_set_timeout(timeout); | ||
315 | } | ||
316 | |||
317 | /* reset the timer */ | ||
318 | |||
319 | static void wb_smsc_wdt_reset_timer(void) | ||
320 | { | ||
321 | spin_lock(&io_lock); | ||
322 | open_io_config(); | ||
323 | select_io_device(IODEV_NO); | ||
324 | |||
325 | // reset the timer | ||
326 | wdt_timeout_value(timeout); | ||
327 | wdt_timer_conf(0x08); | ||
328 | |||
329 | close_io_config(); | ||
330 | spin_unlock(&io_lock); | ||
331 | } | ||
332 | |||
333 | /* return, if the watchdog is enabled (timeout is set...) */ | ||
334 | |||
335 | static int wb_smsc_wdt_status(void) | ||
336 | { | ||
337 | return (wb_smsc_wdt_get_timeout() == 0) ? 0 : WDIOF_KEEPALIVEPING; | ||
338 | } | ||
339 | |||
340 | |||
341 | /* -- File operations -------------------------------------------*/ | ||
342 | |||
343 | /* open => enable watchdog and set initial timeout */ | ||
344 | |||
345 | static int wb_smsc_wdt_open(struct inode *inode, struct file *file) | ||
346 | { | ||
347 | /* /dev/watchdog can only be opened once */ | ||
348 | |||
349 | if (test_and_set_bit(0, &timer_enabled)) | ||
350 | return -EBUSY; | ||
351 | |||
352 | if (nowayout) | ||
353 | __module_get(THIS_MODULE); | ||
354 | |||
355 | /* Reload and activate timer */ | ||
356 | wb_smsc_wdt_enable(); | ||
357 | |||
358 | printk(KERN_INFO MODNAME "Watchdog enabled. Timeout set to %d %s.\n", timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)"); | ||
359 | |||
360 | return nonseekable_open(inode, file); | ||
361 | } | ||
362 | |||
363 | /* close => shut off the timer */ | ||
364 | |||
365 | static int wb_smsc_wdt_release(struct inode *inode, struct file *file) | ||
366 | { | ||
367 | /* Shut off the timer. */ | ||
368 | |||
369 | if (expect_close == 42) { | ||
370 | wb_smsc_wdt_disable(); | ||
371 | printk(KERN_INFO MODNAME "Watchdog disabled, sleeping again...\n"); | ||
372 | } else { | ||
373 | printk(KERN_CRIT MODNAME "Unexpected close, not stopping watchdog!\n"); | ||
374 | wb_smsc_wdt_reset_timer(); | ||
375 | } | ||
376 | |||
377 | clear_bit(0, &timer_enabled); | ||
378 | expect_close = 0; | ||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | /* write => update the timer to keep the machine alive */ | ||
383 | |||
384 | static ssize_t wb_smsc_wdt_write(struct file *file, const char __user *data, | ||
385 | size_t len, loff_t *ppos) | ||
386 | { | ||
387 | /* See if we got the magic character 'V' and reload the timer */ | ||
388 | if (len) { | ||
389 | if (!nowayout) { | ||
390 | size_t i; | ||
391 | |||
392 | /* reset expect flag */ | ||
393 | expect_close = 0; | ||
394 | |||
395 | /* scan to see whether or not we got the magic character */ | ||
396 | for (i = 0; i != len; i++) { | ||
397 | char c; | ||
398 | if (get_user(c, data+i)) | ||
399 | return -EFAULT; | ||
400 | if (c == 'V') | ||
401 | expect_close = 42; | ||
402 | } | ||
403 | } | ||
404 | |||
405 | /* someone wrote to us, we should reload the timer */ | ||
406 | wb_smsc_wdt_reset_timer(); | ||
407 | } | ||
408 | return len; | ||
409 | } | ||
410 | |||
411 | /* ioctl => control interface */ | ||
412 | |||
413 | static int wb_smsc_wdt_ioctl(struct inode *inode, struct file *file, | ||
414 | unsigned int cmd, unsigned long arg) | ||
415 | { | ||
416 | int new_timeout; | ||
417 | |||
418 | union { | ||
419 | struct watchdog_info __user *ident; | ||
420 | int __user *i; | ||
421 | } uarg; | ||
422 | |||
423 | static struct watchdog_info ident = { | ||
424 | .options = WDIOF_KEEPALIVEPING | | ||
425 | WDIOF_SETTIMEOUT | | ||
426 | WDIOF_MAGICCLOSE, | ||
427 | .firmware_version = 0, | ||
428 | .identity = "SMsC 37B787 Watchdog" | ||
429 | }; | ||
430 | |||
431 | uarg.i = (int __user *)arg; | ||
432 | |||
433 | switch (cmd) { | ||
434 | default: | ||
435 | return -ENOTTY; | ||
436 | |||
437 | case WDIOC_GETSUPPORT: | ||
438 | return copy_to_user(uarg.ident, &ident, | ||
439 | sizeof(ident)) ? -EFAULT : 0; | ||
440 | |||
441 | case WDIOC_GETSTATUS: | ||
442 | return put_user(wb_smsc_wdt_status(), uarg.i); | ||
443 | |||
444 | case WDIOC_GETBOOTSTATUS: | ||
445 | return put_user(0, uarg.i); | ||
446 | |||
447 | case WDIOC_KEEPALIVE: | ||
448 | wb_smsc_wdt_reset_timer(); | ||
449 | return 0; | ||
450 | |||
451 | case WDIOC_SETTIMEOUT: | ||
452 | if (get_user(new_timeout, uarg.i)) | ||
453 | return -EFAULT; | ||
454 | |||
455 | // the API states this is given in secs | ||
456 | if (unit == UNIT_MINUTE) | ||
457 | new_timeout /= 60; | ||
458 | |||
459 | if (new_timeout < 0 || new_timeout > MAX_TIMEOUT) | ||
460 | return -EINVAL; | ||
461 | |||
462 | timeout = new_timeout; | ||
463 | wb_smsc_wdt_set_timeout(timeout); | ||
464 | |||
465 | // fall through and return the new timeout... | ||
466 | |||
467 | case WDIOC_GETTIMEOUT: | ||
468 | |||
469 | new_timeout = timeout; | ||
470 | |||
471 | if (unit == UNIT_MINUTE) | ||
472 | new_timeout *= 60; | ||
473 | |||
474 | return put_user(new_timeout, uarg.i); | ||
475 | |||
476 | case WDIOC_SETOPTIONS: | ||
477 | { | ||
478 | int options, retval = -EINVAL; | ||
479 | |||
480 | if (get_user(options, uarg.i)) | ||
481 | return -EFAULT; | ||
482 | |||
483 | if (options & WDIOS_DISABLECARD) { | ||
484 | wb_smsc_wdt_disable(); | ||
485 | retval = 0; | ||
486 | } | ||
487 | |||
488 | if (options & WDIOS_ENABLECARD) { | ||
489 | wb_smsc_wdt_enable(); | ||
490 | retval = 0; | ||
491 | } | ||
492 | |||
493 | return retval; | ||
494 | } | ||
495 | } | ||
496 | } | ||
497 | |||
498 | /* -- Notifier funtions -----------------------------------------*/ | ||
499 | |||
500 | static int wb_smsc_wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) | ||
501 | { | ||
502 | if (code == SYS_DOWN || code == SYS_HALT) | ||
503 | { | ||
504 | // set timeout to 0, to avoid possible race-condition | ||
505 | timeout = 0; | ||
506 | wb_smsc_wdt_disable(); | ||
507 | } | ||
508 | return NOTIFY_DONE; | ||
509 | } | ||
510 | |||
511 | /* -- Module's structures ---------------------------------------*/ | ||
512 | |||
513 | static struct file_operations wb_smsc_wdt_fops = | ||
514 | { | ||
515 | .owner = THIS_MODULE, | ||
516 | .llseek = no_llseek, | ||
517 | .write = wb_smsc_wdt_write, | ||
518 | .ioctl = wb_smsc_wdt_ioctl, | ||
519 | .open = wb_smsc_wdt_open, | ||
520 | .release = wb_smsc_wdt_release, | ||
521 | }; | ||
522 | |||
523 | static struct notifier_block wb_smsc_wdt_notifier = | ||
524 | { | ||
525 | .notifier_call = wb_smsc_wdt_notify_sys, | ||
526 | }; | ||
527 | |||
528 | static struct miscdevice wb_smsc_wdt_miscdev = | ||
529 | { | ||
530 | .minor = WATCHDOG_MINOR, | ||
531 | .name = "watchdog", | ||
532 | .fops = &wb_smsc_wdt_fops, | ||
533 | }; | ||
534 | |||
535 | /* -- Module init functions -------------------------------------*/ | ||
536 | |||
537 | /* module's "constructor" */ | ||
538 | |||
539 | static int __init wb_smsc_wdt_init(void) | ||
540 | { | ||
541 | int ret; | ||
542 | |||
543 | spin_lock_init(&io_lock); | ||
544 | |||
545 | printk("SMsC 37B787 watchdog component driver " VERSION " initialising...\n"); | ||
546 | |||
547 | if (!request_region(IOPORT, IOPORT_SIZE, "SMsC 37B787 watchdog")) { | ||
548 | printk(KERN_ERR MODNAME "Unable to register IO port %#x\n", IOPORT); | ||
549 | ret = -EBUSY; | ||
550 | goto out_pnp; | ||
551 | } | ||
552 | |||
553 | // set new maximum, if it's too big | ||
554 | if (timeout > MAX_TIMEOUT) | ||
555 | timeout = MAX_TIMEOUT; | ||
556 | |||
557 | // init the watchdog timer | ||
558 | wb_smsc_wdt_initialize(); | ||
559 | |||
560 | ret = register_reboot_notifier(&wb_smsc_wdt_notifier); | ||
561 | if (ret) { | ||
562 | printk(KERN_ERR MODNAME "Unable to register reboot notifier err = %d\n", ret); | ||
563 | goto out_io; | ||
564 | } | ||
565 | |||
566 | ret = misc_register(&wb_smsc_wdt_miscdev); | ||
567 | if (ret) { | ||
568 | printk(KERN_ERR MODNAME "Unable to register miscdev on minor %d\n", WATCHDOG_MINOR); | ||
569 | goto out_rbt; | ||
570 | } | ||
571 | |||
572 | // output info | ||
573 | printk(KERN_INFO MODNAME "Timeout set to %d %s.\n", timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)"); | ||
574 | printk(KERN_INFO MODNAME "Watchdog initialized and sleeping (nowayout=%d)...\n", nowayout); | ||
575 | |||
576 | // ret = 0 | ||
577 | |||
578 | out_clean: | ||
579 | return ret; | ||
580 | |||
581 | out_rbt: | ||
582 | unregister_reboot_notifier(&wb_smsc_wdt_notifier); | ||
583 | |||
584 | out_io: | ||
585 | release_region(IOPORT, IOPORT_SIZE); | ||
586 | |||
587 | out_pnp: | ||
588 | goto out_clean; | ||
589 | } | ||
590 | |||
591 | /* module's "destructor" */ | ||
592 | |||
593 | static void __exit wb_smsc_wdt_exit(void) | ||
594 | { | ||
595 | /* Stop the timer before we leave */ | ||
596 | if (!nowayout) | ||
597 | { | ||
598 | wb_smsc_wdt_shutdown(); | ||
599 | printk(KERN_INFO MODNAME "Watchdog disabled.\n"); | ||
600 | } | ||
601 | |||
602 | misc_deregister(&wb_smsc_wdt_miscdev); | ||
603 | unregister_reboot_notifier(&wb_smsc_wdt_notifier); | ||
604 | release_region(IOPORT, IOPORT_SIZE); | ||
605 | |||
606 | printk("SMsC 37B787 watchdog component driver removed.\n"); | ||
607 | } | ||
608 | |||
609 | module_init(wb_smsc_wdt_init); | ||
610 | module_exit(wb_smsc_wdt_exit); | ||
611 | |||
612 | MODULE_AUTHOR("Sven Anders <anders@anduras.de>"); | ||
613 | MODULE_DESCRIPTION("Driver for SMsC 37B787 watchdog component (Version " VERSION ")"); | ||
614 | MODULE_LICENSE("GPL"); | ||
615 | |||
616 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
617 | |||
618 | #ifdef SMSC_SUPPORT_MINUTES | ||
619 | module_param(unit, int, 0); | ||
620 | MODULE_PARM_DESC(unit, "set unit to use, 0=seconds or 1=minutes, default is 0"); | ||
621 | #endif | ||
622 | |||
623 | module_param(timeout, int, 0); | ||
624 | MODULE_PARM_DESC(timeout, "range is 1-255 units, default is 60"); | ||
625 | |||
626 | module_param(nowayout, int, 0); | ||
627 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | ||
diff --git a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c index b4adc527e687..07d4bff27226 100644 --- a/drivers/char/watchdog/w83627hf_wdt.c +++ b/drivers/char/watchdog/w83627hf_wdt.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/notifier.h> | 33 | #include <linux/notifier.h> |
34 | #include <linux/reboot.h> | 34 | #include <linux/reboot.h> |
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/spinlock.h> | ||
36 | 37 | ||
37 | #include <asm/io.h> | 38 | #include <asm/io.h> |
38 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
@@ -44,6 +45,7 @@ | |||
44 | 45 | ||
45 | static unsigned long wdt_is_open; | 46 | static unsigned long wdt_is_open; |
46 | static char expect_close; | 47 | static char expect_close; |
48 | static spinlock_t io_lock; | ||
47 | 49 | ||
48 | /* You must set this - there is no sane way to probe for this board. */ | 50 | /* You must set this - there is no sane way to probe for this board. */ |
49 | static int wdt_io = 0x2E; | 51 | static int wdt_io = 0x2E; |
@@ -110,12 +112,16 @@ w83627hf_init(void) | |||
110 | static void | 112 | static void |
111 | wdt_ctrl(int timeout) | 113 | wdt_ctrl(int timeout) |
112 | { | 114 | { |
115 | spin_lock(&io_lock); | ||
116 | |||
113 | w83627hf_select_wd_register(); | 117 | w83627hf_select_wd_register(); |
114 | 118 | ||
115 | outb_p(0xF6, WDT_EFER); /* Select CRF6 */ | 119 | outb_p(0xF6, WDT_EFER); /* Select CRF6 */ |
116 | outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF6 */ | 120 | outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF6 */ |
117 | 121 | ||
118 | w83627hf_unselect_wd_register(); | 122 | w83627hf_unselect_wd_register(); |
123 | |||
124 | spin_unlock(&io_lock); | ||
119 | } | 125 | } |
120 | 126 | ||
121 | static int | 127 | static int |
@@ -303,6 +309,8 @@ wdt_init(void) | |||
303 | { | 309 | { |
304 | int ret; | 310 | int ret; |
305 | 311 | ||
312 | spin_lock_init(&io_lock); | ||
313 | |||
306 | printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF Super I/O chip initialising.\n"); | 314 | printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF Super I/O chip initialising.\n"); |
307 | 315 | ||
308 | if (wdt_set_heartbeat(timeout)) { | 316 | if (wdt_set_heartbeat(timeout)) { |
diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c new file mode 100644 index 000000000000..7768b55487c8 --- /dev/null +++ b/drivers/char/watchdog/w83697hf_wdt.c | |||
@@ -0,0 +1,450 @@ | |||
1 | /* | ||
2 | * w83697hf/hg WDT driver | ||
3 | * | ||
4 | * (c) Copyright 2006 Samuel Tardieu <sam@rfc1149.net> | ||
5 | * (c) Copyright 2006 Marcus Junker <junker@anduras.de> | ||
6 | * | ||
7 | * Based on w83627hf_wdt.c which is based on advantechwdt.c | ||
8 | * which is based on wdt.c. | ||
9 | * Original copyright messages: | ||
10 | * | ||
11 | * (c) Copyright 2003 Pádraig Brady <P@draigBrady.com> | ||
12 | * | ||
13 | * (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl> | ||
14 | * | ||
15 | * (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved. | ||
16 | * http://www.redhat.com | ||
17 | * | ||
18 | * This program is free software; you can redistribute it and/or | ||
19 | * modify it under the terms of the GNU General Public License | ||
20 | * as published by the Free Software Foundation; either version | ||
21 | * 2 of the License, or (at your option) any later version. | ||
22 | * | ||
23 | * Neither Marcus Junker nor ANDURAS AG admit liability nor provide | ||
24 | * warranty for any of this software. This material is provided | ||
25 | * "AS-IS" and at no charge. | ||
26 | */ | ||
27 | |||
28 | #include <linux/module.h> | ||
29 | #include <linux/moduleparam.h> | ||
30 | #include <linux/types.h> | ||
31 | #include <linux/miscdevice.h> | ||
32 | #include <linux/watchdog.h> | ||
33 | #include <linux/fs.h> | ||
34 | #include <linux/ioport.h> | ||
35 | #include <linux/notifier.h> | ||
36 | #include <linux/reboot.h> | ||
37 | #include <linux/init.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | |||
40 | #include <asm/io.h> | ||
41 | #include <asm/uaccess.h> | ||
42 | #include <asm/system.h> | ||
43 | |||
44 | #define WATCHDOG_NAME "w83697hf/hg WDT" | ||
45 | #define PFX WATCHDOG_NAME ": " | ||
46 | #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ | ||
47 | |||
48 | static unsigned long wdt_is_open; | ||
49 | static char expect_close; | ||
50 | static spinlock_t io_lock; | ||
51 | |||
52 | /* You must set this - there is no sane way to probe for this board. */ | ||
53 | static int wdt_io = 0x2e; | ||
54 | module_param(wdt_io, int, 0); | ||
55 | MODULE_PARM_DESC(wdt_io, "w83697hf/hg WDT io port (default 0x2e, 0 = autodetect)"); | ||
56 | |||
57 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ | ||
58 | module_param(timeout, int, 0); | ||
59 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); | ||
60 | |||
61 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
62 | module_param(nowayout, int, 0); | ||
63 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | ||
64 | |||
65 | /* | ||
66 | * Kernel methods. | ||
67 | */ | ||
68 | |||
69 | #define W83697HF_EFER (wdt_io+0) /* Extended Function Enable Register */ | ||
70 | #define W83697HF_EFIR (wdt_io+0) /* Extended Function Index Register (same as EFER) */ | ||
71 | #define W83697HF_EFDR (wdt_io+1) /* Extended Function Data Register */ | ||
72 | |||
73 | static inline void | ||
74 | w83697hf_unlock(void) | ||
75 | { | ||
76 | outb_p(0x87, W83697HF_EFER); /* Enter extended function mode */ | ||
77 | outb_p(0x87, W83697HF_EFER); /* Again according to manual */ | ||
78 | } | ||
79 | |||
80 | static inline void | ||
81 | w83697hf_lock(void) | ||
82 | { | ||
83 | outb_p(0xAA, W83697HF_EFER); /* Leave extended function mode */ | ||
84 | } | ||
85 | |||
86 | /* | ||
87 | * The three functions w83697hf_get_reg(), w83697hf_set_reg() and | ||
88 | * w83697hf_write_timeout() must be called with the device unlocked. | ||
89 | */ | ||
90 | |||
91 | static unsigned char | ||
92 | w83697hf_get_reg(unsigned char reg) | ||
93 | { | ||
94 | outb_p(reg, W83697HF_EFIR); | ||
95 | return inb_p(W83697HF_EFDR); | ||
96 | } | ||
97 | |||
98 | static void | ||
99 | w83697hf_set_reg(unsigned char reg, unsigned char data) | ||
100 | { | ||
101 | outb_p(reg, W83697HF_EFIR); | ||
102 | outb_p(data, W83697HF_EFDR); | ||
103 | } | ||
104 | |||
105 | static void | ||
106 | w83697hf_write_timeout(int timeout) | ||
107 | { | ||
108 | w83697hf_set_reg(0xF4, timeout); /* Write Timeout counter to CRF4 */ | ||
109 | } | ||
110 | |||
111 | static void | ||
112 | w83697hf_select_wdt(void) | ||
113 | { | ||
114 | w83697hf_unlock(); | ||
115 | w83697hf_set_reg(0x07, 0x08); /* Switch to logic device 8 (GPIO2) */ | ||
116 | } | ||
117 | |||
118 | static inline void | ||
119 | w83697hf_deselect_wdt(void) | ||
120 | { | ||
121 | w83697hf_lock(); | ||
122 | } | ||
123 | |||
124 | static void | ||
125 | w83697hf_init(void) | ||
126 | { | ||
127 | unsigned char bbuf; | ||
128 | |||
129 | w83697hf_select_wdt(); | ||
130 | |||
131 | bbuf = w83697hf_get_reg(0x29); | ||
132 | bbuf &= ~0x60; | ||
133 | bbuf |= 0x20; | ||
134 | w83697hf_set_reg(0x29, bbuf); /* Set pin 119 to WDTO# mode (= CR29, WDT0) */ | ||
135 | |||
136 | bbuf = w83697hf_get_reg(0xF3); | ||
137 | bbuf &= ~0x04; | ||
138 | w83697hf_set_reg(0xF3, bbuf); /* Count mode is seconds */ | ||
139 | |||
140 | w83697hf_deselect_wdt(); | ||
141 | } | ||
142 | |||
143 | static int | ||
144 | wdt_ping(void) | ||
145 | { | ||
146 | spin_lock(&io_lock); | ||
147 | w83697hf_select_wdt(); | ||
148 | |||
149 | w83697hf_write_timeout(timeout); | ||
150 | |||
151 | w83697hf_deselect_wdt(); | ||
152 | spin_unlock(&io_lock); | ||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static int | ||
157 | wdt_enable(void) | ||
158 | { | ||
159 | spin_lock(&io_lock); | ||
160 | w83697hf_select_wdt(); | ||
161 | |||
162 | w83697hf_write_timeout(timeout); | ||
163 | w83697hf_set_reg(0x30, 1); /* Enable timer */ | ||
164 | |||
165 | w83697hf_deselect_wdt(); | ||
166 | spin_unlock(&io_lock); | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | static int | ||
171 | wdt_disable(void) | ||
172 | { | ||
173 | spin_lock(&io_lock); | ||
174 | w83697hf_select_wdt(); | ||
175 | |||
176 | w83697hf_set_reg(0x30, 0); /* Disable timer */ | ||
177 | w83697hf_write_timeout(0); | ||
178 | |||
179 | w83697hf_deselect_wdt(); | ||
180 | spin_unlock(&io_lock); | ||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int | ||
185 | wdt_set_heartbeat(int t) | ||
186 | { | ||
187 | if ((t < 1) || (t > 255)) | ||
188 | return -EINVAL; | ||
189 | |||
190 | timeout = t; | ||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static ssize_t | ||
195 | wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | ||
196 | { | ||
197 | if (count) { | ||
198 | if (!nowayout) { | ||
199 | size_t i; | ||
200 | |||
201 | expect_close = 0; | ||
202 | |||
203 | for (i = 0; i != count; i++) { | ||
204 | char c; | ||
205 | if (get_user(c, buf+i)) | ||
206 | return -EFAULT; | ||
207 | if (c == 'V') | ||
208 | expect_close = 42; | ||
209 | } | ||
210 | } | ||
211 | wdt_ping(); | ||
212 | } | ||
213 | return count; | ||
214 | } | ||
215 | |||
216 | static int | ||
217 | wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
218 | unsigned long arg) | ||
219 | { | ||
220 | void __user *argp = (void __user *)arg; | ||
221 | int __user *p = argp; | ||
222 | int new_timeout; | ||
223 | static struct watchdog_info ident = { | ||
224 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, | ||
225 | .firmware_version = 1, | ||
226 | .identity = "W83697HF WDT", | ||
227 | }; | ||
228 | |||
229 | switch (cmd) { | ||
230 | case WDIOC_GETSUPPORT: | ||
231 | if (copy_to_user(argp, &ident, sizeof(ident))) | ||
232 | return -EFAULT; | ||
233 | break; | ||
234 | |||
235 | case WDIOC_GETSTATUS: | ||
236 | case WDIOC_GETBOOTSTATUS: | ||
237 | return put_user(0, p); | ||
238 | |||
239 | case WDIOC_KEEPALIVE: | ||
240 | wdt_ping(); | ||
241 | break; | ||
242 | |||
243 | case WDIOC_SETTIMEOUT: | ||
244 | if (get_user(new_timeout, p)) | ||
245 | return -EFAULT; | ||
246 | if (wdt_set_heartbeat(new_timeout)) | ||
247 | return -EINVAL; | ||
248 | wdt_ping(); | ||
249 | /* Fall */ | ||
250 | |||
251 | case WDIOC_GETTIMEOUT: | ||
252 | return put_user(timeout, p); | ||
253 | |||
254 | case WDIOC_SETOPTIONS: | ||
255 | { | ||
256 | int options, retval = -EINVAL; | ||
257 | |||
258 | if (get_user(options, p)) | ||
259 | return -EFAULT; | ||
260 | |||
261 | if (options & WDIOS_DISABLECARD) { | ||
262 | wdt_disable(); | ||
263 | retval = 0; | ||
264 | } | ||
265 | |||
266 | if (options & WDIOS_ENABLECARD) { | ||
267 | wdt_enable(); | ||
268 | retval = 0; | ||
269 | } | ||
270 | |||
271 | return retval; | ||
272 | } | ||
273 | |||
274 | default: | ||
275 | return -ENOTTY; | ||
276 | } | ||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | static int | ||
281 | wdt_open(struct inode *inode, struct file *file) | ||
282 | { | ||
283 | if (test_and_set_bit(0, &wdt_is_open)) | ||
284 | return -EBUSY; | ||
285 | /* | ||
286 | * Activate | ||
287 | */ | ||
288 | |||
289 | wdt_enable(); | ||
290 | return nonseekable_open(inode, file); | ||
291 | } | ||
292 | |||
293 | static int | ||
294 | wdt_close(struct inode *inode, struct file *file) | ||
295 | { | ||
296 | if (expect_close == 42) { | ||
297 | wdt_disable(); | ||
298 | } else { | ||
299 | printk (KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | ||
300 | wdt_ping(); | ||
301 | } | ||
302 | expect_close = 0; | ||
303 | clear_bit(0, &wdt_is_open); | ||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | /* | ||
308 | * Notifier for system down | ||
309 | */ | ||
310 | |||
311 | static int | ||
312 | wdt_notify_sys(struct notifier_block *this, unsigned long code, | ||
313 | void *unused) | ||
314 | { | ||
315 | if (code == SYS_DOWN || code == SYS_HALT) { | ||
316 | /* Turn the WDT off */ | ||
317 | wdt_disable(); | ||
318 | } | ||
319 | return NOTIFY_DONE; | ||
320 | } | ||
321 | |||
322 | /* | ||
323 | * Kernel Interfaces | ||
324 | */ | ||
325 | |||
326 | static struct file_operations wdt_fops = { | ||
327 | .owner = THIS_MODULE, | ||
328 | .llseek = no_llseek, | ||
329 | .write = wdt_write, | ||
330 | .ioctl = wdt_ioctl, | ||
331 | .open = wdt_open, | ||
332 | .release = wdt_close, | ||
333 | }; | ||
334 | |||
335 | static struct miscdevice wdt_miscdev = { | ||
336 | .minor = WATCHDOG_MINOR, | ||
337 | .name = "watchdog", | ||
338 | .fops = &wdt_fops, | ||
339 | }; | ||
340 | |||
341 | /* | ||
342 | * The WDT needs to learn about soft shutdowns in order to | ||
343 | * turn the timebomb registers off. | ||
344 | */ | ||
345 | |||
346 | static struct notifier_block wdt_notifier = { | ||
347 | .notifier_call = wdt_notify_sys, | ||
348 | }; | ||
349 | |||
350 | static int | ||
351 | w83697hf_check_wdt(void) | ||
352 | { | ||
353 | if (!request_region(wdt_io, 2, WATCHDOG_NAME)) { | ||
354 | printk (KERN_ERR PFX "I/O address 0x%x already in use\n", wdt_io); | ||
355 | return -EIO; | ||
356 | } | ||
357 | |||
358 | printk (KERN_DEBUG PFX "Looking for watchdog at address 0x%x\n", wdt_io); | ||
359 | w83697hf_unlock(); | ||
360 | if (w83697hf_get_reg(0x20) == 0x60) { | ||
361 | printk (KERN_INFO PFX "watchdog found at address 0x%x\n", wdt_io); | ||
362 | w83697hf_lock(); | ||
363 | return 0; | ||
364 | } | ||
365 | w83697hf_lock(); /* Reprotect in case it was a compatible device */ | ||
366 | |||
367 | printk (KERN_INFO PFX "watchdog not found at address 0x%x\n", wdt_io); | ||
368 | release_region(wdt_io, 2); | ||
369 | return -EIO; | ||
370 | } | ||
371 | |||
372 | static int w83697hf_ioports[] = { 0x2e, 0x4e, 0x00 }; | ||
373 | |||
374 | static int __init | ||
375 | wdt_init(void) | ||
376 | { | ||
377 | int ret, i, found = 0; | ||
378 | |||
379 | spin_lock_init(&io_lock); | ||
380 | |||
381 | printk (KERN_INFO PFX "WDT driver for W83697HF/HG initializing\n"); | ||
382 | |||
383 | if (wdt_io == 0) { | ||
384 | /* we will autodetect the W83697HF/HG watchdog */ | ||
385 | for (i = 0; ((!found) && (w83697hf_ioports[i] != 0)); i++) { | ||
386 | wdt_io = w83697hf_ioports[i]; | ||
387 | if (!w83697hf_check_wdt()) | ||
388 | found++; | ||
389 | } | ||
390 | } else { | ||
391 | if (!w83697hf_check_wdt()) | ||
392 | found++; | ||
393 | } | ||
394 | |||
395 | if (!found) { | ||
396 | printk (KERN_ERR PFX "No W83697HF/HG could be found\n"); | ||
397 | ret = -EIO; | ||
398 | goto out; | ||
399 | } | ||
400 | |||
401 | w83697hf_init(); | ||
402 | wdt_disable(); /* Disable watchdog until first use */ | ||
403 | |||
404 | if (wdt_set_heartbeat(timeout)) { | ||
405 | wdt_set_heartbeat(WATCHDOG_TIMEOUT); | ||
406 | printk (KERN_INFO PFX "timeout value must be 1<=timeout<=255, using %d\n", | ||
407 | WATCHDOG_TIMEOUT); | ||
408 | } | ||
409 | |||
410 | ret = register_reboot_notifier(&wdt_notifier); | ||
411 | if (ret != 0) { | ||
412 | printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | ||
413 | ret); | ||
414 | goto unreg_regions; | ||
415 | } | ||
416 | |||
417 | ret = misc_register(&wdt_miscdev); | ||
418 | if (ret != 0) { | ||
419 | printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | ||
420 | WATCHDOG_MINOR, ret); | ||
421 | goto unreg_reboot; | ||
422 | } | ||
423 | |||
424 | printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", | ||
425 | timeout, nowayout); | ||
426 | |||
427 | out: | ||
428 | return ret; | ||
429 | unreg_reboot: | ||
430 | unregister_reboot_notifier(&wdt_notifier); | ||
431 | unreg_regions: | ||
432 | release_region(wdt_io, 2); | ||
433 | goto out; | ||
434 | } | ||
435 | |||
436 | static void __exit | ||
437 | wdt_exit(void) | ||
438 | { | ||
439 | misc_deregister(&wdt_miscdev); | ||
440 | unregister_reboot_notifier(&wdt_notifier); | ||
441 | release_region(wdt_io, 2); | ||
442 | } | ||
443 | |||
444 | module_init(wdt_init); | ||
445 | module_exit(wdt_exit); | ||
446 | |||
447 | MODULE_LICENSE("GPL"); | ||
448 | MODULE_AUTHOR("Marcus Junker <junker@anduras.de>, Samuel Tardieu <sam@rfc1149.net>"); | ||
449 | MODULE_DESCRIPTION("w83697hf/hg WDT driver"); | ||
450 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||