diff options
Diffstat (limited to 'drivers')
27 files changed, 645 insertions, 554 deletions
diff --git a/drivers/char/efirtc.c b/drivers/char/efirtc.c index 67fbd7aab5db..34d15d548236 100644 --- a/drivers/char/efirtc.c +++ b/drivers/char/efirtc.c | |||
| @@ -37,7 +37,6 @@ | |||
| 37 | #include <linux/rtc.h> | 37 | #include <linux/rtc.h> |
| 38 | #include <linux/proc_fs.h> | 38 | #include <linux/proc_fs.h> |
| 39 | #include <linux/efi.h> | 39 | #include <linux/efi.h> |
| 40 | #include <linux/smp_lock.h> | ||
| 41 | #include <linux/uaccess.h> | 40 | #include <linux/uaccess.h> |
| 42 | 41 | ||
| 43 | #include <asm/system.h> | 42 | #include <asm/system.h> |
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 82a51f38a546..1bc00c9d860d 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
| @@ -916,7 +916,6 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) | |||
| 916 | ws.ws_col = vc->vc_cols; | 916 | ws.ws_col = vc->vc_cols; |
| 917 | ws.ws_ypixel = vc->vc_scan_lines; | 917 | ws.ws_ypixel = vc->vc_scan_lines; |
| 918 | 918 | ||
| 919 | mutex_lock(&vc->vc_tty->termios_mutex); | ||
| 920 | spin_lock_irq(&vc->vc_tty->ctrl_lock); | 919 | spin_lock_irq(&vc->vc_tty->ctrl_lock); |
| 921 | if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col)) | 920 | if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col)) |
| 922 | pgrp = get_pid(vc->vc_tty->pgrp); | 921 | pgrp = get_pid(vc->vc_tty->pgrp); |
| @@ -926,7 +925,6 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) | |||
| 926 | put_pid(pgrp); | 925 | put_pid(pgrp); |
| 927 | } | 926 | } |
| 928 | *cws = ws; | 927 | *cws = ws; |
| 929 | mutex_unlock(&vc->vc_tty->termios_mutex); | ||
| 930 | } | 928 | } |
| 931 | 929 | ||
| 932 | if (CON_IS_VISIBLE(vc)) | 930 | if (CON_IS_VISIBLE(vc)) |
diff --git a/drivers/isdn/Makefile b/drivers/isdn/Makefile index 8380a4568d11..f1f777570e8e 100644 --- a/drivers/isdn/Makefile +++ b/drivers/isdn/Makefile | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | obj-$(CONFIG_ISDN_I4L) += i4l/ | 5 | obj-$(CONFIG_ISDN_I4L) += i4l/ |
| 6 | obj-$(CONFIG_ISDN_CAPI) += capi/ | 6 | obj-$(CONFIG_ISDN_CAPI) += capi/ |
| 7 | obj-$(CONFIG_MISDN) += mISDN/ | 7 | obj-$(CONFIG_MISDN) += mISDN/ |
| 8 | obj-$(CONFIG_ISDN_CAPI) += hardware/ | 8 | obj-$(CONFIG_ISDN) += hardware/ |
| 9 | obj-$(CONFIG_ISDN_DIVERSION) += divert/ | 9 | obj-$(CONFIG_ISDN_DIVERSION) += divert/ |
| 10 | obj-$(CONFIG_ISDN_DRV_HISAX) += hisax/ | 10 | obj-$(CONFIG_ISDN_DRV_HISAX) += hisax/ |
| 11 | obj-$(CONFIG_ISDN_DRV_ICN) += icn/ | 11 | obj-$(CONFIG_ISDN_DRV_ICN) += icn/ |
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index 2649ea55a9e8..1eac03f39d00 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c | |||
| @@ -140,7 +140,7 @@ | |||
| 140 | * #define HFC_REGISTER_DEBUG | 140 | * #define HFC_REGISTER_DEBUG |
| 141 | */ | 141 | */ |
| 142 | 142 | ||
| 143 | static const char *hfcmulti_revision = "2.00"; | 143 | static const char *hfcmulti_revision = "2.02"; |
| 144 | 144 | ||
| 145 | #include <linux/module.h> | 145 | #include <linux/module.h> |
| 146 | #include <linux/pci.h> | 146 | #include <linux/pci.h> |
| @@ -427,12 +427,12 @@ write_fifo_regio(struct hfc_multi *hc, u_char *data, int len) | |||
| 427 | { | 427 | { |
| 428 | outb(A_FIFO_DATA0, (hc->pci_iobase)+4); | 428 | outb(A_FIFO_DATA0, (hc->pci_iobase)+4); |
| 429 | while (len>>2) { | 429 | while (len>>2) { |
| 430 | outl(*(u32 *)data, hc->pci_iobase); | 430 | outl(cpu_to_le32(*(u32 *)data), hc->pci_iobase); |
| 431 | data += 4; | 431 | data += 4; |
| 432 | len -= 4; | 432 | len -= 4; |
| 433 | } | 433 | } |
| 434 | while (len>>1) { | 434 | while (len>>1) { |
| 435 | outw(*(u16 *)data, hc->pci_iobase); | 435 | outw(cpu_to_le16(*(u16 *)data), hc->pci_iobase); |
| 436 | data += 2; | 436 | data += 2; |
| 437 | len -= 2; | 437 | len -= 2; |
| 438 | } | 438 | } |
| @@ -447,17 +447,19 @@ void | |||
| 447 | write_fifo_pcimem(struct hfc_multi *hc, u_char *data, int len) | 447 | write_fifo_pcimem(struct hfc_multi *hc, u_char *data, int len) |
| 448 | { | 448 | { |
| 449 | while (len>>2) { | 449 | while (len>>2) { |
| 450 | writel(*(u32 *)data, (hc->pci_membase)+A_FIFO_DATA0); | 450 | writel(cpu_to_le32(*(u32 *)data), |
| 451 | hc->pci_membase + A_FIFO_DATA0); | ||
| 451 | data += 4; | 452 | data += 4; |
| 452 | len -= 4; | 453 | len -= 4; |
| 453 | } | 454 | } |
| 454 | while (len>>1) { | 455 | while (len>>1) { |
| 455 | writew(*(u16 *)data, (hc->pci_membase)+A_FIFO_DATA0); | 456 | writew(cpu_to_le16(*(u16 *)data), |
| 457 | hc->pci_membase + A_FIFO_DATA0); | ||
| 456 | data += 2; | 458 | data += 2; |
| 457 | len -= 2; | 459 | len -= 2; |
| 458 | } | 460 | } |
| 459 | while (len) { | 461 | while (len) { |
| 460 | writeb(*data, (hc->pci_membase)+A_FIFO_DATA0); | 462 | writeb(*data, hc->pci_membase + A_FIFO_DATA0); |
| 461 | data++; | 463 | data++; |
| 462 | len--; | 464 | len--; |
| 463 | } | 465 | } |
| @@ -468,12 +470,12 @@ read_fifo_regio(struct hfc_multi *hc, u_char *data, int len) | |||
| 468 | { | 470 | { |
| 469 | outb(A_FIFO_DATA0, (hc->pci_iobase)+4); | 471 | outb(A_FIFO_DATA0, (hc->pci_iobase)+4); |
| 470 | while (len>>2) { | 472 | while (len>>2) { |
| 471 | *(u32 *)data = inl(hc->pci_iobase); | 473 | *(u32 *)data = le32_to_cpu(inl(hc->pci_iobase)); |
| 472 | data += 4; | 474 | data += 4; |
| 473 | len -= 4; | 475 | len -= 4; |
| 474 | } | 476 | } |
| 475 | while (len>>1) { | 477 | while (len>>1) { |
| 476 | *(u16 *)data = inw(hc->pci_iobase); | 478 | *(u16 *)data = le16_to_cpu(inw(hc->pci_iobase)); |
| 477 | data += 2; | 479 | data += 2; |
| 478 | len -= 2; | 480 | len -= 2; |
| 479 | } | 481 | } |
| @@ -490,18 +492,18 @@ read_fifo_pcimem(struct hfc_multi *hc, u_char *data, int len) | |||
| 490 | { | 492 | { |
| 491 | while (len>>2) { | 493 | while (len>>2) { |
| 492 | *(u32 *)data = | 494 | *(u32 *)data = |
| 493 | readl((hc->pci_membase)+A_FIFO_DATA0); | 495 | le32_to_cpu(readl(hc->pci_membase + A_FIFO_DATA0)); |
| 494 | data += 4; | 496 | data += 4; |
| 495 | len -= 4; | 497 | len -= 4; |
| 496 | } | 498 | } |
| 497 | while (len>>1) { | 499 | while (len>>1) { |
| 498 | *(u16 *)data = | 500 | *(u16 *)data = |
| 499 | readw((hc->pci_membase)+A_FIFO_DATA0); | 501 | le16_to_cpu(readw(hc->pci_membase + A_FIFO_DATA0)); |
| 500 | data += 2; | 502 | data += 2; |
| 501 | len -= 2; | 503 | len -= 2; |
| 502 | } | 504 | } |
| 503 | while (len) { | 505 | while (len) { |
| 504 | *data = readb((hc->pci_membase)+A_FIFO_DATA0); | 506 | *data = readb(hc->pci_membase + A_FIFO_DATA0); |
| 505 | data++; | 507 | data++; |
| 506 | len--; | 508 | len--; |
| 507 | } | 509 | } |
| @@ -3971,7 +3973,7 @@ open_bchannel(struct hfc_multi *hc, struct dchannel *dch, | |||
| 3971 | struct bchannel *bch; | 3973 | struct bchannel *bch; |
| 3972 | int ch; | 3974 | int ch; |
| 3973 | 3975 | ||
| 3974 | if (!test_bit(rq->adr.channel, &dch->dev.channelmap[0])) | 3976 | if (!test_channelmap(rq->adr.channel, dch->dev.channelmap)) |
| 3975 | return -EINVAL; | 3977 | return -EINVAL; |
| 3976 | if (rq->protocol == ISDN_P_NONE) | 3978 | if (rq->protocol == ISDN_P_NONE) |
| 3977 | return -EINVAL; | 3979 | return -EINVAL; |
| @@ -4587,7 +4589,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m) | |||
| 4587 | list_add(&bch->ch.list, &dch->dev.bchannels); | 4589 | list_add(&bch->ch.list, &dch->dev.bchannels); |
| 4588 | hc->chan[ch].bch = bch; | 4590 | hc->chan[ch].bch = bch; |
| 4589 | hc->chan[ch].port = 0; | 4591 | hc->chan[ch].port = 0; |
| 4590 | test_and_set_bit(bch->nr, &dch->dev.channelmap[0]); | 4592 | set_channelmap(bch->nr, dch->dev.channelmap); |
| 4591 | } | 4593 | } |
| 4592 | /* set optical line type */ | 4594 | /* set optical line type */ |
| 4593 | if (port[Port_cnt] & 0x001) { | 4595 | if (port[Port_cnt] & 0x001) { |
| @@ -4755,7 +4757,7 @@ init_multi_port(struct hfc_multi *hc, int pt) | |||
| 4755 | list_add(&bch->ch.list, &dch->dev.bchannels); | 4757 | list_add(&bch->ch.list, &dch->dev.bchannels); |
| 4756 | hc->chan[i + ch].bch = bch; | 4758 | hc->chan[i + ch].bch = bch; |
| 4757 | hc->chan[i + ch].port = pt; | 4759 | hc->chan[i + ch].port = pt; |
| 4758 | test_and_set_bit(bch->nr, &dch->dev.channelmap[0]); | 4760 | set_channelmap(bch->nr, dch->dev.channelmap); |
| 4759 | } | 4761 | } |
| 4760 | /* set master clock */ | 4762 | /* set master clock */ |
| 4761 | if (port[Port_cnt] & 0x001) { | 4763 | if (port[Port_cnt] & 0x001) { |
| @@ -5050,12 +5052,12 @@ static void __devexit hfc_remove_pci(struct pci_dev *pdev) | |||
| 5050 | 5052 | ||
| 5051 | static const struct hm_map hfcm_map[] = { | 5053 | static const struct hm_map hfcm_map[] = { |
| 5052 | /*0*/ {VENDOR_BN, "HFC-1S Card (mini PCI)", 4, 1, 1, 3, 0, DIP_4S, 0}, | 5054 | /*0*/ {VENDOR_BN, "HFC-1S Card (mini PCI)", 4, 1, 1, 3, 0, DIP_4S, 0}, |
| 5053 | /*1*/ {VENDOR_BN, "HFC-2S Card", 4, 2, 1, 3, 0, DIP_4S}, | 5055 | /*1*/ {VENDOR_BN, "HFC-2S Card", 4, 2, 1, 3, 0, DIP_4S, 0}, |
| 5054 | /*2*/ {VENDOR_BN, "HFC-2S Card (mini PCI)", 4, 2, 1, 3, 0, DIP_4S, 0}, | 5056 | /*2*/ {VENDOR_BN, "HFC-2S Card (mini PCI)", 4, 2, 1, 3, 0, DIP_4S, 0}, |
| 5055 | /*3*/ {VENDOR_BN, "HFC-4S Card", 4, 4, 1, 2, 0, DIP_4S, 0}, | 5057 | /*3*/ {VENDOR_BN, "HFC-4S Card", 4, 4, 1, 2, 0, DIP_4S, 0}, |
| 5056 | /*4*/ {VENDOR_BN, "HFC-4S Card (mini PCI)", 4, 4, 1, 2, 0, 0, 0}, | 5058 | /*4*/ {VENDOR_BN, "HFC-4S Card (mini PCI)", 4, 4, 1, 2, 0, 0, 0}, |
| 5057 | /*5*/ {VENDOR_CCD, "HFC-4S Eval (old)", 4, 4, 0, 0, 0, 0, 0}, | 5059 | /*5*/ {VENDOR_CCD, "HFC-4S Eval (old)", 4, 4, 0, 0, 0, 0, 0}, |
| 5058 | /*6*/ {VENDOR_CCD, "HFC-4S IOB4ST", 4, 4, 1, 2, 0, 0, 0}, | 5060 | /*6*/ {VENDOR_CCD, "HFC-4S IOB4ST", 4, 4, 1, 2, 0, DIP_4S, 0}, |
| 5059 | /*7*/ {VENDOR_CCD, "HFC-4S", 4, 4, 1, 2, 0, 0, 0}, | 5061 | /*7*/ {VENDOR_CCD, "HFC-4S", 4, 4, 1, 2, 0, 0, 0}, |
| 5060 | /*8*/ {VENDOR_DIG, "HFC-4S Card", 4, 4, 0, 2, 0, 0, HFC_IO_MODE_REGIO}, | 5062 | /*8*/ {VENDOR_DIG, "HFC-4S Card", 4, 4, 0, 2, 0, 0, HFC_IO_MODE_REGIO}, |
| 5061 | /*9*/ {VENDOR_CCD, "HFC-4S Swyx 4xS0 SX2 QuadBri", 4, 4, 1, 2, 0, 0, 0}, | 5063 | /*9*/ {VENDOR_CCD, "HFC-4S Swyx 4xS0 SX2 QuadBri", 4, 4, 1, 2, 0, 0, 0}, |
| @@ -5251,9 +5253,6 @@ HFCmulti_init(void) | |||
| 5251 | if (debug & DEBUG_HFCMULTI_INIT) | 5253 | if (debug & DEBUG_HFCMULTI_INIT) |
| 5252 | printk(KERN_DEBUG "%s: init entered\n", __func__); | 5254 | printk(KERN_DEBUG "%s: init entered\n", __func__); |
| 5253 | 5255 | ||
| 5254 | #ifdef __BIG_ENDIAN | ||
| 5255 | #error "not running on big endian machines now" | ||
| 5256 | #endif | ||
| 5257 | hfc_interrupt = symbol_get(ztdummy_extern_interrupt); | 5256 | hfc_interrupt = symbol_get(ztdummy_extern_interrupt); |
| 5258 | register_interrupt = symbol_get(ztdummy_register_interrupt); | 5257 | register_interrupt = symbol_get(ztdummy_register_interrupt); |
| 5259 | unregister_interrupt = symbol_get(ztdummy_unregister_interrupt); | 5258 | unregister_interrupt = symbol_get(ztdummy_unregister_interrupt); |
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index 3231814e7efa..9cf5edbb1a9b 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c | |||
| @@ -2056,7 +2056,7 @@ setup_card(struct hfc_pci *card) | |||
| 2056 | card->dch.dev.nrbchan = 2; | 2056 | card->dch.dev.nrbchan = 2; |
| 2057 | for (i = 0; i < 2; i++) { | 2057 | for (i = 0; i < 2; i++) { |
| 2058 | card->bch[i].nr = i + 1; | 2058 | card->bch[i].nr = i + 1; |
| 2059 | test_and_set_bit(i + 1, &card->dch.dev.channelmap[0]); | 2059 | set_channelmap(i + 1, card->dch.dev.channelmap); |
| 2060 | card->bch[i].debug = debug; | 2060 | card->bch[i].debug = debug; |
| 2061 | mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM); | 2061 | mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM); |
| 2062 | card->bch[i].hw = card; | 2062 | card->bch[i].hw = card; |
diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c index 155b99780c4f..e42150a57780 100644 --- a/drivers/isdn/mISDN/l1oip_core.c +++ b/drivers/isdn/mISDN/l1oip_core.c | |||
| @@ -1006,8 +1006,7 @@ open_bchannel(struct l1oip *hc, struct dchannel *dch, struct channel_req *rq) | |||
| 1006 | struct bchannel *bch; | 1006 | struct bchannel *bch; |
| 1007 | int ch; | 1007 | int ch; |
| 1008 | 1008 | ||
| 1009 | if (!test_bit(rq->adr.channel & 0x1f, | 1009 | if (!test_channelmap(rq->adr.channel, dch->dev.channelmap)) |
| 1010 | &dch->dev.channelmap[rq->adr.channel >> 5])) | ||
| 1011 | return -EINVAL; | 1010 | return -EINVAL; |
| 1012 | if (rq->protocol == ISDN_P_NONE) | 1011 | if (rq->protocol == ISDN_P_NONE) |
| 1013 | return -EINVAL; | 1012 | return -EINVAL; |
| @@ -1412,8 +1411,7 @@ init_card(struct l1oip *hc, int pri, int bundle) | |||
| 1412 | bch->ch.nr = i + ch; | 1411 | bch->ch.nr = i + ch; |
| 1413 | list_add(&bch->ch.list, &dch->dev.bchannels); | 1412 | list_add(&bch->ch.list, &dch->dev.bchannels); |
| 1414 | hc->chan[i + ch].bch = bch; | 1413 | hc->chan[i + ch].bch = bch; |
| 1415 | test_and_set_bit(bch->nr & 0x1f, | 1414 | set_channelmap(bch->nr, dch->dev.channelmap); |
| 1416 | &dch->dev.channelmap[bch->nr >> 5]); | ||
| 1417 | } | 1415 | } |
| 1418 | ret = mISDN_register_device(&dch->dev, hc->name); | 1416 | ret = mISDN_register_device(&dch->dev, hc->name); |
| 1419 | if (ret) | 1417 | if (ret) |
diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c index 4ba4cc364c9e..e5a20f9542d1 100644 --- a/drivers/isdn/mISDN/socket.c +++ b/drivers/isdn/mISDN/socket.c | |||
| @@ -379,7 +379,7 @@ data_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
| 379 | di.Bprotocols = dev->Bprotocols | get_all_Bprotocols(); | 379 | di.Bprotocols = dev->Bprotocols | get_all_Bprotocols(); |
| 380 | di.protocol = dev->D.protocol; | 380 | di.protocol = dev->D.protocol; |
| 381 | memcpy(di.channelmap, dev->channelmap, | 381 | memcpy(di.channelmap, dev->channelmap, |
| 382 | MISDN_CHMAP_SIZE * 4); | 382 | sizeof(di.channelmap)); |
| 383 | di.nrbchan = dev->nrbchan; | 383 | di.nrbchan = dev->nrbchan; |
| 384 | strcpy(di.name, dev->name); | 384 | strcpy(di.name, dev->name); |
| 385 | if (copy_to_user((void __user *)arg, &di, sizeof(di))) | 385 | if (copy_to_user((void __user *)arg, &di, sizeof(di))) |
| @@ -637,7 +637,7 @@ base_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
| 637 | di.Bprotocols = dev->Bprotocols | get_all_Bprotocols(); | 637 | di.Bprotocols = dev->Bprotocols | get_all_Bprotocols(); |
| 638 | di.protocol = dev->D.protocol; | 638 | di.protocol = dev->D.protocol; |
| 639 | memcpy(di.channelmap, dev->channelmap, | 639 | memcpy(di.channelmap, dev->channelmap, |
| 640 | MISDN_CHMAP_SIZE * 4); | 640 | sizeof(di.channelmap)); |
| 641 | di.nrbchan = dev->nrbchan; | 641 | di.nrbchan = dev->nrbchan; |
| 642 | strcpy(di.name, dev->name); | 642 | strcpy(di.name, dev->name); |
| 643 | if (copy_to_user((void __user *)arg, &di, sizeof(di))) | 643 | if (copy_to_user((void __user *)arg, &di, sizeof(di))) |
diff --git a/drivers/mtd/maps/ipaq-flash.c b/drivers/mtd/maps/ipaq-flash.c index a806119797e0..113b1062020d 100644 --- a/drivers/mtd/maps/ipaq-flash.c +++ b/drivers/mtd/maps/ipaq-flash.c | |||
| @@ -25,7 +25,7 @@ | |||
| 25 | #endif | 25 | #endif |
| 26 | 26 | ||
| 27 | #include <asm/hardware.h> | 27 | #include <asm/hardware.h> |
| 28 | #include <asm/arch-sa1100/h3600.h> | 28 | #include <asm/arch/h3600.h> |
| 29 | #include <asm/io.h> | 29 | #include <asm/io.h> |
| 30 | 30 | ||
| 31 | 31 | ||
diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c index 9b6af7e74a65..00d46e137b2a 100644 --- a/drivers/mtd/mtdsuper.c +++ b/drivers/mtd/mtdsuper.c | |||
| @@ -125,8 +125,11 @@ int get_sb_mtd(struct file_system_type *fs_type, int flags, | |||
| 125 | int (*fill_super)(struct super_block *, void *, int), | 125 | int (*fill_super)(struct super_block *, void *, int), |
| 126 | struct vfsmount *mnt) | 126 | struct vfsmount *mnt) |
| 127 | { | 127 | { |
| 128 | #ifdef CONFIG_BLOCK | ||
| 128 | struct block_device *bdev; | 129 | struct block_device *bdev; |
| 129 | int mtdnr, ret; | 130 | int ret, major; |
| 131 | #endif | ||
| 132 | int mtdnr; | ||
| 130 | 133 | ||
| 131 | if (!dev_name) | 134 | if (!dev_name) |
| 132 | return -EINVAL; | 135 | return -EINVAL; |
| @@ -178,6 +181,7 @@ int get_sb_mtd(struct file_system_type *fs_type, int flags, | |||
| 178 | } | 181 | } |
| 179 | } | 182 | } |
| 180 | 183 | ||
| 184 | #ifdef CONFIG_BLOCK | ||
| 181 | /* try the old way - the hack where we allowed users to mount | 185 | /* try the old way - the hack where we allowed users to mount |
| 182 | * /dev/mtdblock$(n) but didn't actually _use_ the blockdev | 186 | * /dev/mtdblock$(n) but didn't actually _use_ the blockdev |
| 183 | */ | 187 | */ |
| @@ -190,22 +194,25 @@ int get_sb_mtd(struct file_system_type *fs_type, int flags, | |||
| 190 | DEBUG(1, "MTDSB: lookup_bdev() returned 0\n"); | 194 | DEBUG(1, "MTDSB: lookup_bdev() returned 0\n"); |
| 191 | 195 | ||
| 192 | ret = -EINVAL; | 196 | ret = -EINVAL; |
| 193 | if (MAJOR(bdev->bd_dev) != MTD_BLOCK_MAJOR) | ||
| 194 | goto not_an_MTD_device; | ||
| 195 | 197 | ||
| 198 | major = MAJOR(bdev->bd_dev); | ||
| 196 | mtdnr = MINOR(bdev->bd_dev); | 199 | mtdnr = MINOR(bdev->bd_dev); |
| 197 | bdput(bdev); | 200 | bdput(bdev); |
| 198 | 201 | ||
| 202 | if (major != MTD_BLOCK_MAJOR) | ||
| 203 | goto not_an_MTD_device; | ||
| 204 | |||
| 199 | return get_sb_mtd_nr(fs_type, flags, dev_name, data, mtdnr, fill_super, | 205 | return get_sb_mtd_nr(fs_type, flags, dev_name, data, mtdnr, fill_super, |
| 200 | mnt); | 206 | mnt); |
| 201 | 207 | ||
| 202 | not_an_MTD_device: | 208 | not_an_MTD_device: |
| 209 | #endif /* CONFIG_BLOCK */ | ||
| 210 | |||
| 203 | if (!(flags & MS_SILENT)) | 211 | if (!(flags & MS_SILENT)) |
| 204 | printk(KERN_NOTICE | 212 | printk(KERN_NOTICE |
| 205 | "MTD: Attempt to mount non-MTD device \"%s\"\n", | 213 | "MTD: Attempt to mount non-MTD device \"%s\"\n", |
| 206 | dev_name); | 214 | dev_name); |
| 207 | bdput(bdev); | 215 | return -EINVAL; |
| 208 | return ret; | ||
| 209 | } | 216 | } |
| 210 | 217 | ||
| 211 | EXPORT_SYMBOL_GPL(get_sb_mtd); | 218 | EXPORT_SYMBOL_GPL(get_sb_mtd); |
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index d0c1d63d1891..203e579ebbd2 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c | |||
| @@ -275,7 +275,7 @@ static int readable(struct pcmcia_socket *s, struct resource *res, | |||
| 275 | destroy_cis_cache(s); | 275 | destroy_cis_cache(s); |
| 276 | } | 276 | } |
| 277 | s->cis_mem.res = NULL; | 277 | s->cis_mem.res = NULL; |
| 278 | if ((ret != 0) || (count == 0)) | 278 | if ((ret != 0) || (*count == 0)) |
| 279 | return 0; | 279 | return 0; |
| 280 | return 1; | 280 | return 1; |
| 281 | } | 281 | } |
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index da876d3924be..74d12b58a263 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c | |||
| @@ -1249,6 +1249,13 @@ static struct pci_device_id hptiop_id_table[] = { | |||
| 1249 | { PCI_VDEVICE(TTI, 0x3522), (kernel_ulong_t)&hptiop_itl_ops }, | 1249 | { PCI_VDEVICE(TTI, 0x3522), (kernel_ulong_t)&hptiop_itl_ops }, |
| 1250 | { PCI_VDEVICE(TTI, 0x3410), (kernel_ulong_t)&hptiop_itl_ops }, | 1250 | { PCI_VDEVICE(TTI, 0x3410), (kernel_ulong_t)&hptiop_itl_ops }, |
| 1251 | { PCI_VDEVICE(TTI, 0x3540), (kernel_ulong_t)&hptiop_itl_ops }, | 1251 | { PCI_VDEVICE(TTI, 0x3540), (kernel_ulong_t)&hptiop_itl_ops }, |
| 1252 | { PCI_VDEVICE(TTI, 0x3530), (kernel_ulong_t)&hptiop_itl_ops }, | ||
| 1253 | { PCI_VDEVICE(TTI, 0x3560), (kernel_ulong_t)&hptiop_itl_ops }, | ||
| 1254 | { PCI_VDEVICE(TTI, 0x4322), (kernel_ulong_t)&hptiop_itl_ops }, | ||
| 1255 | { PCI_VDEVICE(TTI, 0x4210), (kernel_ulong_t)&hptiop_itl_ops }, | ||
| 1256 | { PCI_VDEVICE(TTI, 0x4211), (kernel_ulong_t)&hptiop_itl_ops }, | ||
| 1257 | { PCI_VDEVICE(TTI, 0x4310), (kernel_ulong_t)&hptiop_itl_ops }, | ||
| 1258 | { PCI_VDEVICE(TTI, 0x4311), (kernel_ulong_t)&hptiop_itl_ops }, | ||
| 1252 | { PCI_VDEVICE(TTI, 0x3120), (kernel_ulong_t)&hptiop_mv_ops }, | 1259 | { PCI_VDEVICE(TTI, 0x3120), (kernel_ulong_t)&hptiop_mv_ops }, |
| 1253 | { PCI_VDEVICE(TTI, 0x3122), (kernel_ulong_t)&hptiop_mv_ops }, | 1260 | { PCI_VDEVICE(TTI, 0x3122), (kernel_ulong_t)&hptiop_mv_ops }, |
| 1254 | { PCI_VDEVICE(TTI, 0x3020), (kernel_ulong_t)&hptiop_mv_ops }, | 1261 | { PCI_VDEVICE(TTI, 0x3020), (kernel_ulong_t)&hptiop_mv_ops }, |
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 75a64a6cae8c..b29360ed0bdc 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c | |||
| @@ -366,12 +366,14 @@ spi_transport_rd_attr(rti, "%d\n"); | |||
| 366 | spi_transport_rd_attr(pcomp_en, "%d\n"); | 366 | spi_transport_rd_attr(pcomp_en, "%d\n"); |
| 367 | spi_transport_rd_attr(hold_mcs, "%d\n"); | 367 | spi_transport_rd_attr(hold_mcs, "%d\n"); |
| 368 | 368 | ||
| 369 | /* we only care about the first child device so we return 1 */ | 369 | /* we only care about the first child device that's a real SCSI device |
| 370 | * so we return 1 to terminate the iteration when we find it */ | ||
| 370 | static int child_iter(struct device *dev, void *data) | 371 | static int child_iter(struct device *dev, void *data) |
| 371 | { | 372 | { |
| 372 | struct scsi_device *sdev = to_scsi_device(dev); | 373 | if (!scsi_is_sdev_device(dev)) |
| 374 | return 0; | ||
| 373 | 375 | ||
| 374 | spi_dv_device(sdev); | 376 | spi_dv_device(to_scsi_device(dev)); |
| 375 | return 1; | 377 | return 1; |
| 376 | } | 378 | } |
| 377 | 379 | ||
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index e5e7d7856454..8e08d51a0f05 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
| @@ -375,7 +375,6 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
| 375 | struct gendisk *disk = rq->rq_disk; | 375 | struct gendisk *disk = rq->rq_disk; |
| 376 | struct scsi_disk *sdkp; | 376 | struct scsi_disk *sdkp; |
| 377 | sector_t block = rq->sector; | 377 | sector_t block = rq->sector; |
| 378 | sector_t threshold; | ||
| 379 | unsigned int this_count = rq->nr_sectors; | 378 | unsigned int this_count = rq->nr_sectors; |
| 380 | unsigned int timeout = sdp->timeout; | 379 | unsigned int timeout = sdp->timeout; |
| 381 | int ret; | 380 | int ret; |
| @@ -423,21 +422,13 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
| 423 | } | 422 | } |
| 424 | 423 | ||
| 425 | /* | 424 | /* |
| 426 | * Some SD card readers can't handle multi-sector accesses which touch | 425 | * Some devices (some sdcards for one) don't like it if the |
| 427 | * the last one or two hardware sectors. Split accesses as needed. | 426 | * last sector gets read in a larger then 1 sector read. |
| 428 | */ | 427 | */ |
| 429 | threshold = get_capacity(disk) - SD_LAST_BUGGY_SECTORS * | 428 | if (unlikely(sdp->last_sector_bug && |
| 430 | (sdp->sector_size / 512); | 429 | rq->nr_sectors > sdp->sector_size / 512 && |
| 431 | 430 | block + this_count == get_capacity(disk))) | |
| 432 | if (unlikely(sdp->last_sector_bug && block + this_count > threshold)) { | 431 | this_count -= sdp->sector_size / 512; |
| 433 | if (block < threshold) { | ||
| 434 | /* Access up to the threshold but not beyond */ | ||
| 435 | this_count = threshold - block; | ||
| 436 | } else { | ||
| 437 | /* Access only a single hardware sector */ | ||
| 438 | this_count = sdp->sector_size / 512; | ||
| 439 | } | ||
| 440 | } | ||
| 441 | 432 | ||
| 442 | SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n", | 433 | SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n", |
| 443 | (unsigned long long)block)); | 434 | (unsigned long long)block)); |
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 95b9f06534d5..550b2f70a1f8 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h | |||
| @@ -31,12 +31,6 @@ | |||
| 31 | */ | 31 | */ |
| 32 | #define SD_BUF_SIZE 512 | 32 | #define SD_BUF_SIZE 512 |
| 33 | 33 | ||
| 34 | /* | ||
| 35 | * Number of sectors at the end of the device to avoid multi-sector | ||
| 36 | * accesses to in the case of last_sector_bug | ||
| 37 | */ | ||
| 38 | #define SD_LAST_BUGGY_SECTORS 8 | ||
| 39 | |||
| 40 | struct scsi_disk { | 34 | struct scsi_disk { |
| 41 | struct scsi_driver *driver; /* always &sd_template */ | 35 | struct scsi_driver *driver; /* always &sd_template */ |
| 42 | struct scsi_device *device; | 36 | struct scsi_device *device; |
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c index 0fe031f003e7..1bcf3c33d7ff 100644 --- a/drivers/scsi/ses.c +++ b/drivers/scsi/ses.c | |||
| @@ -345,14 +345,14 @@ static int ses_enclosure_find_by_addr(struct enclosure_device *edev, | |||
| 345 | return 0; | 345 | return 0; |
| 346 | } | 346 | } |
| 347 | 347 | ||
| 348 | #define VPD_INQUIRY_SIZE 512 | 348 | #define VPD_INQUIRY_SIZE 36 |
| 349 | 349 | ||
| 350 | static void ses_match_to_enclosure(struct enclosure_device *edev, | 350 | static void ses_match_to_enclosure(struct enclosure_device *edev, |
| 351 | struct scsi_device *sdev) | 351 | struct scsi_device *sdev) |
| 352 | { | 352 | { |
| 353 | unsigned char *buf = kmalloc(VPD_INQUIRY_SIZE, GFP_KERNEL); | 353 | unsigned char *buf = kmalloc(VPD_INQUIRY_SIZE, GFP_KERNEL); |
| 354 | unsigned char *desc; | 354 | unsigned char *desc; |
| 355 | int len; | 355 | u16 vpd_len; |
| 356 | struct efd efd = { | 356 | struct efd efd = { |
| 357 | .addr = 0, | 357 | .addr = 0, |
| 358 | }; | 358 | }; |
| @@ -372,9 +372,19 @@ static void ses_match_to_enclosure(struct enclosure_device *edev, | |||
| 372 | VPD_INQUIRY_SIZE, NULL, SES_TIMEOUT, SES_RETRIES)) | 372 | VPD_INQUIRY_SIZE, NULL, SES_TIMEOUT, SES_RETRIES)) |
| 373 | goto free; | 373 | goto free; |
| 374 | 374 | ||
| 375 | len = (buf[2] << 8) + buf[3]; | 375 | vpd_len = (buf[2] << 8) + buf[3]; |
| 376 | kfree(buf); | ||
| 377 | buf = kmalloc(vpd_len, GFP_KERNEL); | ||
| 378 | if (!buf) | ||
| 379 | return; | ||
| 380 | cmd[3] = vpd_len >> 8; | ||
| 381 | cmd[4] = vpd_len & 0xff; | ||
| 382 | if (scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, | ||
| 383 | vpd_len, NULL, SES_TIMEOUT, SES_RETRIES)) | ||
| 384 | goto free; | ||
| 385 | |||
| 376 | desc = buf + 4; | 386 | desc = buf + 4; |
| 377 | while (desc < buf + len) { | 387 | while (desc < buf + vpd_len) { |
| 378 | enum scsi_protocol proto = desc[0] >> 4; | 388 | enum scsi_protocol proto = desc[0] >> 4; |
| 379 | u8 code_set = desc[0] & 0x0f; | 389 | u8 code_set = desc[0] & 0x0f; |
| 380 | u8 piv = desc[1] & 0x80; | 390 | u8 piv = desc[1] & 0x80; |
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index 9d8543762a30..efcd44344fb1 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c | |||
| @@ -817,7 +817,7 @@ static void bfin_serial_set_ldisc(struct uart_port *port) | |||
| 817 | if (line >= port->info->port.tty->driver->num) | 817 | if (line >= port->info->port.tty->driver->num) |
| 818 | return; | 818 | return; |
| 819 | 819 | ||
| 820 | switch (port->info->port.tty->ldisc.num) { | 820 | switch (port->info->port.tty->termios->c_line) { |
| 821 | case N_IRDA: | 821 | case N_IRDA: |
| 822 | val = UART_GET_GCTL(&bfin_serial_ports[line]); | 822 | val = UART_GET_GCTL(&bfin_serial_ports[line]); |
| 823 | val |= (IREN | RPOLC); | 823 | val |= (IREN | RPOLC); |
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 8249ac490559..bf94a770bb44 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c | |||
| @@ -234,7 +234,7 @@ unsigned long r_alt_ser_baudrate_shadow = 0; | |||
| 234 | 234 | ||
| 235 | static struct e100_serial rs_table[] = { | 235 | static struct e100_serial rs_table[] = { |
| 236 | { .baud = DEF_BAUD, | 236 | { .baud = DEF_BAUD, |
| 237 | .port = (unsigned char *)R_SERIAL0_CTRL, | 237 | .ioport = (unsigned char *)R_SERIAL0_CTRL, |
| 238 | .irq = 1U << 12, /* uses DMA 6 and 7 */ | 238 | .irq = 1U << 12, /* uses DMA 6 and 7 */ |
| 239 | .oclrintradr = R_DMA_CH6_CLR_INTR, | 239 | .oclrintradr = R_DMA_CH6_CLR_INTR, |
| 240 | .ofirstadr = R_DMA_CH6_FIRST, | 240 | .ofirstadr = R_DMA_CH6_FIRST, |
| @@ -288,7 +288,7 @@ static struct e100_serial rs_table[] = { | |||
| 288 | }, /* ttyS0 */ | 288 | }, /* ttyS0 */ |
| 289 | #ifndef CONFIG_SVINTO_SIM | 289 | #ifndef CONFIG_SVINTO_SIM |
| 290 | { .baud = DEF_BAUD, | 290 | { .baud = DEF_BAUD, |
| 291 | .port = (unsigned char *)R_SERIAL1_CTRL, | 291 | .ioport = (unsigned char *)R_SERIAL1_CTRL, |
| 292 | .irq = 1U << 16, /* uses DMA 8 and 9 */ | 292 | .irq = 1U << 16, /* uses DMA 8 and 9 */ |
| 293 | .oclrintradr = R_DMA_CH8_CLR_INTR, | 293 | .oclrintradr = R_DMA_CH8_CLR_INTR, |
| 294 | .ofirstadr = R_DMA_CH8_FIRST, | 294 | .ofirstadr = R_DMA_CH8_FIRST, |
| @@ -344,7 +344,7 @@ static struct e100_serial rs_table[] = { | |||
| 344 | }, /* ttyS1 */ | 344 | }, /* ttyS1 */ |
| 345 | 345 | ||
| 346 | { .baud = DEF_BAUD, | 346 | { .baud = DEF_BAUD, |
| 347 | .port = (unsigned char *)R_SERIAL2_CTRL, | 347 | .ioport = (unsigned char *)R_SERIAL2_CTRL, |
| 348 | .irq = 1U << 4, /* uses DMA 2 and 3 */ | 348 | .irq = 1U << 4, /* uses DMA 2 and 3 */ |
| 349 | .oclrintradr = R_DMA_CH2_CLR_INTR, | 349 | .oclrintradr = R_DMA_CH2_CLR_INTR, |
| 350 | .ofirstadr = R_DMA_CH2_FIRST, | 350 | .ofirstadr = R_DMA_CH2_FIRST, |
| @@ -398,7 +398,7 @@ static struct e100_serial rs_table[] = { | |||
| 398 | }, /* ttyS2 */ | 398 | }, /* ttyS2 */ |
| 399 | 399 | ||
| 400 | { .baud = DEF_BAUD, | 400 | { .baud = DEF_BAUD, |
| 401 | .port = (unsigned char *)R_SERIAL3_CTRL, | 401 | .ioport = (unsigned char *)R_SERIAL3_CTRL, |
| 402 | .irq = 1U << 8, /* uses DMA 4 and 5 */ | 402 | .irq = 1U << 8, /* uses DMA 4 and 5 */ |
| 403 | .oclrintradr = R_DMA_CH4_CLR_INTR, | 403 | .oclrintradr = R_DMA_CH4_CLR_INTR, |
| 404 | .ofirstadr = R_DMA_CH4_FIRST, | 404 | .ofirstadr = R_DMA_CH4_FIRST, |
| @@ -939,7 +939,7 @@ static const struct control_pins e100_modem_pins[NR_PORTS] = | |||
| 939 | /* Output */ | 939 | /* Output */ |
| 940 | #define E100_RTS_GET(info) ((info)->rx_ctrl & E100_RTS_MASK) | 940 | #define E100_RTS_GET(info) ((info)->rx_ctrl & E100_RTS_MASK) |
| 941 | /* Input */ | 941 | /* Input */ |
| 942 | #define E100_CTS_GET(info) ((info)->port[REG_STATUS] & E100_CTS_MASK) | 942 | #define E100_CTS_GET(info) ((info)->ioport[REG_STATUS] & E100_CTS_MASK) |
| 943 | 943 | ||
| 944 | /* These are typically PA or PB and 0 means 0V, 1 means 3.3V */ | 944 | /* These are typically PA or PB and 0 means 0V, 1 means 3.3V */ |
| 945 | /* Is an output */ | 945 | /* Is an output */ |
| @@ -1092,7 +1092,7 @@ e100_rts(struct e100_serial *info, int set) | |||
| 1092 | local_irq_save(flags); | 1092 | local_irq_save(flags); |
| 1093 | info->rx_ctrl &= ~E100_RTS_MASK; | 1093 | info->rx_ctrl &= ~E100_RTS_MASK; |
| 1094 | info->rx_ctrl |= (set ? 0 : E100_RTS_MASK); /* RTS is active low */ | 1094 | info->rx_ctrl |= (set ? 0 : E100_RTS_MASK); /* RTS is active low */ |
| 1095 | info->port[REG_REC_CTRL] = info->rx_ctrl; | 1095 | info->ioport[REG_REC_CTRL] = info->rx_ctrl; |
| 1096 | local_irq_restore(flags); | 1096 | local_irq_restore(flags); |
| 1097 | #ifdef SERIAL_DEBUG_IO | 1097 | #ifdef SERIAL_DEBUG_IO |
| 1098 | printk("ser%i rts %i\n", info->line, set); | 1098 | printk("ser%i rts %i\n", info->line, set); |
| @@ -1142,7 +1142,7 @@ e100_disable_rx(struct e100_serial *info) | |||
| 1142 | { | 1142 | { |
| 1143 | #ifndef CONFIG_SVINTO_SIM | 1143 | #ifndef CONFIG_SVINTO_SIM |
| 1144 | /* disable the receiver */ | 1144 | /* disable the receiver */ |
| 1145 | info->port[REG_REC_CTRL] = | 1145 | info->ioport[REG_REC_CTRL] = |
| 1146 | (info->rx_ctrl &= ~IO_MASK(R_SERIAL0_REC_CTRL, rec_enable)); | 1146 | (info->rx_ctrl &= ~IO_MASK(R_SERIAL0_REC_CTRL, rec_enable)); |
| 1147 | #endif | 1147 | #endif |
| 1148 | } | 1148 | } |
| @@ -1152,7 +1152,7 @@ e100_enable_rx(struct e100_serial *info) | |||
| 1152 | { | 1152 | { |
| 1153 | #ifndef CONFIG_SVINTO_SIM | 1153 | #ifndef CONFIG_SVINTO_SIM |
| 1154 | /* enable the receiver */ | 1154 | /* enable the receiver */ |
| 1155 | info->port[REG_REC_CTRL] = | 1155 | info->ioport[REG_REC_CTRL] = |
| 1156 | (info->rx_ctrl |= IO_MASK(R_SERIAL0_REC_CTRL, rec_enable)); | 1156 | (info->rx_ctrl |= IO_MASK(R_SERIAL0_REC_CTRL, rec_enable)); |
| 1157 | #endif | 1157 | #endif |
| 1158 | } | 1158 | } |
| @@ -1490,7 +1490,7 @@ rs_stop(struct tty_struct *tty) | |||
| 1490 | xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); | 1490 | xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); |
| 1491 | } | 1491 | } |
| 1492 | 1492 | ||
| 1493 | *((unsigned long *)&info->port[REG_XOFF]) = xoff; | 1493 | *((unsigned long *)&info->ioport[REG_XOFF]) = xoff; |
| 1494 | local_irq_restore(flags); | 1494 | local_irq_restore(flags); |
| 1495 | } | 1495 | } |
| 1496 | } | 1496 | } |
| @@ -1513,7 +1513,7 @@ rs_start(struct tty_struct *tty) | |||
| 1513 | xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); | 1513 | xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); |
| 1514 | } | 1514 | } |
| 1515 | 1515 | ||
| 1516 | *((unsigned long *)&info->port[REG_XOFF]) = xoff; | 1516 | *((unsigned long *)&info->ioport[REG_XOFF]) = xoff; |
| 1517 | if (!info->uses_dma_out && | 1517 | if (!info->uses_dma_out && |
| 1518 | info->xmit.head != info->xmit.tail && info->xmit.buf) | 1518 | info->xmit.head != info->xmit.tail && info->xmit.buf) |
| 1519 | e100_enable_serial_tx_ready_irq(info); | 1519 | e100_enable_serial_tx_ready_irq(info); |
| @@ -1888,7 +1888,7 @@ static void receive_chars_dma(struct e100_serial *info) | |||
| 1888 | handle_all_descr_data(info); | 1888 | handle_all_descr_data(info); |
| 1889 | 1889 | ||
| 1890 | /* Read the status register to detect errors */ | 1890 | /* Read the status register to detect errors */ |
| 1891 | rstat = info->port[REG_STATUS]; | 1891 | rstat = info->ioport[REG_STATUS]; |
| 1892 | if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect) ) { | 1892 | if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect) ) { |
| 1893 | DFLOW(DEBUG_LOG(info->line, "XOFF detect stat %x\n", rstat)); | 1893 | DFLOW(DEBUG_LOG(info->line, "XOFF detect stat %x\n", rstat)); |
| 1894 | } | 1894 | } |
| @@ -1897,7 +1897,7 @@ static void receive_chars_dma(struct e100_serial *info) | |||
| 1897 | /* If we got an error, we must reset it by reading the | 1897 | /* If we got an error, we must reset it by reading the |
| 1898 | * data_in field | 1898 | * data_in field |
| 1899 | */ | 1899 | */ |
| 1900 | unsigned char data = info->port[REG_DATA]; | 1900 | unsigned char data = info->ioport[REG_DATA]; |
| 1901 | 1901 | ||
| 1902 | PROCSTAT(ser_stat[info->line].errors_cnt++); | 1902 | PROCSTAT(ser_stat[info->line].errors_cnt++); |
| 1903 | DEBUG_LOG(info->line, "#dERR: s d 0x%04X\n", | 1903 | DEBUG_LOG(info->line, "#dERR: s d 0x%04X\n", |
| @@ -2077,7 +2077,7 @@ static int force_eop_if_needed(struct e100_serial *info) | |||
| 2077 | /* We check data_avail bit to determine if data has | 2077 | /* We check data_avail bit to determine if data has |
| 2078 | * arrived since last time | 2078 | * arrived since last time |
| 2079 | */ | 2079 | */ |
| 2080 | unsigned char rstat = info->port[REG_STATUS]; | 2080 | unsigned char rstat = info->ioport[REG_STATUS]; |
| 2081 | 2081 | ||
| 2082 | /* error or datavail? */ | 2082 | /* error or datavail? */ |
| 2083 | if (rstat & SER_ERROR_MASK) { | 2083 | if (rstat & SER_ERROR_MASK) { |
| @@ -2096,7 +2096,7 @@ static int force_eop_if_needed(struct e100_serial *info) | |||
| 2096 | TIMERD(DEBUG_LOG(info->line, "timeout: rstat 0x%03X\n", | 2096 | TIMERD(DEBUG_LOG(info->line, "timeout: rstat 0x%03X\n", |
| 2097 | rstat | (info->line << 8))); | 2097 | rstat | (info->line << 8))); |
| 2098 | /* Read data to clear status flags */ | 2098 | /* Read data to clear status flags */ |
| 2099 | (void)info->port[REG_DATA]; | 2099 | (void)info->ioport[REG_DATA]; |
| 2100 | 2100 | ||
| 2101 | info->forced_eop = 0; | 2101 | info->forced_eop = 0; |
| 2102 | START_FLUSH_FAST_TIMER(info, "magic"); | 2102 | START_FLUSH_FAST_TIMER(info, "magic"); |
| @@ -2296,7 +2296,7 @@ struct e100_serial * handle_ser_rx_interrupt_no_dma(struct e100_serial *info) | |||
| 2296 | } | 2296 | } |
| 2297 | 2297 | ||
| 2298 | /* Read data and status at the same time */ | 2298 | /* Read data and status at the same time */ |
| 2299 | data_read = *((unsigned long *)&info->port[REG_DATA_STATUS32]); | 2299 | data_read = *((unsigned long *)&info->ioport[REG_DATA_STATUS32]); |
| 2300 | more_data: | 2300 | more_data: |
| 2301 | if (data_read & IO_MASK(R_SERIAL0_READ, xoff_detect) ) { | 2301 | if (data_read & IO_MASK(R_SERIAL0_READ, xoff_detect) ) { |
| 2302 | DFLOW(DEBUG_LOG(info->line, "XOFF detect\n", 0)); | 2302 | DFLOW(DEBUG_LOG(info->line, "XOFF detect\n", 0)); |
| @@ -2391,7 +2391,7 @@ more_data: | |||
| 2391 | 2391 | ||
| 2392 | 2392 | ||
| 2393 | info->icount.rx++; | 2393 | info->icount.rx++; |
| 2394 | data_read = *((unsigned long *)&info->port[REG_DATA_STATUS32]); | 2394 | data_read = *((unsigned long *)&info->ioport[REG_DATA_STATUS32]); |
| 2395 | if (data_read & IO_MASK(R_SERIAL0_READ, data_avail)) { | 2395 | if (data_read & IO_MASK(R_SERIAL0_READ, data_avail)) { |
| 2396 | DEBUG_LOG(info->line, "ser_rx %c in loop\n", IO_EXTRACT(R_SERIAL0_READ, data_in, data_read)); | 2396 | DEBUG_LOG(info->line, "ser_rx %c in loop\n", IO_EXTRACT(R_SERIAL0_READ, data_in, data_read)); |
| 2397 | goto more_data; | 2397 | goto more_data; |
| @@ -2413,7 +2413,7 @@ static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info) | |||
| 2413 | return handle_ser_rx_interrupt_no_dma(info); | 2413 | return handle_ser_rx_interrupt_no_dma(info); |
| 2414 | } | 2414 | } |
| 2415 | /* DMA is used */ | 2415 | /* DMA is used */ |
| 2416 | rstat = info->port[REG_STATUS]; | 2416 | rstat = info->ioport[REG_STATUS]; |
| 2417 | if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect) ) { | 2417 | if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect) ) { |
| 2418 | DFLOW(DEBUG_LOG(info->line, "XOFF detect\n", 0)); | 2418 | DFLOW(DEBUG_LOG(info->line, "XOFF detect\n", 0)); |
| 2419 | } | 2419 | } |
| @@ -2426,7 +2426,7 @@ static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info) | |||
| 2426 | /* If we got an error, we must reset it by reading the | 2426 | /* If we got an error, we must reset it by reading the |
| 2427 | * data_in field | 2427 | * data_in field |
| 2428 | */ | 2428 | */ |
| 2429 | data = info->port[REG_DATA]; | 2429 | data = info->ioport[REG_DATA]; |
| 2430 | DINTR1(DEBUG_LOG(info->line, "ser_rx! %c\n", data)); | 2430 | DINTR1(DEBUG_LOG(info->line, "ser_rx! %c\n", data)); |
| 2431 | DINTR1(DEBUG_LOG(info->line, "ser_rx err stat %02X\n", rstat)); | 2431 | DINTR1(DEBUG_LOG(info->line, "ser_rx err stat %02X\n", rstat)); |
| 2432 | if (!data && (rstat & SER_FRAMING_ERR_MASK)) { | 2432 | if (!data && (rstat & SER_FRAMING_ERR_MASK)) { |
| @@ -2528,10 +2528,10 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) | |||
| 2528 | unsigned char rstat; | 2528 | unsigned char rstat; |
| 2529 | DFLOW(DEBUG_LOG(info->line, "tx_int: xchar 0x%02X\n", info->x_char)); | 2529 | DFLOW(DEBUG_LOG(info->line, "tx_int: xchar 0x%02X\n", info->x_char)); |
| 2530 | local_irq_save(flags); | 2530 | local_irq_save(flags); |
| 2531 | rstat = info->port[REG_STATUS]; | 2531 | rstat = info->ioport[REG_STATUS]; |
| 2532 | DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat)); | 2532 | DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat)); |
| 2533 | 2533 | ||
| 2534 | info->port[REG_TR_DATA] = info->x_char; | 2534 | info->ioport[REG_TR_DATA] = info->x_char; |
| 2535 | info->icount.tx++; | 2535 | info->icount.tx++; |
| 2536 | info->x_char = 0; | 2536 | info->x_char = 0; |
| 2537 | /* We must enable since it is disabled in ser_interrupt */ | 2537 | /* We must enable since it is disabled in ser_interrupt */ |
| @@ -2545,7 +2545,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) | |||
| 2545 | /* We only use normal tx interrupt when sending x_char */ | 2545 | /* We only use normal tx interrupt when sending x_char */ |
| 2546 | DFLOW(DEBUG_LOG(info->line, "tx_int: xchar sent\n", 0)); | 2546 | DFLOW(DEBUG_LOG(info->line, "tx_int: xchar sent\n", 0)); |
| 2547 | local_irq_save(flags); | 2547 | local_irq_save(flags); |
| 2548 | rstat = info->port[REG_STATUS]; | 2548 | rstat = info->ioport[REG_STATUS]; |
| 2549 | DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat)); | 2549 | DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat)); |
| 2550 | e100_disable_serial_tx_ready_irq(info); | 2550 | e100_disable_serial_tx_ready_irq(info); |
| 2551 | if (info->port.tty->stopped) | 2551 | if (info->port.tty->stopped) |
| @@ -2573,7 +2573,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) | |||
| 2573 | DINTR2(DEBUG_LOG(info->line, "tx_int %c\n", info->xmit.buf[info->xmit.tail])); | 2573 | DINTR2(DEBUG_LOG(info->line, "tx_int %c\n", info->xmit.buf[info->xmit.tail])); |
| 2574 | /* Send a byte, rs485 timing is critical so turn of ints */ | 2574 | /* Send a byte, rs485 timing is critical so turn of ints */ |
| 2575 | local_irq_save(flags); | 2575 | local_irq_save(flags); |
| 2576 | info->port[REG_TR_DATA] = info->xmit.buf[info->xmit.tail]; | 2576 | info->ioport[REG_TR_DATA] = info->xmit.buf[info->xmit.tail]; |
| 2577 | info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1); | 2577 | info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1); |
| 2578 | info->icount.tx++; | 2578 | info->icount.tx++; |
| 2579 | if (info->xmit.head == info->xmit.tail) { | 2579 | if (info->xmit.head == info->xmit.tail) { |
| @@ -2848,7 +2848,7 @@ startup(struct e100_serial * info) | |||
| 2848 | 2848 | ||
| 2849 | /* dummy read to reset any serial errors */ | 2849 | /* dummy read to reset any serial errors */ |
| 2850 | 2850 | ||
| 2851 | (void)info->port[REG_DATA]; | 2851 | (void)info->ioport[REG_DATA]; |
| 2852 | 2852 | ||
| 2853 | /* enable the interrupts */ | 2853 | /* enable the interrupts */ |
| 2854 | if (info->uses_dma_out) | 2854 | if (info->uses_dma_out) |
| @@ -2897,7 +2897,7 @@ shutdown(struct e100_serial * info) | |||
| 2897 | /* shut down the transmitter and receiver */ | 2897 | /* shut down the transmitter and receiver */ |
| 2898 | DFLOW(DEBUG_LOG(info->line, "shutdown %i\n", info->line)); | 2898 | DFLOW(DEBUG_LOG(info->line, "shutdown %i\n", info->line)); |
| 2899 | e100_disable_rx(info); | 2899 | e100_disable_rx(info); |
| 2900 | info->port[REG_TR_CTRL] = (info->tx_ctrl &= ~0x40); | 2900 | info->ioport[REG_TR_CTRL] = (info->tx_ctrl &= ~0x40); |
| 2901 | 2901 | ||
| 2902 | /* disable interrupts, reset dma channels */ | 2902 | /* disable interrupts, reset dma channels */ |
| 2903 | if (info->uses_dma_in) { | 2903 | if (info->uses_dma_in) { |
| @@ -2968,7 +2968,7 @@ change_speed(struct e100_serial *info) | |||
| 2968 | 2968 | ||
| 2969 | if (!info->port.tty || !info->port.tty->termios) | 2969 | if (!info->port.tty || !info->port.tty->termios) |
| 2970 | return; | 2970 | return; |
| 2971 | if (!info->port) | 2971 | if (!info->ioport) |
| 2972 | return; | 2972 | return; |
| 2973 | 2973 | ||
| 2974 | cflag = info->port.tty->termios->c_cflag; | 2974 | cflag = info->port.tty->termios->c_cflag; |
| @@ -3037,7 +3037,7 @@ change_speed(struct e100_serial *info) | |||
| 3037 | 3037 | ||
| 3038 | info->baud = cflag_to_baud(cflag); | 3038 | info->baud = cflag_to_baud(cflag); |
| 3039 | #ifndef CONFIG_SVINTO_SIM | 3039 | #ifndef CONFIG_SVINTO_SIM |
| 3040 | info->port[REG_BAUD] = cflag_to_etrax_baud(cflag); | 3040 | info->ioport[REG_BAUD] = cflag_to_etrax_baud(cflag); |
| 3041 | #endif /* CONFIG_SVINTO_SIM */ | 3041 | #endif /* CONFIG_SVINTO_SIM */ |
| 3042 | } | 3042 | } |
| 3043 | 3043 | ||
| @@ -3097,8 +3097,8 @@ change_speed(struct e100_serial *info) | |||
| 3097 | 3097 | ||
| 3098 | /* actually write the control regs to the hardware */ | 3098 | /* actually write the control regs to the hardware */ |
| 3099 | 3099 | ||
| 3100 | info->port[REG_TR_CTRL] = info->tx_ctrl; | 3100 | info->ioport[REG_TR_CTRL] = info->tx_ctrl; |
| 3101 | info->port[REG_REC_CTRL] = info->rx_ctrl; | 3101 | info->ioport[REG_REC_CTRL] = info->rx_ctrl; |
| 3102 | xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->port.tty)); | 3102 | xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->port.tty)); |
| 3103 | xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable); | 3103 | xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable); |
| 3104 | if (info->port.tty->termios->c_iflag & IXON ) { | 3104 | if (info->port.tty->termios->c_iflag & IXON ) { |
| @@ -3107,7 +3107,7 @@ change_speed(struct e100_serial *info) | |||
| 3107 | xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); | 3107 | xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); |
| 3108 | } | 3108 | } |
| 3109 | 3109 | ||
| 3110 | *((unsigned long *)&info->port[REG_XOFF]) = xoff; | 3110 | *((unsigned long *)&info->ioport[REG_XOFF]) = xoff; |
| 3111 | local_irq_restore(flags); | 3111 | local_irq_restore(flags); |
| 3112 | #endif /* !CONFIG_SVINTO_SIM */ | 3112 | #endif /* !CONFIG_SVINTO_SIM */ |
| 3113 | 3113 | ||
| @@ -3156,7 +3156,7 @@ static int rs_raw_write(struct tty_struct *tty, | |||
| 3156 | #ifdef SERIAL_DEBUG_DATA | 3156 | #ifdef SERIAL_DEBUG_DATA |
| 3157 | if (info->line == SERIAL_DEBUG_LINE) | 3157 | if (info->line == SERIAL_DEBUG_LINE) |
| 3158 | printk("rs_raw_write (%d), status %d\n", | 3158 | printk("rs_raw_write (%d), status %d\n", |
| 3159 | count, info->port[REG_STATUS]); | 3159 | count, info->ioport[REG_STATUS]); |
| 3160 | #endif | 3160 | #endif |
| 3161 | 3161 | ||
| 3162 | #ifdef CONFIG_SVINTO_SIM | 3162 | #ifdef CONFIG_SVINTO_SIM |
| @@ -3427,7 +3427,7 @@ get_serial_info(struct e100_serial * info, | |||
| 3427 | memset(&tmp, 0, sizeof(tmp)); | 3427 | memset(&tmp, 0, sizeof(tmp)); |
| 3428 | tmp.type = info->type; | 3428 | tmp.type = info->type; |
| 3429 | tmp.line = info->line; | 3429 | tmp.line = info->line; |
| 3430 | tmp.port = (int)info->port; | 3430 | tmp.port = (int)info->ioport; |
| 3431 | tmp.irq = info->irq; | 3431 | tmp.irq = info->irq; |
| 3432 | tmp.flags = info->flags; | 3432 | tmp.flags = info->flags; |
| 3433 | tmp.baud_base = info->baud_base; | 3433 | tmp.baud_base = info->baud_base; |
| @@ -3557,14 +3557,14 @@ char *get_control_state_str(int MLines, char *s) | |||
| 3557 | } | 3557 | } |
| 3558 | #endif | 3558 | #endif |
| 3559 | 3559 | ||
| 3560 | static void | 3560 | static int |
| 3561 | rs_break(struct tty_struct *tty, int break_state) | 3561 | rs_break(struct tty_struct *tty, int break_state) |
| 3562 | { | 3562 | { |
| 3563 | struct e100_serial *info = (struct e100_serial *)tty->driver_data; | 3563 | struct e100_serial *info = (struct e100_serial *)tty->driver_data; |
| 3564 | unsigned long flags; | 3564 | unsigned long flags; |
| 3565 | 3565 | ||
| 3566 | if (!info->port) | 3566 | if (!info->ioport) |
| 3567 | return; | 3567 | return -EIO; |
| 3568 | 3568 | ||
| 3569 | local_irq_save(flags); | 3569 | local_irq_save(flags); |
| 3570 | if (break_state == -1) { | 3570 | if (break_state == -1) { |
| @@ -3575,8 +3575,9 @@ rs_break(struct tty_struct *tty, int break_state) | |||
| 3575 | /* Set bit 7 (txd) and 6 (tr_enable) */ | 3575 | /* Set bit 7 (txd) and 6 (tr_enable) */ |
| 3576 | info->tx_ctrl |= (0x80 | 0x40); | 3576 | info->tx_ctrl |= (0x80 | 0x40); |
| 3577 | } | 3577 | } |
| 3578 | info->port[REG_TR_CTRL] = info->tx_ctrl; | 3578 | info->ioport[REG_TR_CTRL] = info->tx_ctrl; |
| 3579 | local_irq_restore(flags); | 3579 | local_irq_restore(flags); |
| 3580 | return 0; | ||
| 3580 | } | 3581 | } |
| 3581 | 3582 | ||
| 3582 | static int | 3583 | static int |
| @@ -4231,9 +4232,9 @@ static int line_info(char *buf, struct e100_serial *info) | |||
| 4231 | unsigned long tmp; | 4232 | unsigned long tmp; |
| 4232 | 4233 | ||
| 4233 | ret = sprintf(buf, "%d: uart:E100 port:%lX irq:%d", | 4234 | ret = sprintf(buf, "%d: uart:E100 port:%lX irq:%d", |
| 4234 | info->line, (unsigned long)info->port, info->irq); | 4235 | info->line, (unsigned long)info->ioport, info->irq); |
| 4235 | 4236 | ||
| 4236 | if (!info->port || (info->type == PORT_UNKNOWN)) { | 4237 | if (!info->ioport || (info->type == PORT_UNKNOWN)) { |
| 4237 | ret += sprintf(buf+ret, "\n"); | 4238 | ret += sprintf(buf+ret, "\n"); |
| 4238 | return ret; | 4239 | return ret; |
| 4239 | } | 4240 | } |
| @@ -4281,7 +4282,7 @@ static int line_info(char *buf, struct e100_serial *info) | |||
| 4281 | } | 4282 | } |
| 4282 | 4283 | ||
| 4283 | { | 4284 | { |
| 4284 | unsigned char rstat = info->port[REG_STATUS]; | 4285 | unsigned char rstat = info->ioport[REG_STATUS]; |
| 4285 | if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect) ) | 4286 | if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect) ) |
| 4286 | ret += sprintf(buf+ret, " xoff_detect:1"); | 4287 | ret += sprintf(buf+ret, " xoff_detect:1"); |
| 4287 | } | 4288 | } |
| @@ -4502,7 +4503,7 @@ rs_init(void) | |||
| 4502 | 4503 | ||
| 4503 | if (info->enabled) { | 4504 | if (info->enabled) { |
| 4504 | printk(KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n", | 4505 | printk(KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n", |
| 4505 | serial_driver->name, info->line, (unsigned int)info->port); | 4506 | serial_driver->name, info->line, (unsigned int)info->ioport); |
| 4506 | } | 4507 | } |
| 4507 | } | 4508 | } |
| 4508 | #ifdef CONFIG_ETRAX_FAST_TIMER | 4509 | #ifdef CONFIG_ETRAX_FAST_TIMER |
diff --git a/drivers/serial/crisv10.h b/drivers/serial/crisv10.h index ccd0f32b7372..e3c5c8c3c09b 100644 --- a/drivers/serial/crisv10.h +++ b/drivers/serial/crisv10.h | |||
| @@ -36,8 +36,9 @@ struct etrax_recv_buffer { | |||
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| 38 | struct e100_serial { | 38 | struct e100_serial { |
| 39 | struct tty_port port; | ||
| 39 | int baud; | 40 | int baud; |
| 40 | volatile u8 *port; /* R_SERIALx_CTRL */ | 41 | volatile u8 *ioport; /* R_SERIALx_CTRL */ |
| 41 | u32 irq; /* bitnr in R_IRQ_MASK2 for dmaX_descr */ | 42 | u32 irq; /* bitnr in R_IRQ_MASK2 for dmaX_descr */ |
| 42 | 43 | ||
| 43 | /* Output registers */ | 44 | /* Output registers */ |
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index 0c7165660853..95190c619c10 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c | |||
| @@ -184,7 +184,8 @@ static void atmel_spi_next_xfer(struct spi_master *master, | |||
| 184 | { | 184 | { |
| 185 | struct atmel_spi *as = spi_master_get_devdata(master); | 185 | struct atmel_spi *as = spi_master_get_devdata(master); |
| 186 | struct spi_transfer *xfer; | 186 | struct spi_transfer *xfer; |
| 187 | u32 len, remaining, total; | 187 | u32 len, remaining; |
| 188 | u32 ieval; | ||
| 188 | dma_addr_t tx_dma, rx_dma; | 189 | dma_addr_t tx_dma, rx_dma; |
| 189 | 190 | ||
| 190 | if (!as->current_transfer) | 191 | if (!as->current_transfer) |
| @@ -197,6 +198,8 @@ static void atmel_spi_next_xfer(struct spi_master *master, | |||
| 197 | xfer = NULL; | 198 | xfer = NULL; |
| 198 | 199 | ||
| 199 | if (xfer) { | 200 | if (xfer) { |
| 201 | spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); | ||
| 202 | |||
| 200 | len = xfer->len; | 203 | len = xfer->len; |
| 201 | atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len); | 204 | atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len); |
| 202 | remaining = xfer->len - len; | 205 | remaining = xfer->len - len; |
| @@ -234,6 +237,8 @@ static void atmel_spi_next_xfer(struct spi_master *master, | |||
| 234 | as->next_transfer = xfer; | 237 | as->next_transfer = xfer; |
| 235 | 238 | ||
| 236 | if (xfer) { | 239 | if (xfer) { |
| 240 | u32 total; | ||
| 241 | |||
| 237 | total = len; | 242 | total = len; |
| 238 | atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len); | 243 | atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len); |
| 239 | as->next_remaining_bytes = total - len; | 244 | as->next_remaining_bytes = total - len; |
| @@ -250,9 +255,11 @@ static void atmel_spi_next_xfer(struct spi_master *master, | |||
| 250 | " next xfer %p: len %u tx %p/%08x rx %p/%08x\n", | 255 | " next xfer %p: len %u tx %p/%08x rx %p/%08x\n", |
| 251 | xfer, xfer->len, xfer->tx_buf, xfer->tx_dma, | 256 | xfer, xfer->len, xfer->tx_buf, xfer->tx_dma, |
| 252 | xfer->rx_buf, xfer->rx_dma); | 257 | xfer->rx_buf, xfer->rx_dma); |
| 258 | ieval = SPI_BIT(ENDRX) | SPI_BIT(OVRES); | ||
| 253 | } else { | 259 | } else { |
| 254 | spi_writel(as, RNCR, 0); | 260 | spi_writel(as, RNCR, 0); |
| 255 | spi_writel(as, TNCR, 0); | 261 | spi_writel(as, TNCR, 0); |
| 262 | ieval = SPI_BIT(RXBUFF) | SPI_BIT(ENDRX) | SPI_BIT(OVRES); | ||
| 256 | } | 263 | } |
| 257 | 264 | ||
| 258 | /* REVISIT: We're waiting for ENDRX before we start the next | 265 | /* REVISIT: We're waiting for ENDRX before we start the next |
| @@ -265,7 +272,7 @@ static void atmel_spi_next_xfer(struct spi_master *master, | |||
| 265 | * | 272 | * |
| 266 | * It should be doable, though. Just not now... | 273 | * It should be doable, though. Just not now... |
| 267 | */ | 274 | */ |
| 268 | spi_writel(as, IER, SPI_BIT(ENDRX) | SPI_BIT(OVRES)); | 275 | spi_writel(as, IER, ieval); |
| 269 | spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN)); | 276 | spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN)); |
| 270 | } | 277 | } |
| 271 | 278 | ||
| @@ -396,7 +403,7 @@ atmel_spi_interrupt(int irq, void *dev_id) | |||
| 396 | 403 | ||
| 397 | ret = IRQ_HANDLED; | 404 | ret = IRQ_HANDLED; |
| 398 | 405 | ||
| 399 | spi_writel(as, IDR, (SPI_BIT(ENDTX) | SPI_BIT(ENDRX) | 406 | spi_writel(as, IDR, (SPI_BIT(RXBUFF) | SPI_BIT(ENDRX) |
| 400 | | SPI_BIT(OVRES))); | 407 | | SPI_BIT(OVRES))); |
| 401 | 408 | ||
| 402 | /* | 409 | /* |
| @@ -418,7 +425,7 @@ atmel_spi_interrupt(int irq, void *dev_id) | |||
| 418 | if (xfer->delay_usecs) | 425 | if (xfer->delay_usecs) |
| 419 | udelay(xfer->delay_usecs); | 426 | udelay(xfer->delay_usecs); |
| 420 | 427 | ||
| 421 | dev_warn(master->dev.parent, "fifo overrun (%u/%u remaining)\n", | 428 | dev_warn(master->dev.parent, "overrun (%u/%u remaining)\n", |
| 422 | spi_readl(as, TCR), spi_readl(as, RCR)); | 429 | spi_readl(as, TCR), spi_readl(as, RCR)); |
| 423 | 430 | ||
| 424 | /* | 431 | /* |
| @@ -442,7 +449,7 @@ atmel_spi_interrupt(int irq, void *dev_id) | |||
| 442 | spi_readl(as, SR); | 449 | spi_readl(as, SR); |
| 443 | 450 | ||
| 444 | atmel_spi_msg_done(master, as, msg, -EIO, 0); | 451 | atmel_spi_msg_done(master, as, msg, -EIO, 0); |
| 445 | } else if (pending & SPI_BIT(ENDRX)) { | 452 | } else if (pending & (SPI_BIT(RXBUFF) | SPI_BIT(ENDRX))) { |
| 446 | ret = IRQ_HANDLED; | 453 | ret = IRQ_HANDLED; |
| 447 | 454 | ||
| 448 | spi_writel(as, IDR, pending); | 455 | spi_writel(as, IDR, pending); |
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c index 1c643c9e1f15..21661c7959c8 100644 --- a/drivers/spi/spi_s3c24xx.c +++ b/drivers/spi/spi_s3c24xx.c | |||
| @@ -236,6 +236,19 @@ static irqreturn_t s3c24xx_spi_irq(int irq, void *dev) | |||
| 236 | return IRQ_HANDLED; | 236 | return IRQ_HANDLED; |
| 237 | } | 237 | } |
| 238 | 238 | ||
| 239 | static void s3c24xx_spi_initialsetup(struct s3c24xx_spi *hw) | ||
| 240 | { | ||
| 241 | /* for the moment, permanently enable the clock */ | ||
| 242 | |||
| 243 | clk_enable(hw->clk); | ||
| 244 | |||
| 245 | /* program defaults into the registers */ | ||
| 246 | |||
| 247 | writeb(0xff, hw->regs + S3C2410_SPPRE); | ||
| 248 | writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN); | ||
| 249 | writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON); | ||
| 250 | } | ||
| 251 | |||
| 239 | static int __init s3c24xx_spi_probe(struct platform_device *pdev) | 252 | static int __init s3c24xx_spi_probe(struct platform_device *pdev) |
| 240 | { | 253 | { |
| 241 | struct s3c2410_spi_info *pdata; | 254 | struct s3c2410_spi_info *pdata; |
| @@ -327,15 +340,7 @@ static int __init s3c24xx_spi_probe(struct platform_device *pdev) | |||
| 327 | goto err_no_clk; | 340 | goto err_no_clk; |
| 328 | } | 341 | } |
| 329 | 342 | ||
| 330 | /* for the moment, permanently enable the clock */ | 343 | s3c24xx_spi_initialsetup(hw); |
| 331 | |||
| 332 | clk_enable(hw->clk); | ||
| 333 | |||
| 334 | /* program defaults into the registers */ | ||
| 335 | |||
| 336 | writeb(0xff, hw->regs + S3C2410_SPPRE); | ||
| 337 | writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN); | ||
| 338 | writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON); | ||
| 339 | 344 | ||
| 340 | /* setup any gpio we can */ | 345 | /* setup any gpio we can */ |
| 341 | 346 | ||
| @@ -415,7 +420,7 @@ static int s3c24xx_spi_resume(struct platform_device *pdev) | |||
| 415 | { | 420 | { |
| 416 | struct s3c24xx_spi *hw = platform_get_drvdata(pdev); | 421 | struct s3c24xx_spi *hw = platform_get_drvdata(pdev); |
| 417 | 422 | ||
| 418 | clk_enable(hw->clk); | 423 | s3c24xx_spi_initialsetup(hw); |
| 419 | return 0; | 424 | return 0; |
| 420 | } | 425 | } |
| 421 | 426 | ||
diff --git a/drivers/video/console/.gitignore b/drivers/video/console/.gitignore new file mode 100644 index 000000000000..0c258b45439c --- /dev/null +++ b/drivers/video/console/.gitignore | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | # conmakehash generated file | ||
| 2 | promcon_tbl.c | ||
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c index 2eb48c0df32c..ef7b0d67095e 100644 --- a/drivers/watchdog/ar7_wdt.c +++ b/drivers/watchdog/ar7_wdt.c | |||
| @@ -69,7 +69,8 @@ struct ar7_wdt { | |||
| 69 | u32 prescale; | 69 | u32 prescale; |
| 70 | }; | 70 | }; |
| 71 | 71 | ||
| 72 | static struct semaphore open_semaphore; | 72 | static unsigned long wdt_is_open; |
| 73 | static spinlock_t wdt_lock; | ||
| 73 | static unsigned expect_close; | 74 | static unsigned expect_close; |
| 74 | 75 | ||
| 75 | /* XXX currently fixed, allows max margin ~68.72 secs */ | 76 | /* XXX currently fixed, allows max margin ~68.72 secs */ |
| @@ -154,8 +155,10 @@ static void ar7_wdt_update_margin(int new_margin) | |||
| 154 | u32 change; | 155 | u32 change; |
| 155 | 156 | ||
| 156 | change = new_margin * (ar7_vbus_freq() / prescale_value); | 157 | change = new_margin * (ar7_vbus_freq() / prescale_value); |
| 157 | if (change < 1) change = 1; | 158 | if (change < 1) |
| 158 | if (change > 0xffff) change = 0xffff; | 159 | change = 1; |
| 160 | if (change > 0xffff) | ||
| 161 | change = 0xffff; | ||
| 159 | ar7_wdt_change(change); | 162 | ar7_wdt_change(change); |
| 160 | margin = change * prescale_value / ar7_vbus_freq(); | 163 | margin = change * prescale_value / ar7_vbus_freq(); |
| 161 | printk(KERN_INFO DRVNAME | 164 | printk(KERN_INFO DRVNAME |
| @@ -179,7 +182,7 @@ static void ar7_wdt_disable_wdt(void) | |||
| 179 | static int ar7_wdt_open(struct inode *inode, struct file *file) | 182 | static int ar7_wdt_open(struct inode *inode, struct file *file) |
| 180 | { | 183 | { |
| 181 | /* only allow one at a time */ | 184 | /* only allow one at a time */ |
| 182 | if (down_trylock(&open_semaphore)) | 185 | if (test_and_set_bit(0, &wdt_is_open)) |
| 183 | return -EBUSY; | 186 | return -EBUSY; |
| 184 | ar7_wdt_enable_wdt(); | 187 | ar7_wdt_enable_wdt(); |
| 185 | expect_close = 0; | 188 | expect_close = 0; |
| @@ -195,9 +198,7 @@ static int ar7_wdt_release(struct inode *inode, struct file *file) | |||
| 195 | "will not disable the watchdog timer\n"); | 198 | "will not disable the watchdog timer\n"); |
| 196 | else if (!nowayout) | 199 | else if (!nowayout) |
| 197 | ar7_wdt_disable_wdt(); | 200 | ar7_wdt_disable_wdt(); |
| 198 | 201 | clear_bit(0, &wdt_is_open); | |
| 199 | up(&open_semaphore); | ||
| 200 | |||
| 201 | return 0; | 202 | return 0; |
| 202 | } | 203 | } |
| 203 | 204 | ||
| @@ -222,7 +223,9 @@ static ssize_t ar7_wdt_write(struct file *file, const char *data, | |||
| 222 | if (len) { | 223 | if (len) { |
| 223 | size_t i; | 224 | size_t i; |
| 224 | 225 | ||
| 226 | spin_lock(&wdt_lock); | ||
| 225 | ar7_wdt_kick(1); | 227 | ar7_wdt_kick(1); |
| 228 | spin_unlock(&wdt_lock); | ||
| 226 | 229 | ||
| 227 | expect_close = 0; | 230 | expect_close = 0; |
| 228 | for (i = 0; i < len; ++i) { | 231 | for (i = 0; i < len; ++i) { |
| @@ -237,8 +240,8 @@ static ssize_t ar7_wdt_write(struct file *file, const char *data, | |||
| 237 | return len; | 240 | return len; |
| 238 | } | 241 | } |
| 239 | 242 | ||
| 240 | static int ar7_wdt_ioctl(struct inode *inode, struct file *file, | 243 | static long ar7_wdt_ioctl(struct file *file, |
| 241 | unsigned int cmd, unsigned long arg) | 244 | unsigned int cmd, unsigned long arg) |
| 242 | { | 245 | { |
| 243 | static struct watchdog_info ident = { | 246 | static struct watchdog_info ident = { |
| 244 | .identity = LONGNAME, | 247 | .identity = LONGNAME, |
| @@ -269,8 +272,10 @@ static int ar7_wdt_ioctl(struct inode *inode, struct file *file, | |||
| 269 | if (new_margin < 1) | 272 | if (new_margin < 1) |
| 270 | return -EINVAL; | 273 | return -EINVAL; |
| 271 | 274 | ||
| 275 | spin_lock(&wdt_lock); | ||
| 272 | ar7_wdt_update_margin(new_margin); | 276 | ar7_wdt_update_margin(new_margin); |
| 273 | ar7_wdt_kick(1); | 277 | ar7_wdt_kick(1); |
| 278 | spin_unlock(&wdt_lock); | ||
| 274 | 279 | ||
| 275 | case WDIOC_GETTIMEOUT: | 280 | case WDIOC_GETTIMEOUT: |
| 276 | if (put_user(margin, (int *)arg)) | 281 | if (put_user(margin, (int *)arg)) |
| @@ -282,7 +287,7 @@ static int ar7_wdt_ioctl(struct inode *inode, struct file *file, | |||
| 282 | static const struct file_operations ar7_wdt_fops = { | 287 | static const struct file_operations ar7_wdt_fops = { |
| 283 | .owner = THIS_MODULE, | 288 | .owner = THIS_MODULE, |
| 284 | .write = ar7_wdt_write, | 289 | .write = ar7_wdt_write, |
| 285 | .ioctl = ar7_wdt_ioctl, | 290 | .unlocked_ioctl = ar7_wdt_ioctl, |
| 286 | .open = ar7_wdt_open, | 291 | .open = ar7_wdt_open, |
| 287 | .release = ar7_wdt_release, | 292 | .release = ar7_wdt_release, |
| 288 | }; | 293 | }; |
| @@ -297,6 +302,8 @@ static int __init ar7_wdt_init(void) | |||
| 297 | { | 302 | { |
| 298 | int rc; | 303 | int rc; |
| 299 | 304 | ||
| 305 | spin_lock_init(&wdt_lock); | ||
| 306 | |||
| 300 | ar7_wdt_get_regs(); | 307 | ar7_wdt_get_regs(); |
| 301 | 308 | ||
| 302 | if (!request_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt), | 309 | if (!request_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt), |
| @@ -312,8 +319,6 @@ static int __init ar7_wdt_init(void) | |||
| 312 | ar7_wdt_prescale(prescale_value); | 319 | ar7_wdt_prescale(prescale_value); |
| 313 | ar7_wdt_update_margin(margin); | 320 | ar7_wdt_update_margin(margin); |
| 314 | 321 | ||
| 315 | sema_init(&open_semaphore, 1); | ||
| 316 | |||
| 317 | rc = register_reboot_notifier(&ar7_wdt_notifier); | 322 | rc = register_reboot_notifier(&ar7_wdt_notifier); |
| 318 | if (rc) { | 323 | if (rc) { |
| 319 | printk(KERN_ERR DRVNAME | 324 | printk(KERN_ERR DRVNAME |
diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c index 445b7e812112..51bfd5721833 100644 --- a/drivers/watchdog/it8712f_wdt.c +++ b/drivers/watchdog/it8712f_wdt.c | |||
| @@ -30,9 +30,8 @@ | |||
| 30 | #include <linux/fs.h> | 30 | #include <linux/fs.h> |
| 31 | #include <linux/pci.h> | 31 | #include <linux/pci.h> |
| 32 | #include <linux/spinlock.h> | 32 | #include <linux/spinlock.h> |
| 33 | 33 | #include <linux/uaccess.h> | |
| 34 | #include <asm/uaccess.h> | 34 | #include <linux/io.h> |
| 35 | #include <asm/io.h> | ||
| 36 | 35 | ||
| 37 | #define NAME "it8712f_wdt" | 36 | #define NAME "it8712f_wdt" |
| 38 | 37 | ||
| @@ -50,7 +49,7 @@ static int nowayout = WATCHDOG_NOWAYOUT; | |||
| 50 | module_param(nowayout, int, 0); | 49 | module_param(nowayout, int, 0); |
| 51 | MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); | 50 | MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); |
| 52 | 51 | ||
| 53 | static struct semaphore it8712f_wdt_sem; | 52 | static unsigned long wdt_open; |
| 54 | static unsigned expect_close; | 53 | static unsigned expect_close; |
| 55 | static spinlock_t io_lock; | 54 | static spinlock_t io_lock; |
| 56 | static unsigned char revision; | 55 | static unsigned char revision; |
| @@ -86,22 +85,19 @@ static unsigned short address; | |||
| 86 | #define WDT_OUT_PWROK 0x10 | 85 | #define WDT_OUT_PWROK 0x10 |
| 87 | #define WDT_OUT_KRST 0x40 | 86 | #define WDT_OUT_KRST 0x40 |
| 88 | 87 | ||
| 89 | static int | 88 | static int superio_inb(int reg) |
| 90 | superio_inb(int reg) | ||
| 91 | { | 89 | { |
| 92 | outb(reg, REG); | 90 | outb(reg, REG); |
| 93 | return inb(VAL); | 91 | return inb(VAL); |
| 94 | } | 92 | } |
| 95 | 93 | ||
| 96 | static void | 94 | static void superio_outb(int val, int reg) |
| 97 | superio_outb(int val, int reg) | ||
| 98 | { | 95 | { |
| 99 | outb(reg, REG); | 96 | outb(reg, REG); |
| 100 | outb(val, VAL); | 97 | outb(val, VAL); |
| 101 | } | 98 | } |
| 102 | 99 | ||
| 103 | static int | 100 | static int superio_inw(int reg) |
| 104 | superio_inw(int reg) | ||
| 105 | { | 101 | { |
| 106 | int val; | 102 | int val; |
| 107 | outb(reg++, REG); | 103 | outb(reg++, REG); |
| @@ -111,15 +107,13 @@ superio_inw(int reg) | |||
| 111 | return val; | 107 | return val; |
| 112 | } | 108 | } |
| 113 | 109 | ||
| 114 | static inline void | 110 | static inline void superio_select(int ldn) |
| 115 | superio_select(int ldn) | ||
| 116 | { | 111 | { |
| 117 | outb(LDN, REG); | 112 | outb(LDN, REG); |
| 118 | outb(ldn, VAL); | 113 | outb(ldn, VAL); |
| 119 | } | 114 | } |
| 120 | 115 | ||
| 121 | static inline void | 116 | static inline void superio_enter(void) |
| 122 | superio_enter(void) | ||
| 123 | { | 117 | { |
| 124 | spin_lock(&io_lock); | 118 | spin_lock(&io_lock); |
| 125 | outb(0x87, REG); | 119 | outb(0x87, REG); |
| @@ -128,22 +122,19 @@ superio_enter(void) | |||
| 128 | outb(0x55, REG); | 122 | outb(0x55, REG); |
| 129 | } | 123 | } |
| 130 | 124 | ||
| 131 | static inline void | 125 | static inline void superio_exit(void) |
| 132 | superio_exit(void) | ||
| 133 | { | 126 | { |
| 134 | outb(0x02, REG); | 127 | outb(0x02, REG); |
| 135 | outb(0x02, VAL); | 128 | outb(0x02, VAL); |
| 136 | spin_unlock(&io_lock); | 129 | spin_unlock(&io_lock); |
| 137 | } | 130 | } |
| 138 | 131 | ||
| 139 | static inline void | 132 | static inline void it8712f_wdt_ping(void) |
| 140 | it8712f_wdt_ping(void) | ||
| 141 | { | 133 | { |
| 142 | inb(address); | 134 | inb(address); |
| 143 | } | 135 | } |
| 144 | 136 | ||
| 145 | static void | 137 | static void it8712f_wdt_update_margin(void) |
| 146 | it8712f_wdt_update_margin(void) | ||
| 147 | { | 138 | { |
| 148 | int config = WDT_OUT_KRST | WDT_OUT_PWROK; | 139 | int config = WDT_OUT_KRST | WDT_OUT_PWROK; |
| 149 | int units = margin; | 140 | int units = margin; |
| @@ -165,8 +156,7 @@ it8712f_wdt_update_margin(void) | |||
| 165 | superio_outb(units, WDT_TIMEOUT); | 156 | superio_outb(units, WDT_TIMEOUT); |
| 166 | } | 157 | } |
| 167 | 158 | ||
| 168 | static int | 159 | static int it8712f_wdt_get_status(void) |
| 169 | it8712f_wdt_get_status(void) | ||
| 170 | { | 160 | { |
| 171 | if (superio_inb(WDT_CONTROL) & 0x01) | 161 | if (superio_inb(WDT_CONTROL) & 0x01) |
| 172 | return WDIOF_CARDRESET; | 162 | return WDIOF_CARDRESET; |
| @@ -174,8 +164,7 @@ it8712f_wdt_get_status(void) | |||
| 174 | return 0; | 164 | return 0; |
| 175 | } | 165 | } |
| 176 | 166 | ||
| 177 | static void | 167 | static void it8712f_wdt_enable(void) |
| 178 | it8712f_wdt_enable(void) | ||
| 179 | { | 168 | { |
| 180 | printk(KERN_DEBUG NAME ": enabling watchdog timer\n"); | 169 | printk(KERN_DEBUG NAME ": enabling watchdog timer\n"); |
| 181 | superio_enter(); | 170 | superio_enter(); |
| @@ -190,8 +179,7 @@ it8712f_wdt_enable(void) | |||
| 190 | it8712f_wdt_ping(); | 179 | it8712f_wdt_ping(); |
| 191 | } | 180 | } |
| 192 | 181 | ||
| 193 | static void | 182 | static void it8712f_wdt_disable(void) |
| 194 | it8712f_wdt_disable(void) | ||
| 195 | { | 183 | { |
| 196 | printk(KERN_DEBUG NAME ": disabling watchdog timer\n"); | 184 | printk(KERN_DEBUG NAME ": disabling watchdog timer\n"); |
| 197 | 185 | ||
| @@ -207,8 +195,7 @@ it8712f_wdt_disable(void) | |||
| 207 | superio_exit(); | 195 | superio_exit(); |
| 208 | } | 196 | } |
| 209 | 197 | ||
| 210 | static int | 198 | static int it8712f_wdt_notify(struct notifier_block *this, |
| 211 | it8712f_wdt_notify(struct notifier_block *this, | ||
| 212 | unsigned long code, void *unused) | 199 | unsigned long code, void *unused) |
| 213 | { | 200 | { |
| 214 | if (code == SYS_HALT || code == SYS_POWER_OFF) | 201 | if (code == SYS_HALT || code == SYS_POWER_OFF) |
| @@ -222,9 +209,8 @@ static struct notifier_block it8712f_wdt_notifier = { | |||
| 222 | .notifier_call = it8712f_wdt_notify, | 209 | .notifier_call = it8712f_wdt_notify, |
| 223 | }; | 210 | }; |
| 224 | 211 | ||
| 225 | static ssize_t | 212 | static ssize_t it8712f_wdt_write(struct file *file, const char __user *data, |
| 226 | it8712f_wdt_write(struct file *file, const char __user *data, | 213 | size_t len, loff_t *ppos) |
| 227 | size_t len, loff_t *ppos) | ||
| 228 | { | 214 | { |
| 229 | /* check for a magic close character */ | 215 | /* check for a magic close character */ |
| 230 | if (len) { | 216 | if (len) { |
| @@ -245,9 +231,8 @@ it8712f_wdt_write(struct file *file, const char __user *data, | |||
| 245 | return len; | 231 | return len; |
| 246 | } | 232 | } |
| 247 | 233 | ||
| 248 | static int | 234 | static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd, |
| 249 | it8712f_wdt_ioctl(struct inode *inode, struct file *file, | 235 | unsigned long arg) |
| 250 | unsigned int cmd, unsigned long arg) | ||
| 251 | { | 236 | { |
| 252 | void __user *argp = (void __user *)arg; | 237 | void __user *argp = (void __user *)arg; |
| 253 | int __user *p = argp; | 238 | int __user *p = argp; |
| @@ -302,19 +287,16 @@ it8712f_wdt_ioctl(struct inode *inode, struct file *file, | |||
| 302 | } | 287 | } |
| 303 | } | 288 | } |
| 304 | 289 | ||
| 305 | static int | 290 | static int it8712f_wdt_open(struct inode *inode, struct file *file) |
| 306 | it8712f_wdt_open(struct inode *inode, struct file *file) | ||
| 307 | { | 291 | { |
| 308 | /* only allow one at a time */ | 292 | /* only allow one at a time */ |
| 309 | if (down_trylock(&it8712f_wdt_sem)) | 293 | if (test_and_set_bit(0, &wdt_open)) |
| 310 | return -EBUSY; | 294 | return -EBUSY; |
| 311 | it8712f_wdt_enable(); | 295 | it8712f_wdt_enable(); |
| 312 | |||
| 313 | return nonseekable_open(inode, file); | 296 | return nonseekable_open(inode, file); |
| 314 | } | 297 | } |
| 315 | 298 | ||
| 316 | static int | 299 | static int it8712f_wdt_release(struct inode *inode, struct file *file) |
| 317 | it8712f_wdt_release(struct inode *inode, struct file *file) | ||
| 318 | { | 300 | { |
| 319 | if (expect_close != 42) { | 301 | if (expect_close != 42) { |
| 320 | printk(KERN_WARNING NAME | 302 | printk(KERN_WARNING NAME |
| @@ -324,7 +306,7 @@ it8712f_wdt_release(struct inode *inode, struct file *file) | |||
| 324 | it8712f_wdt_disable(); | 306 | it8712f_wdt_disable(); |
| 325 | } | 307 | } |
| 326 | expect_close = 0; | 308 | expect_close = 0; |
| 327 | up(&it8712f_wdt_sem); | 309 | clear_bit(0, &wdt_open); |
| 328 | 310 | ||
| 329 | return 0; | 311 | return 0; |
| 330 | } | 312 | } |
| @@ -333,7 +315,7 @@ static const struct file_operations it8712f_wdt_fops = { | |||
| 333 | .owner = THIS_MODULE, | 315 | .owner = THIS_MODULE, |
| 334 | .llseek = no_llseek, | 316 | .llseek = no_llseek, |
| 335 | .write = it8712f_wdt_write, | 317 | .write = it8712f_wdt_write, |
| 336 | .ioctl = it8712f_wdt_ioctl, | 318 | .unlocked_ioctl = it8712f_wdt_ioctl, |
| 337 | .open = it8712f_wdt_open, | 319 | .open = it8712f_wdt_open, |
| 338 | .release = it8712f_wdt_release, | 320 | .release = it8712f_wdt_release, |
| 339 | }; | 321 | }; |
| @@ -344,8 +326,7 @@ static struct miscdevice it8712f_wdt_miscdev = { | |||
| 344 | .fops = &it8712f_wdt_fops, | 326 | .fops = &it8712f_wdt_fops, |
| 345 | }; | 327 | }; |
| 346 | 328 | ||
| 347 | static int __init | 329 | static int __init it8712f_wdt_find(unsigned short *address) |
| 348 | it8712f_wdt_find(unsigned short *address) | ||
| 349 | { | 330 | { |
| 350 | int err = -ENODEV; | 331 | int err = -ENODEV; |
| 351 | int chip_type; | 332 | int chip_type; |
| @@ -387,8 +368,7 @@ exit: | |||
| 387 | return err; | 368 | return err; |
| 388 | } | 369 | } |
| 389 | 370 | ||
| 390 | static int __init | 371 | static int __init it8712f_wdt_init(void) |
| 391 | it8712f_wdt_init(void) | ||
| 392 | { | 372 | { |
| 393 | int err = 0; | 373 | int err = 0; |
| 394 | 374 | ||
| @@ -404,8 +384,6 @@ it8712f_wdt_init(void) | |||
| 404 | 384 | ||
| 405 | it8712f_wdt_disable(); | 385 | it8712f_wdt_disable(); |
| 406 | 386 | ||
| 407 | sema_init(&it8712f_wdt_sem, 1); | ||
| 408 | |||
| 409 | err = register_reboot_notifier(&it8712f_wdt_notifier); | 387 | err = register_reboot_notifier(&it8712f_wdt_notifier); |
| 410 | if (err) { | 388 | if (err) { |
| 411 | printk(KERN_ERR NAME ": unable to register reboot notifier\n"); | 389 | printk(KERN_ERR NAME ": unable to register reboot notifier\n"); |
| @@ -430,8 +408,7 @@ out: | |||
| 430 | return err; | 408 | return err; |
| 431 | } | 409 | } |
| 432 | 410 | ||
| 433 | static void __exit | 411 | static void __exit it8712f_wdt_exit(void) |
| 434 | it8712f_wdt_exit(void) | ||
| 435 | { | 412 | { |
| 436 | misc_deregister(&it8712f_wdt_miscdev); | 413 | misc_deregister(&it8712f_wdt_miscdev); |
| 437 | unregister_reboot_notifier(&it8712f_wdt_notifier); | 414 | unregister_reboot_notifier(&it8712f_wdt_notifier); |
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 98532c0e0689..97b4a2e8eb09 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c | |||
| @@ -46,9 +46,8 @@ | |||
| 46 | #include <linux/platform_device.h> | 46 | #include <linux/platform_device.h> |
| 47 | #include <linux/interrupt.h> | 47 | #include <linux/interrupt.h> |
| 48 | #include <linux/clk.h> | 48 | #include <linux/clk.h> |
| 49 | 49 | #include <linux/uaccess.h> | |
| 50 | #include <asm/uaccess.h> | 50 | #include <linux/io.h> |
| 51 | #include <asm/io.h> | ||
| 52 | 51 | ||
| 53 | #include <asm/arch/map.h> | 52 | #include <asm/arch/map.h> |
| 54 | 53 | ||
| @@ -65,8 +64,8 @@ | |||
| 65 | static int nowayout = WATCHDOG_NOWAYOUT; | 64 | static int nowayout = WATCHDOG_NOWAYOUT; |
| 66 | static int tmr_margin = CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME; | 65 | static int tmr_margin = CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME; |
| 67 | static int tmr_atboot = CONFIG_S3C2410_WATCHDOG_ATBOOT; | 66 | static int tmr_atboot = CONFIG_S3C2410_WATCHDOG_ATBOOT; |
| 68 | static int soft_noboot = 0; | 67 | static int soft_noboot; |
| 69 | static int debug = 0; | 68 | static int debug; |
| 70 | 69 | ||
| 71 | module_param(tmr_margin, int, 0); | 70 | module_param(tmr_margin, int, 0); |
| 72 | module_param(tmr_atboot, int, 0); | 71 | module_param(tmr_atboot, int, 0); |
| @@ -74,24 +73,23 @@ module_param(nowayout, int, 0); | |||
| 74 | module_param(soft_noboot, int, 0); | 73 | module_param(soft_noboot, int, 0); |
| 75 | module_param(debug, int, 0); | 74 | module_param(debug, int, 0); |
| 76 | 75 | ||
| 77 | MODULE_PARM_DESC(tmr_margin, "Watchdog tmr_margin in seconds. default=" __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME) ")"); | 76 | MODULE_PARM_DESC(tmr_margin, "Watchdog tmr_margin in seconds. default=" |
| 78 | 77 | __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME) ")"); | |
| 79 | MODULE_PARM_DESC(tmr_atboot, "Watchdog is started at boot time if set to 1, default=" __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_ATBOOT)); | 78 | MODULE_PARM_DESC(tmr_atboot, |
| 80 | 79 | "Watchdog is started at boot time if set to 1, default=" | |
| 81 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 80 | __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_ATBOOT)); |
| 82 | 81 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" | |
| 82 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
| 83 | MODULE_PARM_DESC(soft_noboot, "Watchdog action, set to 1 to ignore reboots, 0 to reboot (default depends on ONLY_TESTING)"); | 83 | MODULE_PARM_DESC(soft_noboot, "Watchdog action, set to 1 to ignore reboots, 0 to reboot (default depends on ONLY_TESTING)"); |
| 84 | |||
| 85 | MODULE_PARM_DESC(debug, "Watchdog debug, set to >1 for debug, (default 0)"); | 84 | MODULE_PARM_DESC(debug, "Watchdog debug, set to >1 for debug, (default 0)"); |
| 86 | 85 | ||
| 87 | 86 | ||
| 88 | typedef enum close_state { | 87 | typedef enum close_state { |
| 89 | CLOSE_STATE_NOT, | 88 | CLOSE_STATE_NOT, |
| 90 | CLOSE_STATE_ALLOW=0x4021 | 89 | CLOSE_STATE_ALLOW = 0x4021 |
| 91 | } close_state_t; | 90 | } close_state_t; |
| 92 | 91 | ||
| 93 | static DECLARE_MUTEX(open_lock); | 92 | static unsigned long open_lock; |
| 94 | |||
| 95 | static struct device *wdt_dev; /* platform device attached to */ | 93 | static struct device *wdt_dev; /* platform device attached to */ |
| 96 | static struct resource *wdt_mem; | 94 | static struct resource *wdt_mem; |
| 97 | static struct resource *wdt_irq; | 95 | static struct resource *wdt_irq; |
| @@ -99,38 +97,58 @@ static struct clk *wdt_clock; | |||
| 99 | static void __iomem *wdt_base; | 97 | static void __iomem *wdt_base; |
| 100 | static unsigned int wdt_count; | 98 | static unsigned int wdt_count; |
| 101 | static close_state_t allow_close; | 99 | static close_state_t allow_close; |
| 100 | static DEFINE_SPINLOCK(wdt_lock); | ||
| 102 | 101 | ||
| 103 | /* watchdog control routines */ | 102 | /* watchdog control routines */ |
| 104 | 103 | ||
| 105 | #define DBG(msg...) do { \ | 104 | #define DBG(msg...) do { \ |
| 106 | if (debug) \ | 105 | if (debug) \ |
| 107 | printk(KERN_INFO msg); \ | 106 | printk(KERN_INFO msg); \ |
| 108 | } while(0) | 107 | } while (0) |
| 109 | 108 | ||
| 110 | /* functions */ | 109 | /* functions */ |
| 111 | 110 | ||
| 112 | static int s3c2410wdt_keepalive(void) | 111 | static void s3c2410wdt_keepalive(void) |
| 113 | { | 112 | { |
| 113 | spin_lock(&wdt_lock); | ||
| 114 | writel(wdt_count, wdt_base + S3C2410_WTCNT); | 114 | writel(wdt_count, wdt_base + S3C2410_WTCNT); |
| 115 | return 0; | 115 | spin_unlock(&wdt_lock); |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | static int s3c2410wdt_stop(void) | 118 | static void __s3c2410wdt_stop(void) |
| 119 | { | 119 | { |
| 120 | unsigned long wtcon; | 120 | unsigned long wtcon; |
| 121 | 121 | ||
| 122 | spin_lock(&wdt_lock); | ||
| 122 | wtcon = readl(wdt_base + S3C2410_WTCON); | 123 | wtcon = readl(wdt_base + S3C2410_WTCON); |
| 123 | wtcon &= ~(S3C2410_WTCON_ENABLE | S3C2410_WTCON_RSTEN); | 124 | wtcon &= ~(S3C2410_WTCON_ENABLE | S3C2410_WTCON_RSTEN); |
| 124 | writel(wtcon, wdt_base + S3C2410_WTCON); | 125 | writel(wtcon, wdt_base + S3C2410_WTCON); |
| 126 | spin_unlock(&wdt_lock); | ||
| 127 | } | ||
| 125 | 128 | ||
| 126 | return 0; | 129 | static void __s3c2410wdt_stop(void) |
| 130 | { | ||
| 131 | unsigned long wtcon; | ||
| 132 | |||
| 133 | wtcon = readl(wdt_base + S3C2410_WTCON); | ||
| 134 | wtcon &= ~(S3C2410_WTCON_ENABLE | S3C2410_WTCON_RSTEN); | ||
| 135 | writel(wtcon, wdt_base + S3C2410_WTCON); | ||
| 136 | } | ||
| 137 | |||
| 138 | static void s3c2410wdt_stop(void) | ||
| 139 | { | ||
| 140 | spin_lock(&wdt_lock); | ||
| 141 | __s3c2410wdt_stop(); | ||
| 142 | spin_unlock(&wdt_lock); | ||
| 127 | } | 143 | } |
| 128 | 144 | ||
| 129 | static int s3c2410wdt_start(void) | 145 | static void s3c2410wdt_start(void) |
| 130 | { | 146 | { |
| 131 | unsigned long wtcon; | 147 | unsigned long wtcon; |
| 132 | 148 | ||
| 133 | s3c2410wdt_stop(); | 149 | spin_lock(&wdt_lock); |
| 150 | |||
| 151 | __s3c2410wdt_stop(); | ||
| 134 | 152 | ||
| 135 | wtcon = readl(wdt_base + S3C2410_WTCON); | 153 | wtcon = readl(wdt_base + S3C2410_WTCON); |
| 136 | wtcon |= S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128; | 154 | wtcon |= S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128; |
| @@ -149,6 +167,7 @@ static int s3c2410wdt_start(void) | |||
| 149 | writel(wdt_count, wdt_base + S3C2410_WTDAT); | 167 | writel(wdt_count, wdt_base + S3C2410_WTDAT); |
| 150 | writel(wdt_count, wdt_base + S3C2410_WTCNT); | 168 | writel(wdt_count, wdt_base + S3C2410_WTCNT); |
| 151 | writel(wtcon, wdt_base + S3C2410_WTCON); | 169 | writel(wtcon, wdt_base + S3C2410_WTCON); |
| 170 | spin_unlock(&wdt_lock); | ||
| 152 | 171 | ||
| 153 | return 0; | 172 | return 0; |
| 154 | } | 173 | } |
| @@ -211,7 +230,7 @@ static int s3c2410wdt_set_heartbeat(int timeout) | |||
| 211 | 230 | ||
| 212 | static int s3c2410wdt_open(struct inode *inode, struct file *file) | 231 | static int s3c2410wdt_open(struct inode *inode, struct file *file) |
| 213 | { | 232 | { |
| 214 | if(down_trylock(&open_lock)) | 233 | if (test_and_set_bit(0, &open_lock)) |
| 215 | return -EBUSY; | 234 | return -EBUSY; |
| 216 | 235 | ||
| 217 | if (nowayout) | 236 | if (nowayout) |
| @@ -231,15 +250,14 @@ static int s3c2410wdt_release(struct inode *inode, struct file *file) | |||
| 231 | * Lock it in if it's a module and we set nowayout | 250 | * Lock it in if it's a module and we set nowayout |
| 232 | */ | 251 | */ |
| 233 | 252 | ||
| 234 | if (allow_close == CLOSE_STATE_ALLOW) { | 253 | if (allow_close == CLOSE_STATE_ALLOW) |
| 235 | s3c2410wdt_stop(); | 254 | s3c2410wdt_stop(); |
| 236 | } else { | 255 | else { |
| 237 | dev_err(wdt_dev, "Unexpected close, not stopping watchdog\n"); | 256 | dev_err(wdt_dev, "Unexpected close, not stopping watchdog\n"); |
| 238 | s3c2410wdt_keepalive(); | 257 | s3c2410wdt_keepalive(); |
| 239 | } | 258 | } |
| 240 | |||
| 241 | allow_close = CLOSE_STATE_NOT; | 259 | allow_close = CLOSE_STATE_NOT; |
| 242 | up(&open_lock); | 260 | clear_bit(0, &open_lock); |
| 243 | return 0; | 261 | return 0; |
| 244 | } | 262 | } |
| 245 | 263 | ||
| @@ -249,7 +267,7 @@ static ssize_t s3c2410wdt_write(struct file *file, const char __user *data, | |||
| 249 | /* | 267 | /* |
| 250 | * Refresh the timer. | 268 | * Refresh the timer. |
| 251 | */ | 269 | */ |
| 252 | if(len) { | 270 | if (len) { |
| 253 | if (!nowayout) { | 271 | if (!nowayout) { |
| 254 | size_t i; | 272 | size_t i; |
| 255 | 273 | ||
| @@ -265,7 +283,6 @@ static ssize_t s3c2410wdt_write(struct file *file, const char __user *data, | |||
| 265 | allow_close = CLOSE_STATE_ALLOW; | 283 | allow_close = CLOSE_STATE_ALLOW; |
| 266 | } | 284 | } |
| 267 | } | 285 | } |
| 268 | |||
| 269 | s3c2410wdt_keepalive(); | 286 | s3c2410wdt_keepalive(); |
| 270 | } | 287 | } |
| 271 | return len; | 288 | return len; |
| @@ -273,48 +290,41 @@ static ssize_t s3c2410wdt_write(struct file *file, const char __user *data, | |||
| 273 | 290 | ||
| 274 | #define OPTIONS WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE | 291 | #define OPTIONS WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE |
| 275 | 292 | ||
| 276 | static struct watchdog_info s3c2410_wdt_ident = { | 293 | static const struct watchdog_info s3c2410_wdt_ident = { |
| 277 | .options = OPTIONS, | 294 | .options = OPTIONS, |
| 278 | .firmware_version = 0, | 295 | .firmware_version = 0, |
| 279 | .identity = "S3C2410 Watchdog", | 296 | .identity = "S3C2410 Watchdog", |
| 280 | }; | 297 | }; |
| 281 | 298 | ||
| 282 | 299 | ||
| 283 | static int s3c2410wdt_ioctl(struct inode *inode, struct file *file, | 300 | static long s3c2410wdt_ioctl(struct file *file, unsigned int cmd, |
| 284 | unsigned int cmd, unsigned long arg) | 301 | unsigned long arg) |
| 285 | { | 302 | { |
| 286 | void __user *argp = (void __user *)arg; | 303 | void __user *argp = (void __user *)arg; |
| 287 | int __user *p = argp; | 304 | int __user *p = argp; |
| 288 | int new_margin; | 305 | int new_margin; |
| 289 | 306 | ||
| 290 | switch (cmd) { | 307 | switch (cmd) { |
| 291 | default: | 308 | default: |
| 292 | return -ENOTTY; | 309 | return -ENOTTY; |
| 293 | 310 | case WDIOC_GETSUPPORT: | |
| 294 | case WDIOC_GETSUPPORT: | 311 | return copy_to_user(argp, &s3c2410_wdt_ident, |
| 295 | return copy_to_user(argp, &s3c2410_wdt_ident, | 312 | sizeof(s3c2410_wdt_ident)) ? -EFAULT : 0; |
| 296 | sizeof(s3c2410_wdt_ident)) ? -EFAULT : 0; | 313 | case WDIOC_GETSTATUS: |
| 297 | 314 | case WDIOC_GETBOOTSTATUS: | |
| 298 | case WDIOC_GETSTATUS: | 315 | return put_user(0, p); |
| 299 | case WDIOC_GETBOOTSTATUS: | 316 | case WDIOC_KEEPALIVE: |
| 300 | return put_user(0, p); | 317 | s3c2410wdt_keepalive(); |
| 301 | 318 | return 0; | |
| 302 | case WDIOC_KEEPALIVE: | 319 | case WDIOC_SETTIMEOUT: |
| 303 | s3c2410wdt_keepalive(); | 320 | if (get_user(new_margin, p)) |
| 304 | return 0; | 321 | return -EFAULT; |
| 305 | 322 | if (s3c2410wdt_set_heartbeat(new_margin)) | |
| 306 | case WDIOC_SETTIMEOUT: | 323 | return -EINVAL; |
| 307 | if (get_user(new_margin, p)) | 324 | s3c2410wdt_keepalive(); |
| 308 | return -EFAULT; | 325 | return put_user(tmr_margin, p); |
| 309 | 326 | case WDIOC_GETTIMEOUT: | |
| 310 | if (s3c2410wdt_set_heartbeat(new_margin)) | 327 | return put_user(tmr_margin, p); |
| 311 | return -EINVAL; | ||
| 312 | |||
| 313 | s3c2410wdt_keepalive(); | ||
| 314 | return put_user(tmr_margin, p); | ||
| 315 | |||
| 316 | case WDIOC_GETTIMEOUT: | ||
| 317 | return put_user(tmr_margin, p); | ||
| 318 | } | 328 | } |
| 319 | } | 329 | } |
| 320 | 330 | ||
| @@ -324,7 +334,7 @@ static const struct file_operations s3c2410wdt_fops = { | |||
| 324 | .owner = THIS_MODULE, | 334 | .owner = THIS_MODULE, |
| 325 | .llseek = no_llseek, | 335 | .llseek = no_llseek, |
| 326 | .write = s3c2410wdt_write, | 336 | .write = s3c2410wdt_write, |
| 327 | .ioctl = s3c2410wdt_ioctl, | 337 | .unlocked_ioctl = s3c2410wdt_ioctl, |
| 328 | .open = s3c2410wdt_open, | 338 | .open = s3c2410wdt_open, |
| 329 | .release = s3c2410wdt_release, | 339 | .release = s3c2410wdt_release, |
| 330 | }; | 340 | }; |
| @@ -411,14 +421,15 @@ static int s3c2410wdt_probe(struct platform_device *pdev) | |||
| 411 | * not, try the default value */ | 421 | * not, try the default value */ |
| 412 | 422 | ||
| 413 | if (s3c2410wdt_set_heartbeat(tmr_margin)) { | 423 | if (s3c2410wdt_set_heartbeat(tmr_margin)) { |
| 414 | started = s3c2410wdt_set_heartbeat(CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME); | 424 | started = s3c2410wdt_set_heartbeat( |
| 425 | CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME); | ||
| 415 | 426 | ||
| 416 | if (started == 0) { | 427 | if (started == 0) |
| 417 | dev_info(dev,"tmr_margin value out of range, default %d used\n", | 428 | dev_info(dev, |
| 429 | "tmr_margin value out of range, default %d used\n", | ||
| 418 | CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME); | 430 | CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME); |
| 419 | } else { | 431 | else |
| 420 | dev_info(dev, "default timer value is out of range, cannot start\n"); | 432 | dev_info(dev, "default timer value is out of range, cannot start\n"); |
| 421 | } | ||
| 422 | } | 433 | } |
| 423 | 434 | ||
| 424 | ret = misc_register(&s3c2410wdt_miscdev); | 435 | ret = misc_register(&s3c2410wdt_miscdev); |
| @@ -447,7 +458,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev) | |||
| 447 | (wtcon & S3C2410_WTCON_ENABLE) ? "" : "in", | 458 | (wtcon & S3C2410_WTCON_ENABLE) ? "" : "in", |
| 448 | (wtcon & S3C2410_WTCON_RSTEN) ? "" : "dis", | 459 | (wtcon & S3C2410_WTCON_RSTEN) ? "" : "dis", |
| 449 | (wtcon & S3C2410_WTCON_INTEN) ? "" : "en"); | 460 | (wtcon & S3C2410_WTCON_INTEN) ? "" : "en"); |
| 450 | 461 | ||
| 451 | return 0; | 462 | return 0; |
| 452 | 463 | ||
| 453 | err_clk: | 464 | err_clk: |
| @@ -487,7 +498,7 @@ static int s3c2410wdt_remove(struct platform_device *dev) | |||
| 487 | 498 | ||
| 488 | static void s3c2410wdt_shutdown(struct platform_device *dev) | 499 | static void s3c2410wdt_shutdown(struct platform_device *dev) |
| 489 | { | 500 | { |
| 490 | s3c2410wdt_stop(); | 501 | s3c2410wdt_stop(); |
| 491 | } | 502 | } |
| 492 | 503 | ||
| 493 | #ifdef CONFIG_PM | 504 | #ifdef CONFIG_PM |
| @@ -540,7 +551,8 @@ static struct platform_driver s3c2410wdt_driver = { | |||
| 540 | }; | 551 | }; |
| 541 | 552 | ||
| 542 | 553 | ||
| 543 | static char banner[] __initdata = KERN_INFO "S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n"; | 554 | static char banner[] __initdata = |
| 555 | KERN_INFO "S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n"; | ||
| 544 | 556 | ||
| 545 | static int __init watchdog_init(void) | 557 | static int __init watchdog_init(void) |
| 546 | { | 558 | { |
diff --git a/drivers/watchdog/sc1200wdt.c b/drivers/watchdog/sc1200wdt.c index 35cddff7020f..621ebad56d86 100644 --- a/drivers/watchdog/sc1200wdt.c +++ b/drivers/watchdog/sc1200wdt.c | |||
| @@ -15,14 +15,18 @@ | |||
| 15 | * | 15 | * |
| 16 | * Changelog: | 16 | * Changelog: |
| 17 | * 20020220 Zwane Mwaikambo Code based on datasheet, no hardware. | 17 | * 20020220 Zwane Mwaikambo Code based on datasheet, no hardware. |
| 18 | * 20020221 Zwane Mwaikambo Cleanups as suggested by Jeff Garzik and Alan Cox. | 18 | * 20020221 Zwane Mwaikambo Cleanups as suggested by Jeff Garzik |
| 19 | * and Alan Cox. | ||
| 19 | * 20020222 Zwane Mwaikambo Added probing. | 20 | * 20020222 Zwane Mwaikambo Added probing. |
| 20 | * 20020225 Zwane Mwaikambo Added ISAPNP support. | 21 | * 20020225 Zwane Mwaikambo Added ISAPNP support. |
| 21 | * 20020412 Rob Radez Broke out start/stop functions | 22 | * 20020412 Rob Radez Broke out start/stop functions |
| 22 | * <rob@osinvestor.com> Return proper status instead of temperature warning | 23 | * <rob@osinvestor.com> Return proper status instead of |
| 23 | * Add WDIOC_GETBOOTSTATUS and WDIOC_SETOPTIONS ioctls | 24 | * temperature warning |
| 25 | * Add WDIOC_GETBOOTSTATUS and | ||
| 26 | * WDIOC_SETOPTIONS ioctls | ||
| 24 | * Fix CONFIG_WATCHDOG_NOWAYOUT | 27 | * Fix CONFIG_WATCHDOG_NOWAYOUT |
| 25 | * 20020530 Joel Becker Add Matt Domsch's nowayout module option | 28 | * 20020530 Joel Becker Add Matt Domsch's nowayout module |
| 29 | * option | ||
| 26 | * 20030116 Adam Belay Updated to the latest pnp code | 30 | * 20030116 Adam Belay Updated to the latest pnp code |
| 27 | * | 31 | * |
| 28 | */ | 32 | */ |
| @@ -39,9 +43,8 @@ | |||
| 39 | #include <linux/pnp.h> | 43 | #include <linux/pnp.h> |
| 40 | #include <linux/fs.h> | 44 | #include <linux/fs.h> |
| 41 | #include <linux/semaphore.h> | 45 | #include <linux/semaphore.h> |
| 42 | 46 | #include <linux/io.h> | |
| 43 | #include <asm/io.h> | 47 | #include <linux/uaccess.h> |
| 44 | #include <asm/uaccess.h> | ||
| 45 | 48 | ||
| 46 | #define SC1200_MODULE_VER "build 20020303" | 49 | #define SC1200_MODULE_VER "build 20020303" |
| 47 | #define SC1200_MODULE_NAME "sc1200wdt" | 50 | #define SC1200_MODULE_NAME "sc1200wdt" |
| @@ -72,7 +75,7 @@ static char banner[] __initdata = KERN_INFO PFX SC1200_MODULE_VER; | |||
| 72 | static int timeout = 1; | 75 | static int timeout = 1; |
| 73 | static int io = -1; | 76 | static int io = -1; |
| 74 | static int io_len = 2; /* for non plug and play */ | 77 | static int io_len = 2; /* for non plug and play */ |
| 75 | static struct semaphore open_sem; | 78 | static unsigned long open_flag; |
| 76 | static char expect_close; | 79 | static char expect_close; |
| 77 | static DEFINE_SPINLOCK(sc1200wdt_lock); /* io port access serialisation */ | 80 | static DEFINE_SPINLOCK(sc1200wdt_lock); /* io port access serialisation */ |
| 78 | 81 | ||
| @@ -81,7 +84,8 @@ static int isapnp = 1; | |||
| 81 | static struct pnp_dev *wdt_dev; | 84 | static struct pnp_dev *wdt_dev; |
| 82 | 85 | ||
| 83 | module_param(isapnp, int, 0); | 86 | module_param(isapnp, int, 0); |
| 84 | MODULE_PARM_DESC(isapnp, "When set to 0 driver ISA PnP support will be disabled"); | 87 | MODULE_PARM_DESC(isapnp, |
| 88 | "When set to 0 driver ISA PnP support will be disabled"); | ||
| 85 | #endif | 89 | #endif |
| 86 | 90 | ||
| 87 | module_param(io, int, 0); | 91 | module_param(io, int, 0); |
| @@ -91,26 +95,40 @@ MODULE_PARM_DESC(timeout, "range is 0-255 minutes, default is 1"); | |||
| 91 | 95 | ||
| 92 | static int nowayout = WATCHDOG_NOWAYOUT; | 96 | static int nowayout = WATCHDOG_NOWAYOUT; |
| 93 | module_param(nowayout, int, 0); | 97 | module_param(nowayout, int, 0); |
| 94 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 98 | MODULE_PARM_DESC(nowayout, |
| 99 | "Watchdog cannot be stopped once started (default=" | ||
| 100 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
| 95 | 101 | ||
| 96 | 102 | ||
| 97 | 103 | ||
| 98 | /* Read from Data Register */ | 104 | /* Read from Data Register */ |
| 99 | static inline void sc1200wdt_read_data(unsigned char index, unsigned char *data) | 105 | static inline void __sc1200wdt_read_data(unsigned char index, |
| 106 | unsigned char *data) | ||
| 100 | { | 107 | { |
| 101 | spin_lock(&sc1200wdt_lock); | ||
| 102 | outb_p(index, PMIR); | 108 | outb_p(index, PMIR); |
| 103 | *data = inb(PMDR); | 109 | *data = inb(PMDR); |
| 104 | spin_unlock(&sc1200wdt_lock); | ||
| 105 | } | 110 | } |
| 106 | 111 | ||
| 112 | static void sc1200wdt_read_data(unsigned char index, unsigned char *data) | ||
| 113 | { | ||
| 114 | spin_lock(&sc1200wdt_lock); | ||
| 115 | __sc1200wdt_read_data(index, data); | ||
| 116 | spin_unlock(&sc1200wdt_lock); | ||
| 117 | } | ||
| 107 | 118 | ||
| 108 | /* Write to Data Register */ | 119 | /* Write to Data Register */ |
| 109 | static inline void sc1200wdt_write_data(unsigned char index, unsigned char data) | 120 | static inline void __sc1200wdt_write_data(unsigned char index, |
| 121 | unsigned char data) | ||
| 110 | { | 122 | { |
| 111 | spin_lock(&sc1200wdt_lock); | ||
| 112 | outb_p(index, PMIR); | 123 | outb_p(index, PMIR); |
| 113 | outb(data, PMDR); | 124 | outb(data, PMDR); |
| 125 | } | ||
| 126 | |||
| 127 | static inline void sc1200wdt_write_data(unsigned char index, | ||
| 128 | unsigned char data) | ||
| 129 | { | ||
| 130 | spin_lock(&sc1200wdt_lock); | ||
| 131 | __sc1200wdt_write_data(index, data); | ||
| 114 | spin_unlock(&sc1200wdt_lock); | 132 | spin_unlock(&sc1200wdt_lock); |
| 115 | } | 133 | } |
| 116 | 134 | ||
| @@ -118,22 +136,23 @@ static inline void sc1200wdt_write_data(unsigned char index, unsigned char data) | |||
| 118 | static void sc1200wdt_start(void) | 136 | static void sc1200wdt_start(void) |
| 119 | { | 137 | { |
| 120 | unsigned char reg; | 138 | unsigned char reg; |
| 139 | spin_lock(&sc1200wdt_lock); | ||
| 121 | 140 | ||
| 122 | sc1200wdt_read_data(WDCF, ®); | 141 | __sc1200wdt_read_data(WDCF, ®); |
| 123 | /* assert WDO when any of the following interrupts are triggered too */ | 142 | /* assert WDO when any of the following interrupts are triggered too */ |
| 124 | reg |= (KBC_IRQ | MSE_IRQ | UART1_IRQ | UART2_IRQ); | 143 | reg |= (KBC_IRQ | MSE_IRQ | UART1_IRQ | UART2_IRQ); |
| 125 | sc1200wdt_write_data(WDCF, reg); | 144 | __sc1200wdt_write_data(WDCF, reg); |
| 126 | /* set the timeout and get the ball rolling */ | 145 | /* set the timeout and get the ball rolling */ |
| 127 | sc1200wdt_write_data(WDTO, timeout); | 146 | __sc1200wdt_write_data(WDTO, timeout); |
| 128 | } | ||
| 129 | 147 | ||
| 148 | spin_unlock(&sc1200wdt_lock); | ||
| 149 | } | ||
| 130 | 150 | ||
| 131 | static void sc1200wdt_stop(void) | 151 | static void sc1200wdt_stop(void) |
| 132 | { | 152 | { |
| 133 | sc1200wdt_write_data(WDTO, 0); | 153 | sc1200wdt_write_data(WDTO, 0); |
| 134 | } | 154 | } |
| 135 | 155 | ||
| 136 | |||
| 137 | /* This returns the status of the WDO signal, inactive high. */ | 156 | /* This returns the status of the WDO signal, inactive high. */ |
| 138 | static inline int sc1200wdt_status(void) | 157 | static inline int sc1200wdt_status(void) |
| 139 | { | 158 | { |
| @@ -144,14 +163,13 @@ static inline int sc1200wdt_status(void) | |||
| 144 | * KEEPALIVEPING which is a bit of a kludge because there's nothing | 163 | * KEEPALIVEPING which is a bit of a kludge because there's nothing |
| 145 | * else for enabled/disabled status | 164 | * else for enabled/disabled status |
| 146 | */ | 165 | */ |
| 147 | return (ret & 0x01) ? 0 : WDIOF_KEEPALIVEPING; /* bits 1 - 7 are undefined */ | 166 | return (ret & 0x01) ? 0 : WDIOF_KEEPALIVEPING; |
| 148 | } | 167 | } |
| 149 | 168 | ||
| 150 | |||
| 151 | static int sc1200wdt_open(struct inode *inode, struct file *file) | 169 | static int sc1200wdt_open(struct inode *inode, struct file *file) |
| 152 | { | 170 | { |
| 153 | /* allow one at a time */ | 171 | /* allow one at a time */ |
| 154 | if (down_trylock(&open_sem)) | 172 | if (test_and_set_bit(0, &open_flag)) |
| 155 | return -EBUSY; | 173 | return -EBUSY; |
| 156 | 174 | ||
| 157 | if (timeout > MAX_TIMEOUT) | 175 | if (timeout > MAX_TIMEOUT) |
| @@ -164,71 +182,71 @@ static int sc1200wdt_open(struct inode *inode, struct file *file) | |||
| 164 | } | 182 | } |
| 165 | 183 | ||
| 166 | 184 | ||
| 167 | static int sc1200wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 185 | static long sc1200wdt_ioctl(struct file *file, unsigned int cmd, |
| 186 | unsigned long arg) | ||
| 168 | { | 187 | { |
| 169 | int new_timeout; | 188 | int new_timeout; |
| 170 | void __user *argp = (void __user *)arg; | 189 | void __user *argp = (void __user *)arg; |
| 171 | int __user *p = argp; | 190 | int __user *p = argp; |
| 172 | static struct watchdog_info ident = { | 191 | static const struct watchdog_info ident = { |
| 173 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, | 192 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | |
| 193 | WDIOF_MAGICCLOSE, | ||
| 174 | .firmware_version = 0, | 194 | .firmware_version = 0, |
| 175 | .identity = "PC87307/PC97307", | 195 | .identity = "PC87307/PC97307", |
| 176 | }; | 196 | }; |
| 177 | 197 | ||
| 178 | switch (cmd) { | 198 | switch (cmd) { |
| 179 | default: | ||
| 180 | return -ENOTTY; | ||
| 181 | |||
| 182 | case WDIOC_GETSUPPORT: | ||
| 183 | if (copy_to_user(argp, &ident, sizeof ident)) | ||
| 184 | return -EFAULT; | ||
| 185 | return 0; | ||
| 186 | |||
| 187 | case WDIOC_GETSTATUS: | ||
| 188 | return put_user(sc1200wdt_status(), p); | ||
| 189 | |||
| 190 | case WDIOC_GETBOOTSTATUS: | ||
| 191 | return put_user(0, p); | ||
| 192 | |||
| 193 | case WDIOC_KEEPALIVE: | ||
| 194 | sc1200wdt_write_data(WDTO, timeout); | ||
| 195 | return 0; | ||
| 196 | 199 | ||
| 197 | case WDIOC_SETTIMEOUT: | 200 | case WDIOC_GETSUPPORT: |
| 198 | if (get_user(new_timeout, p)) | 201 | if (copy_to_user(argp, &ident, sizeof ident)) |
| 199 | return -EFAULT; | 202 | return -EFAULT; |
| 203 | return 0; | ||
| 200 | 204 | ||
| 201 | /* the API states this is given in secs */ | 205 | case WDIOC_GETSTATUS: |
| 202 | new_timeout /= 60; | 206 | return put_user(sc1200wdt_status(), p); |
| 203 | if (new_timeout < 0 || new_timeout > MAX_TIMEOUT) | ||
| 204 | return -EINVAL; | ||
| 205 | 207 | ||
| 206 | timeout = new_timeout; | 208 | case WDIOC_GETBOOTSTATUS: |
| 207 | sc1200wdt_write_data(WDTO, timeout); | 209 | return put_user(0, p); |
| 208 | /* fall through and return the new timeout */ | ||
| 209 | 210 | ||
| 210 | case WDIOC_GETTIMEOUT: | 211 | case WDIOC_KEEPALIVE: |
| 211 | return put_user(timeout * 60, p); | 212 | sc1200wdt_write_data(WDTO, timeout); |
| 213 | return 0; | ||
| 214 | |||
| 215 | case WDIOC_SETTIMEOUT: | ||
| 216 | if (get_user(new_timeout, p)) | ||
| 217 | return -EFAULT; | ||
| 218 | /* the API states this is given in secs */ | ||
| 219 | new_timeout /= 60; | ||
| 220 | if (new_timeout < 0 || new_timeout > MAX_TIMEOUT) | ||
| 221 | return -EINVAL; | ||
| 222 | timeout = new_timeout; | ||
| 223 | sc1200wdt_write_data(WDTO, timeout); | ||
| 224 | /* fall through and return the new timeout */ | ||
| 212 | 225 | ||
| 213 | case WDIOC_SETOPTIONS: | 226 | case WDIOC_GETTIMEOUT: |
| 214 | { | 227 | return put_user(timeout * 60, p); |
| 215 | int options, retval = -EINVAL; | ||
| 216 | 228 | ||
| 217 | if (get_user(options, p)) | 229 | case WDIOC_SETOPTIONS: |
| 218 | return -EFAULT; | 230 | { |
| 231 | int options, retval = -EINVAL; | ||
| 219 | 232 | ||
| 220 | if (options & WDIOS_DISABLECARD) { | 233 | if (get_user(options, p)) |
| 221 | sc1200wdt_stop(); | 234 | return -EFAULT; |
| 222 | retval = 0; | ||
| 223 | } | ||
| 224 | 235 | ||
| 225 | if (options & WDIOS_ENABLECARD) { | 236 | if (options & WDIOS_DISABLECARD) { |
| 226 | sc1200wdt_start(); | 237 | sc1200wdt_stop(); |
| 227 | retval = 0; | 238 | retval = 0; |
| 228 | } | 239 | } |
| 229 | 240 | ||
| 230 | return retval; | 241 | if (options & WDIOS_ENABLECARD) { |
| 242 | sc1200wdt_start(); | ||
| 243 | retval = 0; | ||
| 231 | } | 244 | } |
| 245 | |||
| 246 | return retval; | ||
| 247 | } | ||
| 248 | default: | ||
| 249 | return -ENOTTY; | ||
| 232 | } | 250 | } |
| 233 | } | 251 | } |
| 234 | 252 | ||
| @@ -240,16 +258,18 @@ static int sc1200wdt_release(struct inode *inode, struct file *file) | |||
| 240 | printk(KERN_INFO PFX "Watchdog disabled\n"); | 258 | printk(KERN_INFO PFX "Watchdog disabled\n"); |
| 241 | } else { | 259 | } else { |
| 242 | sc1200wdt_write_data(WDTO, timeout); | 260 | sc1200wdt_write_data(WDTO, timeout); |
| 243 | printk(KERN_CRIT PFX "Unexpected close!, timeout = %d min(s)\n", timeout); | 261 | printk(KERN_CRIT PFX |
| 262 | "Unexpected close!, timeout = %d min(s)\n", timeout); | ||
| 244 | } | 263 | } |
| 245 | up(&open_sem); | 264 | clear_bit(0, &open_flag); |
| 246 | expect_close = 0; | 265 | expect_close = 0; |
| 247 | 266 | ||
| 248 | return 0; | 267 | return 0; |
| 249 | } | 268 | } |
| 250 | 269 | ||
| 251 | 270 | ||
| 252 | static ssize_t sc1200wdt_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) | 271 | static ssize_t sc1200wdt_write(struct file *file, const char __user *data, |
| 272 | size_t len, loff_t *ppos) | ||
| 253 | { | 273 | { |
| 254 | if (len) { | 274 | if (len) { |
| 255 | if (!nowayout) { | 275 | if (!nowayout) { |
| @@ -275,7 +295,8 @@ static ssize_t sc1200wdt_write(struct file *file, const char __user *data, size_ | |||
| 275 | } | 295 | } |
| 276 | 296 | ||
| 277 | 297 | ||
| 278 | static int sc1200wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) | 298 | static int sc1200wdt_notify_sys(struct notifier_block *this, |
| 299 | unsigned long code, void *unused) | ||
| 279 | { | 300 | { |
| 280 | if (code == SYS_DOWN || code == SYS_HALT) | 301 | if (code == SYS_DOWN || code == SYS_HALT) |
| 281 | sc1200wdt_stop(); | 302 | sc1200wdt_stop(); |
| @@ -284,23 +305,20 @@ static int sc1200wdt_notify_sys(struct notifier_block *this, unsigned long code, | |||
| 284 | } | 305 | } |
| 285 | 306 | ||
| 286 | 307 | ||
| 287 | static struct notifier_block sc1200wdt_notifier = | 308 | static struct notifier_block sc1200wdt_notifier = { |
| 288 | { | ||
| 289 | .notifier_call = sc1200wdt_notify_sys, | 309 | .notifier_call = sc1200wdt_notify_sys, |
| 290 | }; | 310 | }; |
| 291 | 311 | ||
| 292 | static const struct file_operations sc1200wdt_fops = | 312 | static const struct file_operations sc1200wdt_fops = { |
| 293 | { | ||
| 294 | .owner = THIS_MODULE, | 313 | .owner = THIS_MODULE, |
| 295 | .llseek = no_llseek, | 314 | .llseek = no_llseek, |
| 296 | .write = sc1200wdt_write, | 315 | .write = sc1200wdt_write, |
| 297 | .ioctl = sc1200wdt_ioctl, | 316 | .unlocked_ioctl = sc1200wdt_ioctl, |
| 298 | .open = sc1200wdt_open, | 317 | .open = sc1200wdt_open, |
| 299 | .release = sc1200wdt_release, | 318 | .release = sc1200wdt_release, |
| 300 | }; | 319 | }; |
| 301 | 320 | ||
| 302 | static struct miscdevice sc1200wdt_miscdev = | 321 | static struct miscdevice sc1200wdt_miscdev = { |
| 303 | { | ||
| 304 | .minor = WATCHDOG_MINOR, | 322 | .minor = WATCHDOG_MINOR, |
| 305 | .name = "watchdog", | 323 | .name = "watchdog", |
| 306 | .fops = &sc1200wdt_fops, | 324 | .fops = &sc1200wdt_fops, |
| @@ -312,14 +330,14 @@ static int __init sc1200wdt_probe(void) | |||
| 312 | /* The probe works by reading the PMC3 register's default value of 0x0e | 330 | /* The probe works by reading the PMC3 register's default value of 0x0e |
| 313 | * there is one caveat, if the device disables the parallel port or any | 331 | * there is one caveat, if the device disables the parallel port or any |
| 314 | * of the UARTs we won't be able to detect it. | 332 | * of the UARTs we won't be able to detect it. |
| 315 | * Nb. This could be done with accuracy by reading the SID registers, but | 333 | * NB. This could be done with accuracy by reading the SID registers, |
| 316 | * we don't have access to those io regions. | 334 | * but we don't have access to those io regions. |
| 317 | */ | 335 | */ |
| 318 | 336 | ||
| 319 | unsigned char reg; | 337 | unsigned char reg; |
| 320 | 338 | ||
| 321 | sc1200wdt_read_data(PMC3, ®); | 339 | sc1200wdt_read_data(PMC3, ®); |
| 322 | reg &= 0x0f; /* we don't want the UART busy bits */ | 340 | reg &= 0x0f; /* we don't want the UART busy bits */ |
| 323 | return (reg == 0x0e) ? 0 : -ENODEV; | 341 | return (reg == 0x0e) ? 0 : -ENODEV; |
| 324 | } | 342 | } |
| 325 | 343 | ||
| @@ -332,7 +350,8 @@ static struct pnp_device_id scl200wdt_pnp_devices[] = { | |||
| 332 | {.id = ""}, | 350 | {.id = ""}, |
| 333 | }; | 351 | }; |
| 334 | 352 | ||
| 335 | static int scl200wdt_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id) | 353 | static int scl200wdt_pnp_probe(struct pnp_dev *dev, |
| 354 | const struct pnp_device_id *dev_id) | ||
| 336 | { | 355 | { |
| 337 | /* this driver only supports one card at a time */ | 356 | /* this driver only supports one card at a time */ |
| 338 | if (wdt_dev || !isapnp) | 357 | if (wdt_dev || !isapnp) |
| @@ -347,13 +366,14 @@ static int scl200wdt_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id | |||
| 347 | return -EBUSY; | 366 | return -EBUSY; |
| 348 | } | 367 | } |
| 349 | 368 | ||
| 350 | printk(KERN_INFO "scl200wdt: PnP device found at io port %#x/%d\n", io, io_len); | 369 | printk(KERN_INFO "scl200wdt: PnP device found at io port %#x/%d\n", |
| 370 | io, io_len); | ||
| 351 | return 0; | 371 | return 0; |
| 352 | } | 372 | } |
| 353 | 373 | ||
| 354 | static void scl200wdt_pnp_remove(struct pnp_dev * dev) | 374 | static void scl200wdt_pnp_remove(struct pnp_dev *dev) |
| 355 | { | 375 | { |
| 356 | if (wdt_dev){ | 376 | if (wdt_dev) { |
| 357 | release_region(io, io_len); | 377 | release_region(io, io_len); |
| 358 | wdt_dev = NULL; | 378 | wdt_dev = NULL; |
| 359 | } | 379 | } |
| @@ -375,8 +395,6 @@ static int __init sc1200wdt_init(void) | |||
| 375 | 395 | ||
| 376 | printk("%s\n", banner); | 396 | printk("%s\n", banner); |
| 377 | 397 | ||
| 378 | sema_init(&open_sem, 1); | ||
| 379 | |||
| 380 | #if defined CONFIG_PNP | 398 | #if defined CONFIG_PNP |
| 381 | if (isapnp) { | 399 | if (isapnp) { |
| 382 | ret = pnp_register_driver(&scl200wdt_pnp_driver); | 400 | ret = pnp_register_driver(&scl200wdt_pnp_driver); |
| @@ -410,13 +428,16 @@ static int __init sc1200wdt_init(void) | |||
| 410 | 428 | ||
| 411 | ret = register_reboot_notifier(&sc1200wdt_notifier); | 429 | ret = register_reboot_notifier(&sc1200wdt_notifier); |
| 412 | if (ret) { | 430 | if (ret) { |
| 413 | printk(KERN_ERR PFX "Unable to register reboot notifier err = %d\n", ret); | 431 | printk(KERN_ERR PFX |
| 432 | "Unable to register reboot notifier err = %d\n", ret); | ||
| 414 | goto out_io; | 433 | goto out_io; |
| 415 | } | 434 | } |
| 416 | 435 | ||
| 417 | ret = misc_register(&sc1200wdt_miscdev); | 436 | ret = misc_register(&sc1200wdt_miscdev); |
| 418 | if (ret) { | 437 | if (ret) { |
| 419 | printk(KERN_ERR PFX "Unable to register miscdev on minor %d\n", WATCHDOG_MINOR); | 438 | printk(KERN_ERR PFX |
| 439 | "Unable to register miscdev on minor %d\n", | ||
| 440 | WATCHDOG_MINOR); | ||
| 420 | goto out_rbt; | 441 | goto out_rbt; |
| 421 | } | 442 | } |
| 422 | 443 | ||
| @@ -446,7 +467,7 @@ static void __exit sc1200wdt_exit(void) | |||
| 446 | unregister_reboot_notifier(&sc1200wdt_notifier); | 467 | unregister_reboot_notifier(&sc1200wdt_notifier); |
| 447 | 468 | ||
| 448 | #if defined CONFIG_PNP | 469 | #if defined CONFIG_PNP |
| 449 | if(isapnp) | 470 | if (isapnp) |
| 450 | pnp_unregister_driver(&scl200wdt_pnp_driver); | 471 | pnp_unregister_driver(&scl200wdt_pnp_driver); |
| 451 | else | 472 | else |
| 452 | #endif | 473 | #endif |
diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c index 756fb15fdce7..53a6b18bcb9a 100644 --- a/drivers/watchdog/wdt.c +++ b/drivers/watchdog/wdt.c | |||
| @@ -24,9 +24,10 @@ | |||
| 24 | * Matt Crocker). | 24 | * Matt Crocker). |
| 25 | * Alan Cox : Added wdt= boot option | 25 | * Alan Cox : Added wdt= boot option |
| 26 | * Alan Cox : Cleaned up copy/user stuff | 26 | * Alan Cox : Cleaned up copy/user stuff |
| 27 | * Tim Hockin : Added insmod parameters, comment cleanup | 27 | * Tim Hockin : Added insmod parameters, comment |
| 28 | * Parameterized timeout | 28 | * cleanup, parameterized timeout |
| 29 | * Tigran Aivazian : Restructured wdt_init() to handle failures | 29 | * Tigran Aivazian : Restructured wdt_init() to handle |
| 30 | * failures | ||
| 30 | * Joel Becker : Added WDIOC_GET/SETTIMEOUT | 31 | * Joel Becker : Added WDIOC_GET/SETTIMEOUT |
| 31 | * Matt Domsch : Added nowayout module option | 32 | * Matt Domsch : Added nowayout module option |
| 32 | */ | 33 | */ |
| @@ -42,9 +43,9 @@ | |||
| 42 | #include <linux/notifier.h> | 43 | #include <linux/notifier.h> |
| 43 | #include <linux/reboot.h> | 44 | #include <linux/reboot.h> |
| 44 | #include <linux/init.h> | 45 | #include <linux/init.h> |
| 46 | #include <linux/io.h> | ||
| 47 | #include <linux/uaccess.h> | ||
| 45 | 48 | ||
| 46 | #include <asm/io.h> | ||
| 47 | #include <asm/uaccess.h> | ||
| 48 | #include <asm/system.h> | 49 | #include <asm/system.h> |
| 49 | #include "wd501p.h" | 50 | #include "wd501p.h" |
| 50 | 51 | ||
| @@ -60,15 +61,19 @@ static char expect_close; | |||
| 60 | static int heartbeat = WD_TIMO; | 61 | static int heartbeat = WD_TIMO; |
| 61 | static int wd_heartbeat; | 62 | static int wd_heartbeat; |
| 62 | module_param(heartbeat, int, 0); | 63 | module_param(heartbeat, int, 0); |
| 63 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")"); | 64 | MODULE_PARM_DESC(heartbeat, |
| 65 | "Watchdog heartbeat in seconds. (0 < heartbeat < 65536, default=" | ||
| 66 | __MODULE_STRING(WD_TIMO) ")"); | ||
| 64 | 67 | ||
| 65 | static int nowayout = WATCHDOG_NOWAYOUT; | 68 | static int nowayout = WATCHDOG_NOWAYOUT; |
| 66 | module_param(nowayout, int, 0); | 69 | module_param(nowayout, int, 0); |
| 67 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 70 | MODULE_PARM_DESC(nowayout, |
| 71 | "Watchdog cannot be stopped once started (default=" | ||
| 72 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
| 68 | 73 | ||
| 69 | /* You must set these - there is no sane way to probe for this board. */ | 74 | /* You must set these - there is no sane way to probe for this board. */ |
| 70 | static int io=0x240; | 75 | static int io = 0x240; |
| 71 | static int irq=11; | 76 | static int irq = 11; |
| 72 | 77 | ||
| 73 | static DEFINE_SPINLOCK(wdt_lock); | 78 | static DEFINE_SPINLOCK(wdt_lock); |
| 74 | 79 | ||
| @@ -82,7 +87,8 @@ MODULE_PARM_DESC(irq, "WDT irq (default=11)"); | |||
| 82 | static int tachometer; | 87 | static int tachometer; |
| 83 | 88 | ||
| 84 | module_param(tachometer, int, 0); | 89 | module_param(tachometer, int, 0); |
| 85 | MODULE_PARM_DESC(tachometer, "WDT501-P Fan Tachometer support (0=disable, default=0)"); | 90 | MODULE_PARM_DESC(tachometer, |
| 91 | "WDT501-P Fan Tachometer support (0=disable, default=0)"); | ||
| 86 | #endif /* CONFIG_WDT_501 */ | 92 | #endif /* CONFIG_WDT_501 */ |
| 87 | 93 | ||
| 88 | /* | 94 | /* |
| @@ -91,9 +97,9 @@ MODULE_PARM_DESC(tachometer, "WDT501-P Fan Tachometer support (0=disable, defaul | |||
| 91 | 97 | ||
| 92 | static void wdt_ctr_mode(int ctr, int mode) | 98 | static void wdt_ctr_mode(int ctr, int mode) |
| 93 | { | 99 | { |
| 94 | ctr<<=6; | 100 | ctr <<= 6; |
| 95 | ctr|=0x30; | 101 | ctr |= 0x30; |
| 96 | ctr|=(mode<<1); | 102 | ctr |= (mode << 1); |
| 97 | outb_p(ctr, WDT_CR); | 103 | outb_p(ctr, WDT_CR); |
| 98 | } | 104 | } |
| 99 | 105 | ||
| @@ -114,12 +120,15 @@ static int wdt_start(void) | |||
| 114 | unsigned long flags; | 120 | unsigned long flags; |
| 115 | spin_lock_irqsave(&wdt_lock, flags); | 121 | spin_lock_irqsave(&wdt_lock, flags); |
| 116 | inb_p(WDT_DC); /* Disable watchdog */ | 122 | inb_p(WDT_DC); /* Disable watchdog */ |
| 117 | wdt_ctr_mode(0,3); /* Program CTR0 for Mode 3: Square Wave Generator */ | 123 | wdt_ctr_mode(0, 3); /* Program CTR0 for Mode 3: |
| 118 | wdt_ctr_mode(1,2); /* Program CTR1 for Mode 2: Rate Generator */ | 124 | Square Wave Generator */ |
| 119 | wdt_ctr_mode(2,0); /* Program CTR2 for Mode 0: Pulse on Terminal Count */ | 125 | wdt_ctr_mode(1, 2); /* Program CTR1 for Mode 2: |
| 126 | Rate Generator */ | ||
| 127 | wdt_ctr_mode(2, 0); /* Program CTR2 for Mode 0: | ||
| 128 | Pulse on Terminal Count */ | ||
| 120 | wdt_ctr_load(0, 8948); /* Count at 100Hz */ | 129 | wdt_ctr_load(0, 8948); /* Count at 100Hz */ |
| 121 | wdt_ctr_load(1,wd_heartbeat); /* Heartbeat */ | 130 | wdt_ctr_load(1, wd_heartbeat); /* Heartbeat */ |
| 122 | wdt_ctr_load(2,65535); /* Length of reset pulse */ | 131 | wdt_ctr_load(2, 65535); /* Length of reset pulse */ |
| 123 | outb_p(0, WDT_DC); /* Enable watchdog */ | 132 | outb_p(0, WDT_DC); /* Enable watchdog */ |
| 124 | spin_unlock_irqrestore(&wdt_lock, flags); | 133 | spin_unlock_irqrestore(&wdt_lock, flags); |
| 125 | return 0; | 134 | return 0; |
| @@ -131,13 +140,13 @@ static int wdt_start(void) | |||
| 131 | * Stop the watchdog driver. | 140 | * Stop the watchdog driver. |
| 132 | */ | 141 | */ |
| 133 | 142 | ||
| 134 | static int wdt_stop (void) | 143 | static int wdt_stop(void) |
| 135 | { | 144 | { |
| 136 | unsigned long flags; | 145 | unsigned long flags; |
| 137 | spin_lock_irqsave(&wdt_lock, flags); | 146 | spin_lock_irqsave(&wdt_lock, flags); |
| 138 | /* Turn the card off */ | 147 | /* Turn the card off */ |
| 139 | inb_p(WDT_DC); /* Disable watchdog */ | 148 | inb_p(WDT_DC); /* Disable watchdog */ |
| 140 | wdt_ctr_load(2,0); /* 0 length reset pulses now */ | 149 | wdt_ctr_load(2, 0); /* 0 length reset pulses now */ |
| 141 | spin_unlock_irqrestore(&wdt_lock, flags); | 150 | spin_unlock_irqrestore(&wdt_lock, flags); |
| 142 | return 0; | 151 | return 0; |
| 143 | } | 152 | } |
| @@ -145,8 +154,8 @@ static int wdt_stop (void) | |||
| 145 | /** | 154 | /** |
| 146 | * wdt_ping: | 155 | * wdt_ping: |
| 147 | * | 156 | * |
| 148 | * Reload counter one with the watchdog heartbeat. We don't bother reloading | 157 | * Reload counter one with the watchdog heartbeat. We don't bother |
| 149 | * the cascade counter. | 158 | * reloading the cascade counter. |
| 150 | */ | 159 | */ |
| 151 | 160 | ||
| 152 | static int wdt_ping(void) | 161 | static int wdt_ping(void) |
| @@ -155,8 +164,9 @@ static int wdt_ping(void) | |||
| 155 | spin_lock_irqsave(&wdt_lock, flags); | 164 | spin_lock_irqsave(&wdt_lock, flags); |
| 156 | /* Write a watchdog value */ | 165 | /* Write a watchdog value */ |
| 157 | inb_p(WDT_DC); /* Disable watchdog */ | 166 | inb_p(WDT_DC); /* Disable watchdog */ |
| 158 | wdt_ctr_mode(1,2); /* Re-Program CTR1 for Mode 2: Rate Generator */ | 167 | wdt_ctr_mode(1, 2); /* Re-Program CTR1 for Mode 2: |
| 159 | wdt_ctr_load(1,wd_heartbeat); /* Heartbeat */ | 168 | Rate Generator */ |
| 169 | wdt_ctr_load(1, wd_heartbeat); /* Heartbeat */ | ||
| 160 | outb_p(0, WDT_DC); /* Enable watchdog */ | 170 | outb_p(0, WDT_DC); /* Enable watchdog */ |
| 161 | spin_unlock_irqrestore(&wdt_lock, flags); | 171 | spin_unlock_irqrestore(&wdt_lock, flags); |
| 162 | return 0; | 172 | return 0; |
| @@ -166,13 +176,14 @@ static int wdt_ping(void) | |||
| 166 | * wdt_set_heartbeat: | 176 | * wdt_set_heartbeat: |
| 167 | * @t: the new heartbeat value that needs to be set. | 177 | * @t: the new heartbeat value that needs to be set. |
| 168 | * | 178 | * |
| 169 | * Set a new heartbeat value for the watchdog device. If the heartbeat value is | 179 | * Set a new heartbeat value for the watchdog device. If the heartbeat |
| 170 | * incorrect we keep the old value and return -EINVAL. If successfull we | 180 | * value is incorrect we keep the old value and return -EINVAL. If |
| 171 | * return 0. | 181 | * successful we return 0. |
| 172 | */ | 182 | */ |
| 183 | |||
| 173 | static int wdt_set_heartbeat(int t) | 184 | static int wdt_set_heartbeat(int t) |
| 174 | { | 185 | { |
| 175 | if ((t < 1) || (t > 65535)) | 186 | if (t < 1 || t > 65535) |
| 176 | return -EINVAL; | 187 | return -EINVAL; |
| 177 | 188 | ||
| 178 | heartbeat = t; | 189 | heartbeat = t; |
| @@ -200,7 +211,7 @@ static int wdt_get_status(int *status) | |||
| 200 | new_status = inb_p(WDT_SR); | 211 | new_status = inb_p(WDT_SR); |
| 201 | spin_unlock_irqrestore(&wdt_lock, flags); | 212 | spin_unlock_irqrestore(&wdt_lock, flags); |
| 202 | 213 | ||
| 203 | *status=0; | 214 | *status = 0; |
| 204 | if (new_status & WDC_SR_ISOI0) | 215 | if (new_status & WDC_SR_ISOI0) |
| 205 | *status |= WDIOF_EXTERN1; | 216 | *status |= WDIOF_EXTERN1; |
| 206 | if (new_status & WDC_SR_ISII1) | 217 | if (new_status & WDC_SR_ISII1) |
| @@ -266,7 +277,7 @@ static irqreturn_t wdt_interrupt(int irq, void *dev_id) | |||
| 266 | 277 | ||
| 267 | #ifdef CONFIG_WDT_501 | 278 | #ifdef CONFIG_WDT_501 |
| 268 | if (!(status & WDC_SR_TGOOD)) | 279 | if (!(status & WDC_SR_TGOOD)) |
| 269 | printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT)); | 280 | printk(KERN_CRIT "Overheat alarm.(%d)\n", inb_p(WDT_RT)); |
| 270 | if (!(status & WDC_SR_PSUOVER)) | 281 | if (!(status & WDC_SR_PSUOVER)) |
| 271 | printk(KERN_CRIT "PSU over voltage.\n"); | 282 | printk(KERN_CRIT "PSU over voltage.\n"); |
| 272 | if (!(status & WDC_SR_PSUUNDR)) | 283 | if (!(status & WDC_SR_PSUUNDR)) |
| @@ -304,9 +315,10 @@ static irqreturn_t wdt_interrupt(int irq, void *dev_id) | |||
| 304 | * write of data will do, as we we don't define content meaning. | 315 | * write of data will do, as we we don't define content meaning. |
| 305 | */ | 316 | */ |
| 306 | 317 | ||
| 307 | static ssize_t wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | 318 | static ssize_t wdt_write(struct file *file, const char __user *buf, |
| 319 | size_t count, loff_t *ppos) | ||
| 308 | { | 320 | { |
| 309 | if(count) { | 321 | if (count) { |
| 310 | if (!nowayout) { | 322 | if (!nowayout) { |
| 311 | size_t i; | 323 | size_t i; |
| 312 | 324 | ||
| @@ -328,7 +340,6 @@ static ssize_t wdt_write(struct file *file, const char __user *buf, size_t count | |||
| 328 | 340 | ||
| 329 | /** | 341 | /** |
| 330 | * wdt_ioctl: | 342 | * wdt_ioctl: |
| 331 | * @inode: inode of the device | ||
| 332 | * @file: file handle to the device | 343 | * @file: file handle to the device |
| 333 | * @cmd: watchdog command | 344 | * @cmd: watchdog command |
| 334 | * @arg: argument pointer | 345 | * @arg: argument pointer |
| @@ -338,8 +349,7 @@ static ssize_t wdt_write(struct file *file, const char __user *buf, size_t count | |||
| 338 | * querying capabilities and current status. | 349 | * querying capabilities and current status. |
| 339 | */ | 350 | */ |
| 340 | 351 | ||
| 341 | static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 352 | static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| 342 | unsigned long arg) | ||
| 343 | { | 353 | { |
| 344 | void __user *argp = (void __user *)arg; | 354 | void __user *argp = (void __user *)arg; |
| 345 | int __user *p = argp; | 355 | int __user *p = argp; |
| @@ -362,32 +372,28 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 362 | ident.options |= WDIOF_FANFAULT; | 372 | ident.options |= WDIOF_FANFAULT; |
| 363 | #endif /* CONFIG_WDT_501 */ | 373 | #endif /* CONFIG_WDT_501 */ |
| 364 | 374 | ||
| 365 | switch(cmd) | 375 | switch (cmd) { |
| 366 | { | 376 | default: |
| 367 | default: | 377 | return -ENOTTY; |
| 368 | return -ENOTTY; | 378 | case WDIOC_GETSUPPORT: |
| 369 | case WDIOC_GETSUPPORT: | 379 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; |
| 370 | return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; | 380 | case WDIOC_GETSTATUS: |
| 371 | 381 | wdt_get_status(&status); | |
| 372 | case WDIOC_GETSTATUS: | 382 | return put_user(status, p); |
| 373 | wdt_get_status(&status); | 383 | case WDIOC_GETBOOTSTATUS: |
| 374 | return put_user(status, p); | 384 | return put_user(0, p); |
| 375 | case WDIOC_GETBOOTSTATUS: | 385 | case WDIOC_KEEPALIVE: |
| 376 | return put_user(0, p); | 386 | wdt_ping(); |
| 377 | case WDIOC_KEEPALIVE: | 387 | return 0; |
| 378 | wdt_ping(); | 388 | case WDIOC_SETTIMEOUT: |
| 379 | return 0; | 389 | if (get_user(new_heartbeat, p)) |
| 380 | case WDIOC_SETTIMEOUT: | 390 | return -EFAULT; |
| 381 | if (get_user(new_heartbeat, p)) | 391 | if (wdt_set_heartbeat(new_heartbeat)) |
| 382 | return -EFAULT; | 392 | return -EINVAL; |
| 383 | 393 | wdt_ping(); | |
| 384 | if (wdt_set_heartbeat(new_heartbeat)) | 394 | /* Fall */ |
| 385 | return -EINVAL; | 395 | case WDIOC_GETTIMEOUT: |
| 386 | 396 | return put_user(heartbeat, p); | |
| 387 | wdt_ping(); | ||
| 388 | /* Fall */ | ||
| 389 | case WDIOC_GETTIMEOUT: | ||
| 390 | return put_user(heartbeat, p); | ||
| 391 | } | 397 | } |
| 392 | } | 398 | } |
| 393 | 399 | ||
| @@ -405,7 +411,7 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 405 | 411 | ||
| 406 | static int wdt_open(struct inode *inode, struct file *file) | 412 | static int wdt_open(struct inode *inode, struct file *file) |
| 407 | { | 413 | { |
| 408 | if(test_and_set_bit(0, &wdt_is_open)) | 414 | if (test_and_set_bit(0, &wdt_is_open)) |
| 409 | return -EBUSY; | 415 | return -EBUSY; |
| 410 | /* | 416 | /* |
| 411 | * Activate | 417 | * Activate |
| @@ -432,7 +438,8 @@ static int wdt_release(struct inode *inode, struct file *file) | |||
| 432 | wdt_stop(); | 438 | wdt_stop(); |
| 433 | clear_bit(0, &wdt_is_open); | 439 | clear_bit(0, &wdt_is_open); |
| 434 | } else { | 440 | } else { |
| 435 | printk(KERN_CRIT "wdt: WDT device closed unexpectedly. WDT will not stop!\n"); | 441 | printk(KERN_CRIT |
| 442 | "wdt: WDT device closed unexpectedly. WDT will not stop!\n"); | ||
| 436 | wdt_ping(); | 443 | wdt_ping(); |
| 437 | } | 444 | } |
| 438 | expect_close = 0; | 445 | expect_close = 0; |
| @@ -451,14 +458,15 @@ static int wdt_release(struct inode *inode, struct file *file) | |||
| 451 | * farenheit. It was designed by an imperial measurement luddite. | 458 | * farenheit. It was designed by an imperial measurement luddite. |
| 452 | */ | 459 | */ |
| 453 | 460 | ||
| 454 | static ssize_t wdt_temp_read(struct file *file, char __user *buf, size_t count, loff_t *ptr) | 461 | static ssize_t wdt_temp_read(struct file *file, char __user *buf, |
| 462 | size_t count, loff_t *ptr) | ||
| 455 | { | 463 | { |
| 456 | int temperature; | 464 | int temperature; |
| 457 | 465 | ||
| 458 | if (wdt_get_temperature(&temperature)) | 466 | if (wdt_get_temperature(&temperature)) |
| 459 | return -EFAULT; | 467 | return -EFAULT; |
| 460 | 468 | ||
| 461 | if (copy_to_user (buf, &temperature, 1)) | 469 | if (copy_to_user(buf, &temperature, 1)) |
| 462 | return -EFAULT; | 470 | return -EFAULT; |
| 463 | 471 | ||
| 464 | return 1; | 472 | return 1; |
| @@ -506,10 +514,8 @@ static int wdt_temp_release(struct inode *inode, struct file *file) | |||
| 506 | static int wdt_notify_sys(struct notifier_block *this, unsigned long code, | 514 | static int wdt_notify_sys(struct notifier_block *this, unsigned long code, |
| 507 | void *unused) | 515 | void *unused) |
| 508 | { | 516 | { |
| 509 | if(code==SYS_DOWN || code==SYS_HALT) { | 517 | if (code == SYS_DOWN || code == SYS_HALT) |
| 510 | /* Turn the card off */ | ||
| 511 | wdt_stop(); | 518 | wdt_stop(); |
| 512 | } | ||
| 513 | return NOTIFY_DONE; | 519 | return NOTIFY_DONE; |
| 514 | } | 520 | } |
| 515 | 521 | ||
| @@ -522,7 +528,7 @@ static const struct file_operations wdt_fops = { | |||
| 522 | .owner = THIS_MODULE, | 528 | .owner = THIS_MODULE, |
| 523 | .llseek = no_llseek, | 529 | .llseek = no_llseek, |
| 524 | .write = wdt_write, | 530 | .write = wdt_write, |
| 525 | .ioctl = wdt_ioctl, | 531 | .unlocked_ioctl = wdt_ioctl, |
| 526 | .open = wdt_open, | 532 | .open = wdt_open, |
| 527 | .release = wdt_release, | 533 | .release = wdt_release, |
| 528 | }; | 534 | }; |
| @@ -576,7 +582,7 @@ static void __exit wdt_exit(void) | |||
| 576 | #endif /* CONFIG_WDT_501 */ | 582 | #endif /* CONFIG_WDT_501 */ |
| 577 | unregister_reboot_notifier(&wdt_notifier); | 583 | unregister_reboot_notifier(&wdt_notifier); |
| 578 | free_irq(irq, NULL); | 584 | free_irq(irq, NULL); |
| 579 | release_region(io,8); | 585 | release_region(io, 8); |
| 580 | } | 586 | } |
| 581 | 587 | ||
| 582 | /** | 588 | /** |
| @@ -591,44 +597,49 @@ static int __init wdt_init(void) | |||
| 591 | { | 597 | { |
| 592 | int ret; | 598 | int ret; |
| 593 | 599 | ||
| 594 | /* Check that the heartbeat value is within it's range ; if not reset to the default */ | 600 | /* Check that the heartbeat value is within it's range; |
| 601 | if not reset to the default */ | ||
| 595 | if (wdt_set_heartbeat(heartbeat)) { | 602 | if (wdt_set_heartbeat(heartbeat)) { |
| 596 | wdt_set_heartbeat(WD_TIMO); | 603 | wdt_set_heartbeat(WD_TIMO); |
| 597 | printk(KERN_INFO "wdt: heartbeat value must be 0<heartbeat<65536, using %d\n", | 604 | printk(KERN_INFO "wdt: heartbeat value must be 0 < heartbeat < 65536, using %d\n", |
| 598 | WD_TIMO); | 605 | WD_TIMO); |
| 599 | } | 606 | } |
| 600 | 607 | ||
| 601 | if (!request_region(io, 8, "wdt501p")) { | 608 | if (!request_region(io, 8, "wdt501p")) { |
| 602 | printk(KERN_ERR "wdt: I/O address 0x%04x already in use\n", io); | 609 | printk(KERN_ERR |
| 610 | "wdt: I/O address 0x%04x already in use\n", io); | ||
| 603 | ret = -EBUSY; | 611 | ret = -EBUSY; |
| 604 | goto out; | 612 | goto out; |
| 605 | } | 613 | } |
| 606 | 614 | ||
| 607 | ret = request_irq(irq, wdt_interrupt, IRQF_DISABLED, "wdt501p", NULL); | 615 | ret = request_irq(irq, wdt_interrupt, IRQF_DISABLED, "wdt501p", NULL); |
| 608 | if(ret) { | 616 | if (ret) { |
| 609 | printk(KERN_ERR "wdt: IRQ %d is not free.\n", irq); | 617 | printk(KERN_ERR "wdt: IRQ %d is not free.\n", irq); |
| 610 | goto outreg; | 618 | goto outreg; |
| 611 | } | 619 | } |
| 612 | 620 | ||
| 613 | ret = register_reboot_notifier(&wdt_notifier); | 621 | ret = register_reboot_notifier(&wdt_notifier); |
| 614 | if(ret) { | 622 | if (ret) { |
| 615 | printk(KERN_ERR "wdt: cannot register reboot notifier (err=%d)\n", ret); | 623 | printk(KERN_ERR |
| 624 | "wdt: cannot register reboot notifier (err=%d)\n", ret); | ||
| 616 | goto outirq; | 625 | goto outirq; |
| 617 | } | 626 | } |
| 618 | 627 | ||
| 619 | #ifdef CONFIG_WDT_501 | 628 | #ifdef CONFIG_WDT_501 |
| 620 | ret = misc_register(&temp_miscdev); | 629 | ret = misc_register(&temp_miscdev); |
| 621 | if (ret) { | 630 | if (ret) { |
| 622 | printk(KERN_ERR "wdt: cannot register miscdev on minor=%d (err=%d)\n", | 631 | printk(KERN_ERR |
| 623 | TEMP_MINOR, ret); | 632 | "wdt: cannot register miscdev on minor=%d (err=%d)\n", |
| 633 | TEMP_MINOR, ret); | ||
| 624 | goto outrbt; | 634 | goto outrbt; |
| 625 | } | 635 | } |
| 626 | #endif /* CONFIG_WDT_501 */ | 636 | #endif /* CONFIG_WDT_501 */ |
| 627 | 637 | ||
| 628 | ret = misc_register(&wdt_miscdev); | 638 | ret = misc_register(&wdt_miscdev); |
| 629 | if (ret) { | 639 | if (ret) { |
| 630 | printk(KERN_ERR "wdt: cannot register miscdev on minor=%d (err=%d)\n", | 640 | printk(KERN_ERR |
| 631 | WATCHDOG_MINOR, ret); | 641 | "wdt: cannot register miscdev on minor=%d (err=%d)\n", |
| 642 | WATCHDOG_MINOR, ret); | ||
| 632 | goto outmisc; | 643 | goto outmisc; |
| 633 | } | 644 | } |
| 634 | 645 | ||
| @@ -636,7 +647,8 @@ static int __init wdt_init(void) | |||
| 636 | printk(KERN_INFO "WDT500/501-P driver 0.10 at 0x%04x (Interrupt %d). heartbeat=%d sec (nowayout=%d)\n", | 647 | printk(KERN_INFO "WDT500/501-P driver 0.10 at 0x%04x (Interrupt %d). heartbeat=%d sec (nowayout=%d)\n", |
| 637 | io, irq, heartbeat, nowayout); | 648 | io, irq, heartbeat, nowayout); |
| 638 | #ifdef CONFIG_WDT_501 | 649 | #ifdef CONFIG_WDT_501 |
| 639 | printk(KERN_INFO "wdt: Fan Tachometer is %s\n", (tachometer ? "Enabled" : "Disabled")); | 650 | printk(KERN_INFO "wdt: Fan Tachometer is %s\n", |
| 651 | (tachometer ? "Enabled" : "Disabled")); | ||
| 640 | #endif /* CONFIG_WDT_501 */ | 652 | #endif /* CONFIG_WDT_501 */ |
| 641 | 653 | ||
| 642 | out: | 654 | out: |
| @@ -651,7 +663,7 @@ outrbt: | |||
| 651 | outirq: | 663 | outirq: |
| 652 | free_irq(irq, NULL); | 664 | free_irq(irq, NULL); |
| 653 | outreg: | 665 | outreg: |
| 654 | release_region(io,8); | 666 | release_region(io, 8); |
| 655 | goto out; | 667 | goto out; |
| 656 | } | 668 | } |
| 657 | 669 | ||
diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c index 1355608683e4..5d922fd6eafc 100644 --- a/drivers/watchdog/wdt_pci.c +++ b/drivers/watchdog/wdt_pci.c | |||
| @@ -29,9 +29,11 @@ | |||
| 29 | * JP Nollmann : Added support for PCI wdt501p | 29 | * JP Nollmann : Added support for PCI wdt501p |
| 30 | * Alan Cox : Split ISA and PCI cards into two drivers | 30 | * Alan Cox : Split ISA and PCI cards into two drivers |
| 31 | * Jeff Garzik : PCI cleanups | 31 | * Jeff Garzik : PCI cleanups |
| 32 | * Tigran Aivazian : Restructured wdtpci_init_one() to handle failures | 32 | * Tigran Aivazian : Restructured wdtpci_init_one() to handle |
| 33 | * failures | ||
| 33 | * Joel Becker : Added WDIOC_GET/SETTIMEOUT | 34 | * Joel Becker : Added WDIOC_GET/SETTIMEOUT |
| 34 | * Zwane Mwaikambo : Magic char closing, locking changes, cleanups | 35 | * Zwane Mwaikambo : Magic char closing, locking changes, |
| 36 | * cleanups | ||
| 35 | * Matt Domsch : nowayout module option | 37 | * Matt Domsch : nowayout module option |
| 36 | */ | 38 | */ |
| 37 | 39 | ||
| @@ -42,14 +44,15 @@ | |||
| 42 | #include <linux/miscdevice.h> | 44 | #include <linux/miscdevice.h> |
| 43 | #include <linux/watchdog.h> | 45 | #include <linux/watchdog.h> |
| 44 | #include <linux/ioport.h> | 46 | #include <linux/ioport.h> |
| 47 | #include <linux/delay.h> | ||
| 45 | #include <linux/notifier.h> | 48 | #include <linux/notifier.h> |
| 46 | #include <linux/reboot.h> | 49 | #include <linux/reboot.h> |
| 47 | #include <linux/init.h> | 50 | #include <linux/init.h> |
| 48 | #include <linux/fs.h> | 51 | #include <linux/fs.h> |
| 49 | #include <linux/pci.h> | 52 | #include <linux/pci.h> |
| 53 | #include <linux/io.h> | ||
| 54 | #include <linux/uaccess.h> | ||
| 50 | 55 | ||
| 51 | #include <asm/io.h> | ||
| 52 | #include <asm/uaccess.h> | ||
| 53 | #include <asm/system.h> | 56 | #include <asm/system.h> |
| 54 | 57 | ||
| 55 | #define WDT_IS_PCI | 58 | #define WDT_IS_PCI |
| @@ -73,7 +76,7 @@ | |||
| 73 | /* We can only use 1 card due to the /dev/watchdog restriction */ | 76 | /* We can only use 1 card due to the /dev/watchdog restriction */ |
| 74 | static int dev_count; | 77 | static int dev_count; |
| 75 | 78 | ||
| 76 | static struct semaphore open_sem; | 79 | static unsigned long open_lock; |
| 77 | static DEFINE_SPINLOCK(wdtpci_lock); | 80 | static DEFINE_SPINLOCK(wdtpci_lock); |
| 78 | static char expect_close; | 81 | static char expect_close; |
| 79 | 82 | ||
| @@ -86,18 +89,23 @@ static int irq; | |||
| 86 | static int heartbeat = WD_TIMO; | 89 | static int heartbeat = WD_TIMO; |
| 87 | static int wd_heartbeat; | 90 | static int wd_heartbeat; |
| 88 | module_param(heartbeat, int, 0); | 91 | module_param(heartbeat, int, 0); |
| 89 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")"); | 92 | MODULE_PARM_DESC(heartbeat, |
| 93 | "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" | ||
| 94 | __MODULE_STRING(WD_TIMO) ")"); | ||
| 90 | 95 | ||
| 91 | static int nowayout = WATCHDOG_NOWAYOUT; | 96 | static int nowayout = WATCHDOG_NOWAYOUT; |
| 92 | module_param(nowayout, int, 0); | 97 | module_param(nowayout, int, 0); |
| 93 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 98 | MODULE_PARM_DESC(nowayout, |
| 99 | "Watchdog cannot be stopped once started (default=" | ||
| 100 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
| 94 | 101 | ||
| 95 | #ifdef CONFIG_WDT_501_PCI | 102 | #ifdef CONFIG_WDT_501_PCI |
| 96 | /* Support for the Fan Tachometer on the PCI-WDT501 */ | 103 | /* Support for the Fan Tachometer on the PCI-WDT501 */ |
| 97 | static int tachometer; | 104 | static int tachometer; |
| 98 | 105 | ||
| 99 | module_param(tachometer, int, 0); | 106 | module_param(tachometer, int, 0); |
| 100 | MODULE_PARM_DESC(tachometer, "PCI-WDT501 Fan Tachometer support (0=disable, default=0)"); | 107 | MODULE_PARM_DESC(tachometer, |
| 108 | "PCI-WDT501 Fan Tachometer support (0=disable, default=0)"); | ||
| 101 | #endif /* CONFIG_WDT_501_PCI */ | 109 | #endif /* CONFIG_WDT_501_PCI */ |
| 102 | 110 | ||
| 103 | /* | 111 | /* |
| @@ -106,16 +114,19 @@ MODULE_PARM_DESC(tachometer, "PCI-WDT501 Fan Tachometer support (0=disable, defa | |||
| 106 | 114 | ||
| 107 | static void wdtpci_ctr_mode(int ctr, int mode) | 115 | static void wdtpci_ctr_mode(int ctr, int mode) |
| 108 | { | 116 | { |
| 109 | ctr<<=6; | 117 | ctr <<= 6; |
| 110 | ctr|=0x30; | 118 | ctr |= 0x30; |
| 111 | ctr|=(mode<<1); | 119 | ctr |= (mode << 1); |
| 112 | outb_p(ctr, WDT_CR); | 120 | outb(ctr, WDT_CR); |
| 121 | udelay(8); | ||
| 113 | } | 122 | } |
| 114 | 123 | ||
| 115 | static void wdtpci_ctr_load(int ctr, int val) | 124 | static void wdtpci_ctr_load(int ctr, int val) |
| 116 | { | 125 | { |
| 117 | outb_p(val&0xFF, WDT_COUNT0+ctr); | 126 | outb(val & 0xFF, WDT_COUNT0 + ctr); |
| 118 | outb_p(val>>8, WDT_COUNT0+ctr); | 127 | udelay(8); |
| 128 | outb(val >> 8, WDT_COUNT0 + ctr); | ||
| 129 | udelay(8); | ||
| 119 | } | 130 | } |
| 120 | 131 | ||
| 121 | /** | 132 | /** |
| @@ -134,23 +145,35 @@ static int wdtpci_start(void) | |||
| 134 | * "pet" the watchdog, as Access says. | 145 | * "pet" the watchdog, as Access says. |
| 135 | * This resets the clock outputs. | 146 | * This resets the clock outputs. |
| 136 | */ | 147 | */ |
| 137 | inb_p(WDT_DC); /* Disable watchdog */ | 148 | inb(WDT_DC); /* Disable watchdog */ |
| 138 | wdtpci_ctr_mode(2,0); /* Program CTR2 for Mode 0: Pulse on Terminal Count */ | 149 | udelay(8); |
| 139 | outb_p(0, WDT_DC); /* Enable watchdog */ | 150 | wdtpci_ctr_mode(2, 0); /* Program CTR2 for Mode 0: |
| 140 | 151 | Pulse on Terminal Count */ | |
| 141 | inb_p(WDT_DC); /* Disable watchdog */ | 152 | outb(0, WDT_DC); /* Enable watchdog */ |
| 142 | outb_p(0, WDT_CLOCK); /* 2.0833MHz clock */ | 153 | udelay(8); |
| 143 | inb_p(WDT_BUZZER); /* disable */ | 154 | inb(WDT_DC); /* Disable watchdog */ |
| 144 | inb_p(WDT_OPTONOTRST); /* disable */ | 155 | udelay(8); |
| 145 | inb_p(WDT_OPTORST); /* disable */ | 156 | outb(0, WDT_CLOCK); /* 2.0833MHz clock */ |
| 146 | inb_p(WDT_PROGOUT); /* disable */ | 157 | udelay(8); |
| 147 | wdtpci_ctr_mode(0,3); /* Program CTR0 for Mode 3: Square Wave Generator */ | 158 | inb(WDT_BUZZER); /* disable */ |
| 148 | wdtpci_ctr_mode(1,2); /* Program CTR1 for Mode 2: Rate Generator */ | 159 | udelay(8); |
| 149 | wdtpci_ctr_mode(2,1); /* Program CTR2 for Mode 1: Retriggerable One-Shot */ | 160 | inb(WDT_OPTONOTRST); /* disable */ |
| 150 | wdtpci_ctr_load(0,20833); /* count at 100Hz */ | 161 | udelay(8); |
| 151 | wdtpci_ctr_load(1,wd_heartbeat);/* Heartbeat */ | 162 | inb(WDT_OPTORST); /* disable */ |
| 163 | udelay(8); | ||
| 164 | inb(WDT_PROGOUT); /* disable */ | ||
| 165 | udelay(8); | ||
| 166 | wdtpci_ctr_mode(0, 3); /* Program CTR0 for Mode 3: | ||
| 167 | Square Wave Generator */ | ||
| 168 | wdtpci_ctr_mode(1, 2); /* Program CTR1 for Mode 2: | ||
| 169 | Rate Generator */ | ||
| 170 | wdtpci_ctr_mode(2, 1); /* Program CTR2 for Mode 1: | ||
| 171 | Retriggerable One-Shot */ | ||
| 172 | wdtpci_ctr_load(0, 20833); /* count at 100Hz */ | ||
| 173 | wdtpci_ctr_load(1, wd_heartbeat);/* Heartbeat */ | ||
| 152 | /* DO NOT LOAD CTR2 on PCI card! -- JPN */ | 174 | /* DO NOT LOAD CTR2 on PCI card! -- JPN */ |
| 153 | outb_p(0, WDT_DC); /* Enable watchdog */ | 175 | outb(0, WDT_DC); /* Enable watchdog */ |
| 176 | udelay(8); | ||
| 154 | 177 | ||
| 155 | spin_unlock_irqrestore(&wdtpci_lock, flags); | 178 | spin_unlock_irqrestore(&wdtpci_lock, flags); |
| 156 | return 0; | 179 | return 0; |
| @@ -162,14 +185,15 @@ static int wdtpci_start(void) | |||
| 162 | * Stop the watchdog driver. | 185 | * Stop the watchdog driver. |
| 163 | */ | 186 | */ |
| 164 | 187 | ||
| 165 | static int wdtpci_stop (void) | 188 | static int wdtpci_stop(void) |
| 166 | { | 189 | { |
| 167 | unsigned long flags; | 190 | unsigned long flags; |
| 168 | 191 | ||
| 169 | /* Turn the card off */ | 192 | /* Turn the card off */ |
| 170 | spin_lock_irqsave(&wdtpci_lock, flags); | 193 | spin_lock_irqsave(&wdtpci_lock, flags); |
| 171 | inb_p(WDT_DC); /* Disable watchdog */ | 194 | inb(WDT_DC); /* Disable watchdog */ |
| 172 | wdtpci_ctr_load(2,0); /* 0 length reset pulses now */ | 195 | udelay(8); |
| 196 | wdtpci_ctr_load(2, 0); /* 0 length reset pulses now */ | ||
| 173 | spin_unlock_irqrestore(&wdtpci_lock, flags); | 197 | spin_unlock_irqrestore(&wdtpci_lock, flags); |
| 174 | return 0; | 198 | return 0; |
| 175 | } | 199 | } |
| @@ -177,20 +201,23 @@ static int wdtpci_stop (void) | |||
| 177 | /** | 201 | /** |
| 178 | * wdtpci_ping: | 202 | * wdtpci_ping: |
| 179 | * | 203 | * |
| 180 | * Reload counter one with the watchdog heartbeat. We don't bother reloading | 204 | * Reload counter one with the watchdog heartbeat. We don't bother |
| 181 | * the cascade counter. | 205 | * reloading the cascade counter. |
| 182 | */ | 206 | */ |
| 183 | 207 | ||
| 184 | static int wdtpci_ping(void) | 208 | static int wdtpci_ping(void) |
| 185 | { | 209 | { |
| 186 | unsigned long flags; | 210 | unsigned long flags; |
| 187 | 211 | ||
| 188 | /* Write a watchdog value */ | ||
| 189 | spin_lock_irqsave(&wdtpci_lock, flags); | 212 | spin_lock_irqsave(&wdtpci_lock, flags); |
| 190 | inb_p(WDT_DC); /* Disable watchdog */ | 213 | /* Write a watchdog value */ |
| 191 | wdtpci_ctr_mode(1,2); /* Re-Program CTR1 for Mode 2: Rate Generator */ | 214 | inb(WDT_DC); /* Disable watchdog */ |
| 192 | wdtpci_ctr_load(1,wd_heartbeat);/* Heartbeat */ | 215 | udelay(8); |
| 193 | outb_p(0, WDT_DC); /* Enable watchdog */ | 216 | wdtpci_ctr_mode(1, 2); /* Re-Program CTR1 for Mode 2: |
| 217 | Rate Generator */ | ||
| 218 | wdtpci_ctr_load(1, wd_heartbeat);/* Heartbeat */ | ||
| 219 | outb(0, WDT_DC); /* Enable watchdog */ | ||
| 220 | udelay(8); | ||
| 194 | spin_unlock_irqrestore(&wdtpci_lock, flags); | 221 | spin_unlock_irqrestore(&wdtpci_lock, flags); |
| 195 | return 0; | 222 | return 0; |
| 196 | } | 223 | } |
| @@ -199,14 +226,14 @@ static int wdtpci_ping(void) | |||
| 199 | * wdtpci_set_heartbeat: | 226 | * wdtpci_set_heartbeat: |
| 200 | * @t: the new heartbeat value that needs to be set. | 227 | * @t: the new heartbeat value that needs to be set. |
| 201 | * | 228 | * |
| 202 | * Set a new heartbeat value for the watchdog device. If the heartbeat value is | 229 | * Set a new heartbeat value for the watchdog device. If the heartbeat |
| 203 | * incorrect we keep the old value and return -EINVAL. If successfull we | 230 | * value is incorrect we keep the old value and return -EINVAL. |
| 204 | * return 0. | 231 | * If successful we return 0. |
| 205 | */ | 232 | */ |
| 206 | static int wdtpci_set_heartbeat(int t) | 233 | static int wdtpci_set_heartbeat(int t) |
| 207 | { | 234 | { |
| 208 | /* Arbitrary, can't find the card's limits */ | 235 | /* Arbitrary, can't find the card's limits */ |
| 209 | if ((t < 1) || (t > 65535)) | 236 | if (t < 1 || t > 65535) |
| 210 | return -EINVAL; | 237 | return -EINVAL; |
| 211 | 238 | ||
| 212 | heartbeat = t; | 239 | heartbeat = t; |
| @@ -227,9 +254,14 @@ static int wdtpci_set_heartbeat(int t) | |||
| 227 | 254 | ||
| 228 | static int wdtpci_get_status(int *status) | 255 | static int wdtpci_get_status(int *status) |
| 229 | { | 256 | { |
| 230 | unsigned char new_status=inb_p(WDT_SR); | 257 | unsigned char new_status; |
| 258 | unsigned long flags; | ||
| 259 | |||
| 260 | spin_lock_irqsave(&wdtpci_lock, flags); | ||
| 261 | new_status = inb(WDT_SR); | ||
| 262 | spin_unlock_irqrestore(&wdtpci_lock, flags); | ||
| 231 | 263 | ||
| 232 | *status=0; | 264 | *status = 0; |
| 233 | if (new_status & WDC_SR_ISOI0) | 265 | if (new_status & WDC_SR_ISOI0) |
| 234 | *status |= WDIOF_EXTERN1; | 266 | *status |= WDIOF_EXTERN1; |
| 235 | if (new_status & WDC_SR_ISII1) | 267 | if (new_status & WDC_SR_ISII1) |
| @@ -259,8 +291,12 @@ static int wdtpci_get_status(int *status) | |||
| 259 | 291 | ||
| 260 | static int wdtpci_get_temperature(int *temperature) | 292 | static int wdtpci_get_temperature(int *temperature) |
| 261 | { | 293 | { |
| 262 | unsigned short c=inb_p(WDT_RT); | 294 | unsigned short c; |
| 263 | 295 | unsigned long flags; | |
| 296 | spin_lock_irqsave(&wdtpci_lock, flags); | ||
| 297 | c = inb(WDT_RT); | ||
| 298 | udelay(8); | ||
| 299 | spin_unlock_irqrestore(&wdtpci_lock, flags); | ||
| 264 | *temperature = (c * 11 / 15) + 7; | 300 | *temperature = (c * 11 / 15) + 7; |
| 265 | return 0; | 301 | return 0; |
| 266 | } | 302 | } |
| @@ -282,17 +318,25 @@ static irqreturn_t wdtpci_interrupt(int irq, void *dev_id) | |||
| 282 | * Read the status register see what is up and | 318 | * Read the status register see what is up and |
| 283 | * then printk it. | 319 | * then printk it. |
| 284 | */ | 320 | */ |
| 285 | unsigned char status=inb_p(WDT_SR); | 321 | unsigned char status; |
| 322 | |||
| 323 | spin_lock(&wdtpci_lock); | ||
| 324 | |||
| 325 | status = inb(WDT_SR); | ||
| 326 | udelay(8); | ||
| 286 | 327 | ||
| 287 | printk(KERN_CRIT PFX "status %d\n", status); | 328 | printk(KERN_CRIT PFX "status %d\n", status); |
| 288 | 329 | ||
| 289 | #ifdef CONFIG_WDT_501_PCI | 330 | #ifdef CONFIG_WDT_501_PCI |
| 290 | if (!(status & WDC_SR_TGOOD)) | 331 | if (!(status & WDC_SR_TGOOD)) { |
| 291 | printk(KERN_CRIT PFX "Overheat alarm.(%d)\n",inb_p(WDT_RT)); | 332 | u8 alarm = inb(WDT_RT); |
| 333 | printk(KERN_CRIT PFX "Overheat alarm.(%d)\n", alarm); | ||
| 334 | udelay(8); | ||
| 335 | } | ||
| 292 | if (!(status & WDC_SR_PSUOVER)) | 336 | if (!(status & WDC_SR_PSUOVER)) |
| 293 | printk(KERN_CRIT PFX "PSU over voltage.\n"); | 337 | printk(KERN_CRIT PFX "PSU over voltage.\n"); |
| 294 | if (!(status & WDC_SR_PSUUNDR)) | 338 | if (!(status & WDC_SR_PSUUNDR)) |
| 295 | printk(KERN_CRIT PFX "PSU under voltage.\n"); | 339 | printk(KERN_CRIT PFX "PSU under voltage.\n"); |
| 296 | if (tachometer) { | 340 | if (tachometer) { |
| 297 | if (!(status & WDC_SR_FANGOOD)) | 341 | if (!(status & WDC_SR_FANGOOD)) |
| 298 | printk(KERN_CRIT PFX "Possible fan fault.\n"); | 342 | printk(KERN_CRIT PFX "Possible fan fault.\n"); |
| @@ -310,6 +354,7 @@ static irqreturn_t wdtpci_interrupt(int irq, void *dev_id) | |||
| 310 | printk(KERN_CRIT PFX "Reset in 5ms.\n"); | 354 | printk(KERN_CRIT PFX "Reset in 5ms.\n"); |
| 311 | #endif | 355 | #endif |
| 312 | } | 356 | } |
| 357 | spin_unlock(&wdtpci_lock); | ||
| 313 | return IRQ_HANDLED; | 358 | return IRQ_HANDLED; |
| 314 | } | 359 | } |
| 315 | 360 | ||
| @@ -325,7 +370,8 @@ static irqreturn_t wdtpci_interrupt(int irq, void *dev_id) | |||
| 325 | * write of data will do, as we we don't define content meaning. | 370 | * write of data will do, as we we don't define content meaning. |
| 326 | */ | 371 | */ |
| 327 | 372 | ||
| 328 | static ssize_t wdtpci_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | 373 | static ssize_t wdtpci_write(struct file *file, const char __user *buf, |
| 374 | size_t count, loff_t *ppos) | ||
| 329 | { | 375 | { |
| 330 | if (count) { | 376 | if (count) { |
| 331 | if (!nowayout) { | 377 | if (!nowayout) { |
| @@ -335,7 +381,7 @@ static ssize_t wdtpci_write(struct file *file, const char __user *buf, size_t co | |||
| 335 | 381 | ||
| 336 | for (i = 0; i != count; i++) { | 382 | for (i = 0; i != count; i++) { |
| 337 | char c; | 383 | char c; |
| 338 | if(get_user(c, buf+i)) | 384 | if (get_user(c, buf+i)) |
| 339 | return -EFAULT; | 385 | return -EFAULT; |
| 340 | if (c == 'V') | 386 | if (c == 'V') |
| 341 | expect_close = 42; | 387 | expect_close = 42; |
| @@ -343,13 +389,11 @@ static ssize_t wdtpci_write(struct file *file, const char __user *buf, size_t co | |||
| 343 | } | 389 | } |
| 344 | wdtpci_ping(); | 390 | wdtpci_ping(); |
| 345 | } | 391 | } |
| 346 | |||
| 347 | return count; | 392 | return count; |
| 348 | } | 393 | } |
| 349 | 394 | ||
| 350 | /** | 395 | /** |
| 351 | * wdtpci_ioctl: | 396 | * wdtpci_ioctl: |
| 352 | * @inode: inode of the device | ||
| 353 | * @file: file handle to the device | 397 | * @file: file handle to the device |
| 354 | * @cmd: watchdog command | 398 | * @cmd: watchdog command |
| 355 | * @arg: argument pointer | 399 | * @arg: argument pointer |
| @@ -359,8 +403,8 @@ static ssize_t wdtpci_write(struct file *file, const char __user *buf, size_t co | |||
| 359 | * querying capabilities and current status. | 403 | * querying capabilities and current status. |
| 360 | */ | 404 | */ |
| 361 | 405 | ||
| 362 | static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 406 | static long wdtpci_ioctl(struct file *file, unsigned int cmd, |
| 363 | unsigned long arg) | 407 | unsigned long arg) |
| 364 | { | 408 | { |
| 365 | int new_heartbeat; | 409 | int new_heartbeat; |
| 366 | int status; | 410 | int status; |
| @@ -383,33 +427,29 @@ static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
| 383 | ident.options |= WDIOF_FANFAULT; | 427 | ident.options |= WDIOF_FANFAULT; |
| 384 | #endif /* CONFIG_WDT_501_PCI */ | 428 | #endif /* CONFIG_WDT_501_PCI */ |
| 385 | 429 | ||
| 386 | switch(cmd) | 430 | switch (cmd) { |
| 387 | { | 431 | default: |
| 388 | default: | 432 | return -ENOTTY; |
| 389 | return -ENOTTY; | 433 | case WDIOC_GETSUPPORT: |
| 390 | case WDIOC_GETSUPPORT: | 434 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; |
| 391 | return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; | 435 | case WDIOC_GETSTATUS: |
| 392 | 436 | wdtpci_get_status(&status); | |
| 393 | case WDIOC_GETSTATUS: | 437 | return put_user(status, p); |
| 394 | wdtpci_get_status(&status); | 438 | case WDIOC_GETBOOTSTATUS: |
| 395 | return put_user(status, p); | 439 | return put_user(0, p); |
| 396 | case WDIOC_GETBOOTSTATUS: | 440 | case WDIOC_KEEPALIVE: |
| 397 | return put_user(0, p); | 441 | wdtpci_ping(); |
| 398 | case WDIOC_KEEPALIVE: | 442 | return 0; |
| 399 | wdtpci_ping(); | 443 | case WDIOC_SETTIMEOUT: |
| 400 | return 0; | 444 | if (get_user(new_heartbeat, p)) |
| 401 | case WDIOC_SETTIMEOUT: | 445 | return -EFAULT; |
| 402 | if (get_user(new_heartbeat, p)) | 446 | if (wdtpci_set_heartbeat(new_heartbeat)) |
| 403 | return -EFAULT; | 447 | return -EINVAL; |
| 404 | 448 | wdtpci_ping(); | |
| 405 | if (wdtpci_set_heartbeat(new_heartbeat)) | 449 | /* Fall */ |
| 406 | return -EINVAL; | 450 | case WDIOC_GETTIMEOUT: |
| 407 | 451 | return put_user(heartbeat, p); | |
| 408 | wdtpci_ping(); | 452 | } |
| 409 | /* Fall */ | ||
| 410 | case WDIOC_GETTIMEOUT: | ||
| 411 | return put_user(heartbeat, p); | ||
| 412 | } | ||
| 413 | } | 453 | } |
| 414 | 454 | ||
| 415 | /** | 455 | /** |
| @@ -426,12 +466,11 @@ static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
| 426 | 466 | ||
| 427 | static int wdtpci_open(struct inode *inode, struct file *file) | 467 | static int wdtpci_open(struct inode *inode, struct file *file) |
| 428 | { | 468 | { |
| 429 | if (down_trylock(&open_sem)) | 469 | if (test_and_set_bit(0, &open_lock)) |
| 430 | return -EBUSY; | 470 | return -EBUSY; |
| 431 | 471 | ||
| 432 | if (nowayout) { | 472 | if (nowayout) |
| 433 | __module_get(THIS_MODULE); | 473 | __module_get(THIS_MODULE); |
| 434 | } | ||
| 435 | /* | 474 | /* |
| 436 | * Activate | 475 | * Activate |
| 437 | */ | 476 | */ |
| @@ -460,7 +499,7 @@ static int wdtpci_release(struct inode *inode, struct file *file) | |||
| 460 | wdtpci_ping(); | 499 | wdtpci_ping(); |
| 461 | } | 500 | } |
| 462 | expect_close = 0; | 501 | expect_close = 0; |
| 463 | up(&open_sem); | 502 | clear_bit(0, &open_lock); |
| 464 | return 0; | 503 | return 0; |
| 465 | } | 504 | } |
| 466 | 505 | ||
| @@ -476,14 +515,15 @@ static int wdtpci_release(struct inode *inode, struct file *file) | |||
| 476 | * fahrenheit. It was designed by an imperial measurement luddite. | 515 | * fahrenheit. It was designed by an imperial measurement luddite. |
| 477 | */ | 516 | */ |
| 478 | 517 | ||
| 479 | static ssize_t wdtpci_temp_read(struct file *file, char __user *buf, size_t count, loff_t *ptr) | 518 | static ssize_t wdtpci_temp_read(struct file *file, char __user *buf, |
| 519 | size_t count, loff_t *ptr) | ||
| 480 | { | 520 | { |
| 481 | int temperature; | 521 | int temperature; |
| 482 | 522 | ||
| 483 | if (wdtpci_get_temperature(&temperature)) | 523 | if (wdtpci_get_temperature(&temperature)) |
| 484 | return -EFAULT; | 524 | return -EFAULT; |
| 485 | 525 | ||
| 486 | if (copy_to_user (buf, &temperature, 1)) | 526 | if (copy_to_user(buf, &temperature, 1)) |
| 487 | return -EFAULT; | 527 | return -EFAULT; |
| 488 | 528 | ||
| 489 | return 1; | 529 | return 1; |
| @@ -529,12 +569,10 @@ static int wdtpci_temp_release(struct inode *inode, struct file *file) | |||
| 529 | */ | 569 | */ |
| 530 | 570 | ||
| 531 | static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code, | 571 | static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code, |
| 532 | void *unused) | 572 | void *unused) |
| 533 | { | 573 | { |
| 534 | if (code==SYS_DOWN || code==SYS_HALT) { | 574 | if (code == SYS_DOWN || code == SYS_HALT) |
| 535 | /* Turn the card off */ | ||
| 536 | wdtpci_stop(); | 575 | wdtpci_stop(); |
| 537 | } | ||
| 538 | return NOTIFY_DONE; | 576 | return NOTIFY_DONE; |
| 539 | } | 577 | } |
| 540 | 578 | ||
| @@ -547,7 +585,7 @@ static const struct file_operations wdtpci_fops = { | |||
| 547 | .owner = THIS_MODULE, | 585 | .owner = THIS_MODULE, |
| 548 | .llseek = no_llseek, | 586 | .llseek = no_llseek, |
| 549 | .write = wdtpci_write, | 587 | .write = wdtpci_write, |
| 550 | .ioctl = wdtpci_ioctl, | 588 | .unlocked_ioctl = wdtpci_ioctl, |
| 551 | .open = wdtpci_open, | 589 | .open = wdtpci_open, |
| 552 | .release = wdtpci_release, | 590 | .release = wdtpci_release, |
| 553 | }; | 591 | }; |
| @@ -584,80 +622,85 @@ static struct notifier_block wdtpci_notifier = { | |||
| 584 | }; | 622 | }; |
| 585 | 623 | ||
| 586 | 624 | ||
| 587 | static int __devinit wdtpci_init_one (struct pci_dev *dev, | 625 | static int __devinit wdtpci_init_one(struct pci_dev *dev, |
| 588 | const struct pci_device_id *ent) | 626 | const struct pci_device_id *ent) |
| 589 | { | 627 | { |
| 590 | int ret = -EIO; | 628 | int ret = -EIO; |
| 591 | 629 | ||
| 592 | dev_count++; | 630 | dev_count++; |
| 593 | if (dev_count > 1) { | 631 | if (dev_count > 1) { |
| 594 | printk (KERN_ERR PFX "this driver only supports 1 device\n"); | 632 | printk(KERN_ERR PFX "This driver only supports one device\n"); |
| 595 | return -ENODEV; | 633 | return -ENODEV; |
| 596 | } | 634 | } |
| 597 | 635 | ||
| 598 | if (pci_enable_device (dev)) { | 636 | if (pci_enable_device(dev)) { |
| 599 | printk (KERN_ERR PFX "Not possible to enable PCI Device\n"); | 637 | printk(KERN_ERR PFX "Not possible to enable PCI Device\n"); |
| 600 | return -ENODEV; | 638 | return -ENODEV; |
| 601 | } | 639 | } |
| 602 | 640 | ||
| 603 | if (pci_resource_start (dev, 2) == 0x0000) { | 641 | if (pci_resource_start(dev, 2) == 0x0000) { |
| 604 | printk (KERN_ERR PFX "No I/O-Address for card detected\n"); | 642 | printk(KERN_ERR PFX "No I/O-Address for card detected\n"); |
| 605 | ret = -ENODEV; | 643 | ret = -ENODEV; |
| 606 | goto out_pci; | 644 | goto out_pci; |
| 607 | } | 645 | } |
| 608 | 646 | ||
| 609 | sema_init(&open_sem, 1); | ||
| 610 | |||
| 611 | irq = dev->irq; | 647 | irq = dev->irq; |
| 612 | io = pci_resource_start (dev, 2); | 648 | io = pci_resource_start(dev, 2); |
| 613 | 649 | ||
| 614 | if (request_region (io, 16, "wdt_pci") == NULL) { | 650 | if (request_region(io, 16, "wdt_pci") == NULL) { |
| 615 | printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", io); | 651 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", io); |
| 616 | goto out_pci; | 652 | goto out_pci; |
| 617 | } | 653 | } |
| 618 | 654 | ||
| 619 | if (request_irq (irq, wdtpci_interrupt, IRQF_DISABLED | IRQF_SHARED, | 655 | if (request_irq(irq, wdtpci_interrupt, IRQF_DISABLED | IRQF_SHARED, |
| 620 | "wdt_pci", &wdtpci_miscdev)) { | 656 | "wdt_pci", &wdtpci_miscdev)) { |
| 621 | printk (KERN_ERR PFX "IRQ %d is not free\n", irq); | 657 | printk(KERN_ERR PFX "IRQ %d is not free\n", irq); |
| 622 | goto out_reg; | 658 | goto out_reg; |
| 623 | } | 659 | } |
| 624 | 660 | ||
| 625 | printk ("PCI-WDT500/501 (PCI-WDG-CSM) driver 0.10 at 0x%04x (Interrupt %d)\n", | 661 | printk(KERN_INFO |
| 626 | io, irq); | 662 | "PCI-WDT500/501 (PCI-WDG-CSM) driver 0.10 at 0x%04x (Interrupt %d)\n", |
| 663 | io, irq); | ||
| 627 | 664 | ||
| 628 | /* Check that the heartbeat value is within it's range ; if not reset to the default */ | 665 | /* Check that the heartbeat value is within its range; |
| 666 | if not reset to the default */ | ||
| 629 | if (wdtpci_set_heartbeat(heartbeat)) { | 667 | if (wdtpci_set_heartbeat(heartbeat)) { |
| 630 | wdtpci_set_heartbeat(WD_TIMO); | 668 | wdtpci_set_heartbeat(WD_TIMO); |
| 631 | printk(KERN_INFO PFX "heartbeat value must be 0<heartbeat<65536, using %d\n", | 669 | printk(KERN_INFO PFX |
| 632 | WD_TIMO); | 670 | "heartbeat value must be 0 < heartbeat < 65536, using %d\n", |
| 671 | WD_TIMO); | ||
| 633 | } | 672 | } |
| 634 | 673 | ||
| 635 | ret = register_reboot_notifier (&wdtpci_notifier); | 674 | ret = register_reboot_notifier(&wdtpci_notifier); |
| 636 | if (ret) { | 675 | if (ret) { |
| 637 | printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); | 676 | printk(KERN_ERR PFX |
| 677 | "cannot register reboot notifier (err=%d)\n", ret); | ||
| 638 | goto out_irq; | 678 | goto out_irq; |
| 639 | } | 679 | } |
| 640 | 680 | ||
| 641 | #ifdef CONFIG_WDT_501_PCI | 681 | #ifdef CONFIG_WDT_501_PCI |
| 642 | ret = misc_register (&temp_miscdev); | 682 | ret = misc_register(&temp_miscdev); |
| 643 | if (ret) { | 683 | if (ret) { |
| 644 | printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 684 | printk(KERN_ERR PFX |
| 645 | TEMP_MINOR, ret); | 685 | "cannot register miscdev on minor=%d (err=%d)\n", |
| 686 | TEMP_MINOR, ret); | ||
| 646 | goto out_rbt; | 687 | goto out_rbt; |
| 647 | } | 688 | } |
| 648 | #endif /* CONFIG_WDT_501_PCI */ | 689 | #endif /* CONFIG_WDT_501_PCI */ |
| 649 | 690 | ||
| 650 | ret = misc_register (&wdtpci_miscdev); | 691 | ret = misc_register(&wdtpci_miscdev); |
| 651 | if (ret) { | 692 | if (ret) { |
| 652 | printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 693 | printk(KERN_ERR PFX |
| 653 | WATCHDOG_MINOR, ret); | 694 | "cannot register miscdev on minor=%d (err=%d)\n", |
| 695 | WATCHDOG_MINOR, ret); | ||
| 654 | goto out_misc; | 696 | goto out_misc; |
| 655 | } | 697 | } |
| 656 | 698 | ||
| 657 | printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", | 699 | printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", |
| 658 | heartbeat, nowayout); | 700 | heartbeat, nowayout); |
| 659 | #ifdef CONFIG_WDT_501_PCI | 701 | #ifdef CONFIG_WDT_501_PCI |
| 660 | printk(KERN_INFO "wdt: Fan Tachometer is %s\n", (tachometer ? "Enabled" : "Disabled")); | 702 | printk(KERN_INFO "wdt: Fan Tachometer is %s\n", |
| 703 | (tachometer ? "Enabled" : "Disabled")); | ||
| 661 | #endif /* CONFIG_WDT_501_PCI */ | 704 | #endif /* CONFIG_WDT_501_PCI */ |
| 662 | 705 | ||
| 663 | ret = 0; | 706 | ret = 0; |
| @@ -673,14 +716,14 @@ out_rbt: | |||
| 673 | out_irq: | 716 | out_irq: |
| 674 | free_irq(irq, &wdtpci_miscdev); | 717 | free_irq(irq, &wdtpci_miscdev); |
| 675 | out_reg: | 718 | out_reg: |
| 676 | release_region (io, 16); | 719 | release_region(io, 16); |
| 677 | out_pci: | 720 | out_pci: |
| 678 | pci_disable_device(dev); | 721 | pci_disable_device(dev); |
| 679 | goto out; | 722 | goto out; |
| 680 | } | 723 | } |
| 681 | 724 | ||
| 682 | 725 | ||
| 683 | static void __devexit wdtpci_remove_one (struct pci_dev *pdev) | 726 | static void __devexit wdtpci_remove_one(struct pci_dev *pdev) |
| 684 | { | 727 | { |
| 685 | /* here we assume only one device will ever have | 728 | /* here we assume only one device will ever have |
| 686 | * been picked up and registered by probe function */ | 729 | * been picked up and registered by probe function */ |
| @@ -728,7 +771,7 @@ static struct pci_driver wdtpci_driver = { | |||
| 728 | 771 | ||
| 729 | static void __exit wdtpci_cleanup(void) | 772 | static void __exit wdtpci_cleanup(void) |
| 730 | { | 773 | { |
| 731 | pci_unregister_driver (&wdtpci_driver); | 774 | pci_unregister_driver(&wdtpci_driver); |
| 732 | } | 775 | } |
| 733 | 776 | ||
| 734 | 777 | ||
| @@ -742,7 +785,7 @@ static void __exit wdtpci_cleanup(void) | |||
| 742 | 785 | ||
| 743 | static int __init wdtpci_init(void) | 786 | static int __init wdtpci_init(void) |
| 744 | { | 787 | { |
| 745 | return pci_register_driver (&wdtpci_driver); | 788 | return pci_register_driver(&wdtpci_driver); |
| 746 | } | 789 | } |
| 747 | 790 | ||
| 748 | 791 | ||
