diff options
| author | Jeff Garzik <jeff@garzik.org> | 2006-05-02 14:33:57 -0400 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2006-05-02 14:33:57 -0400 |
| commit | 1fb5fef9b80d9a3b5368e22031627afd1585487b (patch) | |
| tree | 54f07a532b5b2622b8642156bbcaeca637fcdb8f /drivers | |
| parent | 1a2e8a6f8ec0a068911a882a19e0912a0c89be6e (diff) | |
| parent | 330ab71619bacc4d4494227a6cfc9b7f5500403d (diff) | |
Merge branch 'master' into upstream
Diffstat (limited to 'drivers')
69 files changed, 1277 insertions, 2494 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig index 5c91d6afb117..aeb5ab2391e4 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig | |||
| @@ -68,8 +68,6 @@ source "drivers/leds/Kconfig" | |||
| 68 | 68 | ||
| 69 | source "drivers/infiniband/Kconfig" | 69 | source "drivers/infiniband/Kconfig" |
| 70 | 70 | ||
| 71 | source "drivers/sn/Kconfig" | ||
| 72 | |||
| 73 | source "drivers/edac/Kconfig" | 71 | source "drivers/edac/Kconfig" |
| 74 | 72 | ||
| 75 | source "drivers/rtc/Kconfig" | 73 | source "drivers/rtc/Kconfig" |
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index bedb689b051f..dff1e67b1dd4 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
| @@ -4301,7 +4301,7 @@ static int __init floppy_init(void) | |||
| 4301 | } | 4301 | } |
| 4302 | 4302 | ||
| 4303 | use_virtual_dma = can_use_virtual_dma & 1; | 4303 | use_virtual_dma = can_use_virtual_dma & 1; |
| 4304 | #if defined(CONFIG_PPC64) | 4304 | #if defined(CONFIG_PPC_MERGE) |
| 4305 | if (check_legacy_ioport(FDC1)) { | 4305 | if (check_legacy_ioport(FDC1)) { |
| 4306 | del_timer(&fd_timeout); | 4306 | del_timer(&fd_timeout); |
| 4307 | err = -ENODEV; | 4307 | err = -ENODEV; |
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c index d3a2bc36129b..588fca542a98 100644 --- a/drivers/char/genrtc.c +++ b/drivers/char/genrtc.c | |||
| @@ -200,13 +200,13 @@ static ssize_t gen_rtc_read(struct file *file, char __user *buf, | |||
| 200 | /* first test allows optimizer to nuke this case for 32-bit machines */ | 200 | /* first test allows optimizer to nuke this case for 32-bit machines */ |
| 201 | if (sizeof (int) != sizeof (long) && count == sizeof (unsigned int)) { | 201 | if (sizeof (int) != sizeof (long) && count == sizeof (unsigned int)) { |
| 202 | unsigned int uidata = data; | 202 | unsigned int uidata = data; |
| 203 | retval = put_user(uidata, (unsigned long __user *)buf); | 203 | retval = put_user(uidata, (unsigned int __user *)buf) ?: |
| 204 | sizeof(unsigned int); | ||
| 204 | } | 205 | } |
| 205 | else { | 206 | else { |
| 206 | retval = put_user(data, (unsigned long __user *)buf); | 207 | retval = put_user(data, (unsigned long __user *)buf) ?: |
| 208 | sizeof(unsigned long); | ||
| 207 | } | 209 | } |
| 208 | if (!retval) | ||
| 209 | retval = sizeof(unsigned long); | ||
| 210 | out: | 210 | out: |
| 211 | current->state = TASK_RUNNING; | 211 | current->state = TASK_RUNNING; |
| 212 | remove_wait_queue(&gen_rtc_wait, &wait); | 212 | remove_wait_queue(&gen_rtc_wait, &wait); |
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 935670a3cd98..5755b7e5f187 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
| @@ -860,9 +860,32 @@ static void k_slock(struct vc_data *vc, unsigned char value, char up_flag, struc | |||
| 860 | } | 860 | } |
| 861 | 861 | ||
| 862 | /* by default, 300ms interval for combination release */ | 862 | /* by default, 300ms interval for combination release */ |
| 863 | static long brl_timeout = 300; | 863 | static unsigned brl_timeout = 300; |
| 864 | MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for combination on first release, < 0 for dead characters)"); | 864 | MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for commit on first key release)"); |
| 865 | module_param(brl_timeout, long, 0644); | 865 | module_param(brl_timeout, uint, 0644); |
| 866 | |||
| 867 | static unsigned brl_nbchords = 1; | ||
| 868 | MODULE_PARM_DESC(brl_nbchords, "Number of chords that produce a braille pattern (0 for dead chords)"); | ||
| 869 | module_param(brl_nbchords, uint, 0644); | ||
| 870 | |||
| 871 | static void k_brlcommit(struct vc_data *vc, unsigned int pattern, char up_flag, struct pt_regs *regs) | ||
| 872 | { | ||
| 873 | static unsigned long chords; | ||
| 874 | static unsigned committed; | ||
| 875 | |||
| 876 | if (!brl_nbchords) | ||
| 877 | k_deadunicode(vc, BRL_UC_ROW | pattern, up_flag, regs); | ||
| 878 | else { | ||
| 879 | committed |= pattern; | ||
| 880 | chords++; | ||
| 881 | if (chords == brl_nbchords) { | ||
| 882 | k_unicode(vc, BRL_UC_ROW | committed, up_flag, regs); | ||
| 883 | chords = 0; | ||
| 884 | committed = 0; | ||
| 885 | } | ||
| 886 | } | ||
| 887 | } | ||
| 888 | |||
| 866 | static void k_brl(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) | 889 | static void k_brl(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) |
| 867 | { | 890 | { |
| 868 | static unsigned pressed,committing; | 891 | static unsigned pressed,committing; |
| @@ -882,11 +905,6 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag, struct | |||
| 882 | if (value > 8) | 905 | if (value > 8) |
| 883 | return; | 906 | return; |
| 884 | 907 | ||
| 885 | if (brl_timeout < 0) { | ||
| 886 | k_deadunicode(vc, BRL_UC_ROW | (1 << (value - 1)), up_flag, regs); | ||
| 887 | return; | ||
| 888 | } | ||
| 889 | |||
| 890 | if (up_flag) { | 908 | if (up_flag) { |
| 891 | if (brl_timeout) { | 909 | if (brl_timeout) { |
| 892 | if (!committing || | 910 | if (!committing || |
| @@ -897,13 +915,13 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag, struct | |||
| 897 | pressed &= ~(1 << (value - 1)); | 915 | pressed &= ~(1 << (value - 1)); |
| 898 | if (!pressed) { | 916 | if (!pressed) { |
| 899 | if (committing) { | 917 | if (committing) { |
| 900 | k_unicode(vc, BRL_UC_ROW | committing, 0, regs); | 918 | k_brlcommit(vc, committing, 0, regs); |
| 901 | committing = 0; | 919 | committing = 0; |
| 902 | } | 920 | } |
| 903 | } | 921 | } |
| 904 | } else { | 922 | } else { |
| 905 | if (committing) { | 923 | if (committing) { |
| 906 | k_unicode(vc, BRL_UC_ROW | committing, 0, regs); | 924 | k_brlcommit(vc, committing, 0, regs); |
| 907 | committing = 0; | 925 | committing = 0; |
| 908 | } | 926 | } |
| 909 | pressed &= ~(1 << (value - 1)); | 927 | pressed &= ~(1 << (value - 1)); |
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c index 8666171e187b..d3ba2f860ef0 100644 --- a/drivers/char/mwave/mwavedd.c +++ b/drivers/char/mwave/mwavedd.c | |||
| @@ -271,7 +271,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
| 271 | ipcnum, | 271 | ipcnum, |
| 272 | pDrvData->IPCs[ipcnum].usIntCount); | 272 | pDrvData->IPCs[ipcnum].usIntCount); |
| 273 | 273 | ||
| 274 | if (ipcnum > ARRAY_SIZE(pDrvData->IPCs)) { | 274 | if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) { |
| 275 | PRINTK_ERROR(KERN_ERR_MWAVE | 275 | PRINTK_ERROR(KERN_ERR_MWAVE |
| 276 | "mwavedd::mwave_ioctl:" | 276 | "mwavedd::mwave_ioctl:" |
| 277 | " IOCTL_MW_REGISTER_IPC:" | 277 | " IOCTL_MW_REGISTER_IPC:" |
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c index eb2eb3e12d6a..079db5a935a1 100644 --- a/drivers/char/tipar.c +++ b/drivers/char/tipar.c | |||
| @@ -515,7 +515,7 @@ tipar_init_module(void) | |||
| 515 | err = PTR_ERR(tipar_class); | 515 | err = PTR_ERR(tipar_class); |
| 516 | goto out_chrdev; | 516 | goto out_chrdev; |
| 517 | } | 517 | } |
| 518 | if (parport_register_driver(&tipar_driver) || tp_count == 0) { | 518 | if (parport_register_driver(&tipar_driver)) { |
| 519 | printk(KERN_ERR "tipar: unable to register with parport\n"); | 519 | printk(KERN_ERR "tipar: unable to register with parport\n"); |
| 520 | err = -EIO; | 520 | err = -EIO; |
| 521 | goto out_class; | 521 | goto out_class; |
diff --git a/drivers/infiniband/hw/ipath/ipath_debug.h b/drivers/infiniband/hw/ipath/ipath_debug.h index 593e28969c69..46762387f5f8 100644 --- a/drivers/infiniband/hw/ipath/ipath_debug.h +++ b/drivers/infiniband/hw/ipath/ipath_debug.h | |||
| @@ -60,11 +60,11 @@ | |||
| 60 | #define __IPATH_KERNEL_SEND 0x2000 /* use kernel mode send */ | 60 | #define __IPATH_KERNEL_SEND 0x2000 /* use kernel mode send */ |
| 61 | #define __IPATH_EPKTDBG 0x4000 /* print ethernet packet data */ | 61 | #define __IPATH_EPKTDBG 0x4000 /* print ethernet packet data */ |
| 62 | #define __IPATH_SMADBG 0x8000 /* sma packet debug */ | 62 | #define __IPATH_SMADBG 0x8000 /* sma packet debug */ |
| 63 | #define __IPATH_IPATHDBG 0x10000 /* Ethernet (IPATH) general debug on */ | 63 | #define __IPATH_IPATHDBG 0x10000 /* Ethernet (IPATH) gen debug */ |
| 64 | #define __IPATH_IPATHWARN 0x20000 /* Ethernet (IPATH) warnings on */ | 64 | #define __IPATH_IPATHWARN 0x20000 /* Ethernet (IPATH) warnings */ |
| 65 | #define __IPATH_IPATHERR 0x40000 /* Ethernet (IPATH) errors on */ | 65 | #define __IPATH_IPATHERR 0x40000 /* Ethernet (IPATH) errors */ |
| 66 | #define __IPATH_IPATHPD 0x80000 /* Ethernet (IPATH) packet dump on */ | 66 | #define __IPATH_IPATHPD 0x80000 /* Ethernet (IPATH) packet dump */ |
| 67 | #define __IPATH_IPATHTABLE 0x100000 /* Ethernet (IPATH) table dump on */ | 67 | #define __IPATH_IPATHTABLE 0x100000 /* Ethernet (IPATH) table dump */ |
| 68 | 68 | ||
| 69 | #else /* _IPATH_DEBUGGING */ | 69 | #else /* _IPATH_DEBUGGING */ |
| 70 | 70 | ||
| @@ -79,11 +79,12 @@ | |||
| 79 | #define __IPATH_TRSAMPLE 0x0 /* generate trace buffer sample entries */ | 79 | #define __IPATH_TRSAMPLE 0x0 /* generate trace buffer sample entries */ |
| 80 | #define __IPATH_VERBDBG 0x0 /* very verbose debug */ | 80 | #define __IPATH_VERBDBG 0x0 /* very verbose debug */ |
| 81 | #define __IPATH_PKTDBG 0x0 /* print packet data */ | 81 | #define __IPATH_PKTDBG 0x0 /* print packet data */ |
| 82 | #define __IPATH_PROCDBG 0x0 /* print process startup (init)/exit messages */ | 82 | #define __IPATH_PROCDBG 0x0 /* process startup (init)/exit messages */ |
| 83 | /* print mmap/nopage stuff, not using VDBG any more */ | 83 | /* print mmap/nopage stuff, not using VDBG any more */ |
| 84 | #define __IPATH_MMDBG 0x0 | 84 | #define __IPATH_MMDBG 0x0 |
| 85 | #define __IPATH_EPKTDBG 0x0 /* print ethernet packet data */ | 85 | #define __IPATH_EPKTDBG 0x0 /* print ethernet packet data */ |
| 86 | #define __IPATH_SMADBG 0x0 /* print process startup (init)/exit messages */#define __IPATH_IPATHDBG 0x0 /* Ethernet (IPATH) table dump on */ | 86 | #define __IPATH_SMADBG 0x0 /* process startup (init)/exit messages */ |
| 87 | #define __IPATH_IPATHDBG 0x0 /* Ethernet (IPATH) table dump on */ | ||
| 87 | #define __IPATH_IPATHWARN 0x0 /* Ethernet (IPATH) warnings on */ | 88 | #define __IPATH_IPATHWARN 0x0 /* Ethernet (IPATH) warnings on */ |
| 88 | #define __IPATH_IPATHERR 0x0 /* Ethernet (IPATH) errors on */ | 89 | #define __IPATH_IPATHERR 0x0 /* Ethernet (IPATH) errors on */ |
| 89 | #define __IPATH_IPATHPD 0x0 /* Ethernet (IPATH) packet dump on */ | 90 | #define __IPATH_IPATHPD 0x0 /* Ethernet (IPATH) packet dump on */ |
diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c index 7d3fb6996b41..28ddceb260e8 100644 --- a/drivers/infiniband/hw/ipath/ipath_diag.c +++ b/drivers/infiniband/hw/ipath/ipath_diag.c | |||
| @@ -277,13 +277,14 @@ static int ipath_diag_open(struct inode *in, struct file *fp) | |||
| 277 | 277 | ||
| 278 | bail: | 278 | bail: |
| 279 | spin_unlock_irqrestore(&ipath_devs_lock, flags); | 279 | spin_unlock_irqrestore(&ipath_devs_lock, flags); |
| 280 | mutex_unlock(&ipath_mutex); | ||
| 281 | 280 | ||
| 282 | /* Only expose a way to reset the device if we | 281 | /* Only expose a way to reset the device if we |
| 283 | make it into diag mode. */ | 282 | make it into diag mode. */ |
| 284 | if (ret == 0) | 283 | if (ret == 0) |
| 285 | ipath_expose_reset(&dd->pcidev->dev); | 284 | ipath_expose_reset(&dd->pcidev->dev); |
| 286 | 285 | ||
| 286 | mutex_unlock(&ipath_mutex); | ||
| 287 | |||
| 287 | return ret; | 288 | return ret; |
| 288 | } | 289 | } |
| 289 | 290 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index e7617c3982ea..398add4d4cb1 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c | |||
| @@ -418,9 +418,19 @@ static int __devinit ipath_init_one(struct pci_dev *pdev, | |||
| 418 | 418 | ||
| 419 | ret = pci_set_dma_mask(pdev, DMA_64BIT_MASK); | 419 | ret = pci_set_dma_mask(pdev, DMA_64BIT_MASK); |
| 420 | if (ret) { | 420 | if (ret) { |
| 421 | dev_info(&pdev->dev, "pci_set_dma_mask unit %u " | 421 | /* |
| 422 | "fails: %d\n", dd->ipath_unit, ret); | 422 | * if the 64 bit setup fails, try 32 bit. Some systems |
| 423 | goto bail_regions; | 423 | * do not setup 64 bit maps on systems with 2GB or less |
| 424 | * memory installed. | ||
| 425 | */ | ||
| 426 | ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); | ||
| 427 | if (ret) { | ||
| 428 | dev_info(&pdev->dev, "pci_set_dma_mask unit %u " | ||
| 429 | "fails: %d\n", dd->ipath_unit, ret); | ||
| 430 | goto bail_regions; | ||
| 431 | } | ||
| 432 | else | ||
| 433 | ipath_dbg("No 64bit DMA mask, used 32 bit mask\n"); | ||
| 424 | } | 434 | } |
| 425 | 435 | ||
| 426 | pci_set_master(pdev); | 436 | pci_set_master(pdev); |
| @@ -1949,7 +1959,7 @@ int ipath_reset_device(int unit) | |||
| 1949 | } | 1959 | } |
| 1950 | 1960 | ||
| 1951 | if (dd->ipath_pd) | 1961 | if (dd->ipath_pd) |
| 1952 | for (i = 1; i < dd->ipath_portcnt; i++) { | 1962 | for (i = 1; i < dd->ipath_cfgports; i++) { |
| 1953 | if (dd->ipath_pd[i] && dd->ipath_pd[i]->port_cnt) { | 1963 | if (dd->ipath_pd[i] && dd->ipath_pd[i]->port_cnt) { |
| 1954 | ipath_dbg("unit %u port %d is in use " | 1964 | ipath_dbg("unit %u port %d is in use " |
| 1955 | "(PID %u cmd %s), can't reset\n", | 1965 | "(PID %u cmd %s), can't reset\n", |
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c index 2823ff9c0c62..16f640e1c16e 100644 --- a/drivers/infiniband/hw/ipath/ipath_init_chip.c +++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c | |||
| @@ -53,13 +53,19 @@ MODULE_PARM_DESC(cfgports, "Set max number of ports to use"); | |||
| 53 | 53 | ||
| 54 | /* | 54 | /* |
| 55 | * Number of buffers reserved for driver (layered drivers and SMA | 55 | * Number of buffers reserved for driver (layered drivers and SMA |
| 56 | * send). Reserved at end of buffer list. | 56 | * send). Reserved at end of buffer list. Initialized based on |
| 57 | * number of PIO buffers if not set via module interface. | ||
| 58 | * The problem with this is that it's global, but we'll use different | ||
| 59 | * numbers for different chip types. So the default value is not | ||
| 60 | * very useful. I've redefined it for the 1.3 release so that it's | ||
| 61 | * zero unless set by the user to something else, in which case we | ||
| 62 | * try to respect it. | ||
| 57 | */ | 63 | */ |
| 58 | static ushort ipath_kpiobufs = 32; | 64 | static ushort ipath_kpiobufs; |
| 59 | 65 | ||
| 60 | static int ipath_set_kpiobufs(const char *val, struct kernel_param *kp); | 66 | static int ipath_set_kpiobufs(const char *val, struct kernel_param *kp); |
| 61 | 67 | ||
| 62 | module_param_call(kpiobufs, ipath_set_kpiobufs, param_get_uint, | 68 | module_param_call(kpiobufs, ipath_set_kpiobufs, param_get_ushort, |
| 63 | &ipath_kpiobufs, S_IWUSR | S_IRUGO); | 69 | &ipath_kpiobufs, S_IWUSR | S_IRUGO); |
| 64 | MODULE_PARM_DESC(kpiobufs, "Set number of PIO buffers for driver"); | 70 | MODULE_PARM_DESC(kpiobufs, "Set number of PIO buffers for driver"); |
| 65 | 71 | ||
| @@ -531,8 +537,11 @@ static int init_housekeeping(struct ipath_devdata *dd, | |||
| 531 | * Don't clear ipath_flags as 8bit mode was set before | 537 | * Don't clear ipath_flags as 8bit mode was set before |
| 532 | * entering this func. However, we do set the linkstate to | 538 | * entering this func. However, we do set the linkstate to |
| 533 | * unknown, so we can watch for a transition. | 539 | * unknown, so we can watch for a transition. |
| 540 | * PRESENT is set because we want register reads to work, | ||
| 541 | * and the kernel infrastructure saw it in config space; | ||
| 542 | * We clear it if we have failures. | ||
| 534 | */ | 543 | */ |
| 535 | dd->ipath_flags |= IPATH_LINKUNK; | 544 | dd->ipath_flags |= IPATH_LINKUNK | IPATH_PRESENT; |
| 536 | dd->ipath_flags &= ~(IPATH_LINKACTIVE | IPATH_LINKARMED | | 545 | dd->ipath_flags &= ~(IPATH_LINKACTIVE | IPATH_LINKARMED | |
| 537 | IPATH_LINKDOWN | IPATH_LINKINIT); | 546 | IPATH_LINKDOWN | IPATH_LINKINIT); |
| 538 | 547 | ||
| @@ -560,6 +569,7 @@ static int init_housekeeping(struct ipath_devdata *dd, | |||
| 560 | || (dd->ipath_uregbase & 0xffffffff) == 0xffffffff) { | 569 | || (dd->ipath_uregbase & 0xffffffff) == 0xffffffff) { |
| 561 | ipath_dev_err(dd, "Register read failures from chip, " | 570 | ipath_dev_err(dd, "Register read failures from chip, " |
| 562 | "giving up initialization\n"); | 571 | "giving up initialization\n"); |
| 572 | dd->ipath_flags &= ~IPATH_PRESENT; | ||
| 563 | ret = -ENODEV; | 573 | ret = -ENODEV; |
| 564 | goto done; | 574 | goto done; |
| 565 | } | 575 | } |
| @@ -682,16 +692,14 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit) | |||
| 682 | */ | 692 | */ |
| 683 | dd->ipath_pioavregs = ALIGN(val, sizeof(u64) * BITS_PER_BYTE / 2) | 693 | dd->ipath_pioavregs = ALIGN(val, sizeof(u64) * BITS_PER_BYTE / 2) |
| 684 | / (sizeof(u64) * BITS_PER_BYTE / 2); | 694 | / (sizeof(u64) * BITS_PER_BYTE / 2); |
| 685 | if (!ipath_kpiobufs) /* have to have at least 1, for SMA */ | 695 | if (ipath_kpiobufs == 0) { |
| 686 | kpiobufs = ipath_kpiobufs = 1; | 696 | /* not set by user, or set explictly to default */ |
| 687 | else if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) < | 697 | if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) > 128) |
| 688 | (dd->ipath_cfgports * IPATH_MIN_USER_PORT_BUFCNT)) { | 698 | kpiobufs = 32; |
| 689 | dev_info(&dd->pcidev->dev, "Too few PIO buffers (%u) " | 699 | else |
| 690 | "for %u ports to have %u each!\n", | 700 | kpiobufs = 16; |
| 691 | dd->ipath_piobcnt2k + dd->ipath_piobcnt4k, | 701 | } |
| 692 | dd->ipath_cfgports, IPATH_MIN_USER_PORT_BUFCNT); | 702 | else |
| 693 | kpiobufs = 1; /* reserve just the minimum for SMA/ether */ | ||
| 694 | } else | ||
| 695 | kpiobufs = ipath_kpiobufs; | 703 | kpiobufs = ipath_kpiobufs; |
| 696 | 704 | ||
| 697 | if (kpiobufs > | 705 | if (kpiobufs > |
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c index 0bcb428041f3..3e72a1fe3d73 100644 --- a/drivers/infiniband/hw/ipath/ipath_intr.c +++ b/drivers/infiniband/hw/ipath/ipath_intr.c | |||
| @@ -665,14 +665,14 @@ static void handle_layer_pioavail(struct ipath_devdata *dd) | |||
| 665 | 665 | ||
| 666 | ret = __ipath_layer_intr(dd, IPATH_LAYER_INT_SEND_CONTINUE); | 666 | ret = __ipath_layer_intr(dd, IPATH_LAYER_INT_SEND_CONTINUE); |
| 667 | if (ret > 0) | 667 | if (ret > 0) |
| 668 | goto clear; | 668 | goto set; |
| 669 | 669 | ||
| 670 | ret = __ipath_verbs_piobufavail(dd); | 670 | ret = __ipath_verbs_piobufavail(dd); |
| 671 | if (ret > 0) | 671 | if (ret > 0) |
| 672 | goto clear; | 672 | goto set; |
| 673 | 673 | ||
| 674 | return; | 674 | return; |
| 675 | clear: | 675 | set: |
| 676 | set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl); | 676 | set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl); |
| 677 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, | 677 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, |
| 678 | dd->ipath_sendctrl); | 678 | dd->ipath_sendctrl); |
| @@ -719,11 +719,24 @@ static void handle_rcv(struct ipath_devdata *dd, u32 istat) | |||
| 719 | irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs) | 719 | irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs) |
| 720 | { | 720 | { |
| 721 | struct ipath_devdata *dd = data; | 721 | struct ipath_devdata *dd = data; |
| 722 | u32 istat = ipath_read_kreg32(dd, dd->ipath_kregs->kr_intstatus); | 722 | u32 istat; |
| 723 | ipath_err_t estat = 0; | 723 | ipath_err_t estat = 0; |
| 724 | static unsigned unexpected = 0; | 724 | static unsigned unexpected = 0; |
| 725 | irqreturn_t ret; | 725 | irqreturn_t ret; |
| 726 | 726 | ||
| 727 | if(!(dd->ipath_flags & IPATH_PRESENT)) { | ||
| 728 | /* this is mostly so we don't try to touch the chip while | ||
| 729 | * it is being reset */ | ||
| 730 | /* | ||
| 731 | * This return value is perhaps odd, but we do not want the | ||
| 732 | * interrupt core code to remove our interrupt handler | ||
| 733 | * because we don't appear to be handling an interrupt | ||
| 734 | * during a chip reset. | ||
| 735 | */ | ||
| 736 | return IRQ_HANDLED; | ||
| 737 | } | ||
| 738 | |||
| 739 | istat = ipath_read_kreg32(dd, dd->ipath_kregs->kr_intstatus); | ||
| 727 | if (unlikely(!istat)) { | 740 | if (unlikely(!istat)) { |
| 728 | ipath_stats.sps_nullintr++; | 741 | ipath_stats.sps_nullintr++; |
| 729 | ret = IRQ_NONE; /* not our interrupt, or already handled */ | 742 | ret = IRQ_NONE; /* not our interrupt, or already handled */ |
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index 0ce5f19c9d62..e6507f8115bc 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h | |||
| @@ -731,7 +731,7 @@ u64 ipath_read_kreg64_port(const struct ipath_devdata *, ipath_kreg, | |||
| 731 | static inline u32 ipath_read_ureg32(const struct ipath_devdata *dd, | 731 | static inline u32 ipath_read_ureg32(const struct ipath_devdata *dd, |
| 732 | ipath_ureg regno, int port) | 732 | ipath_ureg regno, int port) |
| 733 | { | 733 | { |
| 734 | if (!dd->ipath_kregbase) | 734 | if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT)) |
| 735 | return 0; | 735 | return 0; |
| 736 | 736 | ||
| 737 | return readl(regno + (u64 __iomem *) | 737 | return readl(regno + (u64 __iomem *) |
| @@ -762,7 +762,7 @@ static inline void ipath_write_ureg(const struct ipath_devdata *dd, | |||
| 762 | static inline u32 ipath_read_kreg32(const struct ipath_devdata *dd, | 762 | static inline u32 ipath_read_kreg32(const struct ipath_devdata *dd, |
| 763 | ipath_kreg regno) | 763 | ipath_kreg regno) |
| 764 | { | 764 | { |
| 765 | if (!dd->ipath_kregbase) | 765 | if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT)) |
| 766 | return -1; | 766 | return -1; |
| 767 | return readl((u32 __iomem *) & dd->ipath_kregbase[regno]); | 767 | return readl((u32 __iomem *) & dd->ipath_kregbase[regno]); |
| 768 | } | 768 | } |
| @@ -770,7 +770,7 @@ static inline u32 ipath_read_kreg32(const struct ipath_devdata *dd, | |||
| 770 | static inline u64 ipath_read_kreg64(const struct ipath_devdata *dd, | 770 | static inline u64 ipath_read_kreg64(const struct ipath_devdata *dd, |
| 771 | ipath_kreg regno) | 771 | ipath_kreg regno) |
| 772 | { | 772 | { |
| 773 | if (!dd->ipath_kregbase) | 773 | if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT)) |
| 774 | return -1; | 774 | return -1; |
| 775 | 775 | ||
| 776 | return readq(&dd->ipath_kregbase[regno]); | 776 | return readq(&dd->ipath_kregbase[regno]); |
| @@ -786,7 +786,7 @@ static inline void ipath_write_kreg(const struct ipath_devdata *dd, | |||
| 786 | static inline u64 ipath_read_creg(const struct ipath_devdata *dd, | 786 | static inline u64 ipath_read_creg(const struct ipath_devdata *dd, |
| 787 | ipath_sreg regno) | 787 | ipath_sreg regno) |
| 788 | { | 788 | { |
| 789 | if (!dd->ipath_kregbase) | 789 | if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT)) |
| 790 | return 0; | 790 | return 0; |
| 791 | 791 | ||
| 792 | return readq(regno + (u64 __iomem *) | 792 | return readq(regno + (u64 __iomem *) |
| @@ -797,7 +797,7 @@ static inline u64 ipath_read_creg(const struct ipath_devdata *dd, | |||
| 797 | static inline u32 ipath_read_creg32(const struct ipath_devdata *dd, | 797 | static inline u32 ipath_read_creg32(const struct ipath_devdata *dd, |
| 798 | ipath_sreg regno) | 798 | ipath_sreg regno) |
| 799 | { | 799 | { |
| 800 | if (!dd->ipath_kregbase) | 800 | if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT)) |
| 801 | return 0; | 801 | return 0; |
| 802 | return readl(regno + (u64 __iomem *) | 802 | return readl(regno + (u64 __iomem *) |
| 803 | (dd->ipath_cregbase + | 803 | (dd->ipath_cregbase + |
diff --git a/drivers/infiniband/hw/ipath/ipath_layer.c b/drivers/infiniband/hw/ipath/ipath_layer.c index 69ed1100701a..9cb5258ffed9 100644 --- a/drivers/infiniband/hw/ipath/ipath_layer.c +++ b/drivers/infiniband/hw/ipath/ipath_layer.c | |||
| @@ -46,13 +46,15 @@ | |||
| 46 | /* Acquire before ipath_devs_lock. */ | 46 | /* Acquire before ipath_devs_lock. */ |
| 47 | static DEFINE_MUTEX(ipath_layer_mutex); | 47 | static DEFINE_MUTEX(ipath_layer_mutex); |
| 48 | 48 | ||
| 49 | static int ipath_verbs_registered; | ||
| 50 | |||
| 49 | u16 ipath_layer_rcv_opcode; | 51 | u16 ipath_layer_rcv_opcode; |
| 52 | |||
| 50 | static int (*layer_intr)(void *, u32); | 53 | static int (*layer_intr)(void *, u32); |
| 51 | static int (*layer_rcv)(void *, void *, struct sk_buff *); | 54 | static int (*layer_rcv)(void *, void *, struct sk_buff *); |
| 52 | static int (*layer_rcv_lid)(void *, void *); | 55 | static int (*layer_rcv_lid)(void *, void *); |
| 53 | static int (*verbs_piobufavail)(void *); | 56 | static int (*verbs_piobufavail)(void *); |
| 54 | static void (*verbs_rcv)(void *, void *, void *, u32); | 57 | static void (*verbs_rcv)(void *, void *, void *, u32); |
| 55 | static int ipath_verbs_registered; | ||
| 56 | 58 | ||
| 57 | static void *(*layer_add_one)(int, struct ipath_devdata *); | 59 | static void *(*layer_add_one)(int, struct ipath_devdata *); |
| 58 | static void (*layer_remove_one)(void *); | 60 | static void (*layer_remove_one)(void *); |
| @@ -586,6 +588,8 @@ void ipath_verbs_unregister(void) | |||
| 586 | verbs_rcv = NULL; | 588 | verbs_rcv = NULL; |
| 587 | verbs_timer_cb = NULL; | 589 | verbs_timer_cb = NULL; |
| 588 | 590 | ||
| 591 | ipath_verbs_registered = 0; | ||
| 592 | |||
| 589 | mutex_unlock(&ipath_layer_mutex); | 593 | mutex_unlock(&ipath_layer_mutex); |
| 590 | } | 594 | } |
| 591 | 595 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_pe800.c b/drivers/infiniband/hw/ipath/ipath_pe800.c index e1dc4f757062..6318067ab5ec 100644 --- a/drivers/infiniband/hw/ipath/ipath_pe800.c +++ b/drivers/infiniband/hw/ipath/ipath_pe800.c | |||
| @@ -972,6 +972,8 @@ static int ipath_setup_pe_reset(struct ipath_devdata *dd) | |||
| 972 | /* Use ERROR so it shows up in logs, etc. */ | 972 | /* Use ERROR so it shows up in logs, etc. */ |
| 973 | ipath_dev_err(dd, "Resetting PE-800 unit %u\n", | 973 | ipath_dev_err(dd, "Resetting PE-800 unit %u\n", |
| 974 | dd->ipath_unit); | 974 | dd->ipath_unit); |
| 975 | /* keep chip from being accessed in a few places */ | ||
| 976 | dd->ipath_flags &= ~(IPATH_INITTED|IPATH_PRESENT); | ||
| 975 | val = dd->ipath_control | INFINIPATH_C_RESET; | 977 | val = dd->ipath_control | INFINIPATH_C_RESET; |
| 976 | ipath_write_kreg(dd, dd->ipath_kregs->kr_control, val); | 978 | ipath_write_kreg(dd, dd->ipath_kregs->kr_control, val); |
| 977 | mb(); | 979 | mb(); |
| @@ -997,6 +999,8 @@ static int ipath_setup_pe_reset(struct ipath_devdata *dd) | |||
| 997 | if ((r = pci_enable_device(dd->pcidev))) | 999 | if ((r = pci_enable_device(dd->pcidev))) |
| 998 | ipath_dev_err(dd, "pci_enable_device failed after " | 1000 | ipath_dev_err(dd, "pci_enable_device failed after " |
| 999 | "reset: %d\n", r); | 1001 | "reset: %d\n", r); |
| 1002 | /* whether it worked or not, mark as present, again */ | ||
| 1003 | dd->ipath_flags |= IPATH_PRESENT; | ||
| 1000 | val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_revision); | 1004 | val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_revision); |
| 1001 | if (val == dd->ipath_revision) { | 1005 | if (val == dd->ipath_revision) { |
| 1002 | ipath_cdbg(VERBOSE, "Got matching revision " | 1006 | ipath_cdbg(VERBOSE, "Got matching revision " |
diff --git a/drivers/infiniband/hw/ipath/ipath_registers.h b/drivers/infiniband/hw/ipath/ipath_registers.h index 1e59750c5f63..402126eb79c9 100644 --- a/drivers/infiniband/hw/ipath/ipath_registers.h +++ b/drivers/infiniband/hw/ipath/ipath_registers.h | |||
| @@ -34,8 +34,9 @@ | |||
| 34 | #define _IPATH_REGISTERS_H | 34 | #define _IPATH_REGISTERS_H |
| 35 | 35 | ||
| 36 | /* | 36 | /* |
| 37 | * This file should only be included by kernel source, and by the diags. | 37 | * This file should only be included by kernel source, and by the diags. It |
| 38 | * It defines the registers, and their contents, for the InfiniPath HT-400 chip | 38 | * defines the registers, and their contents, for the InfiniPath HT-400 |
| 39 | * chip. | ||
| 39 | */ | 40 | */ |
| 40 | 41 | ||
| 41 | /* | 42 | /* |
| @@ -156,8 +157,10 @@ | |||
| 156 | #define INFINIPATH_IBCC_FLOWCTRLWATERMARK_SHIFT 8 | 157 | #define INFINIPATH_IBCC_FLOWCTRLWATERMARK_SHIFT 8 |
| 157 | #define INFINIPATH_IBCC_LINKINITCMD_MASK 0x3ULL | 158 | #define INFINIPATH_IBCC_LINKINITCMD_MASK 0x3ULL |
| 158 | #define INFINIPATH_IBCC_LINKINITCMD_DISABLE 1 | 159 | #define INFINIPATH_IBCC_LINKINITCMD_DISABLE 1 |
| 159 | #define INFINIPATH_IBCC_LINKINITCMD_POLL 2 /* cycle through TS1/TS2 till OK */ | 160 | /* cycle through TS1/TS2 till OK */ |
| 160 | #define INFINIPATH_IBCC_LINKINITCMD_SLEEP 3 /* wait for TS1, then go on */ | 161 | #define INFINIPATH_IBCC_LINKINITCMD_POLL 2 |
| 162 | /* wait for TS1, then go on */ | ||
| 163 | #define INFINIPATH_IBCC_LINKINITCMD_SLEEP 3 | ||
| 161 | #define INFINIPATH_IBCC_LINKINITCMD_SHIFT 16 | 164 | #define INFINIPATH_IBCC_LINKINITCMD_SHIFT 16 |
| 162 | #define INFINIPATH_IBCC_LINKCMD_MASK 0x3ULL | 165 | #define INFINIPATH_IBCC_LINKCMD_MASK 0x3ULL |
| 163 | #define INFINIPATH_IBCC_LINKCMD_INIT 1 /* move to 0x11 */ | 166 | #define INFINIPATH_IBCC_LINKCMD_INIT 1 /* move to 0x11 */ |
| @@ -182,7 +185,8 @@ | |||
| 182 | #define INFINIPATH_IBCS_LINKSTATE_SHIFT 4 | 185 | #define INFINIPATH_IBCS_LINKSTATE_SHIFT 4 |
| 183 | #define INFINIPATH_IBCS_TXREADY 0x40000000 | 186 | #define INFINIPATH_IBCS_TXREADY 0x40000000 |
| 184 | #define INFINIPATH_IBCS_TXCREDITOK 0x80000000 | 187 | #define INFINIPATH_IBCS_TXCREDITOK 0x80000000 |
| 185 | /* link training states (shift by INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) */ | 188 | /* link training states (shift by |
| 189 | INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) */ | ||
| 186 | #define INFINIPATH_IBCS_LT_STATE_DISABLED 0x00 | 190 | #define INFINIPATH_IBCS_LT_STATE_DISABLED 0x00 |
| 187 | #define INFINIPATH_IBCS_LT_STATE_LINKUP 0x01 | 191 | #define INFINIPATH_IBCS_LT_STATE_LINKUP 0x01 |
| 188 | #define INFINIPATH_IBCS_LT_STATE_POLLACTIVE 0x02 | 192 | #define INFINIPATH_IBCS_LT_STATE_POLLACTIVE 0x02 |
| @@ -267,10 +271,12 @@ | |||
| 267 | /* kr_serdesconfig0 bits */ | 271 | /* kr_serdesconfig0 bits */ |
| 268 | #define INFINIPATH_SERDC0_RESET_MASK 0xfULL /* overal reset bits */ | 272 | #define INFINIPATH_SERDC0_RESET_MASK 0xfULL /* overal reset bits */ |
| 269 | #define INFINIPATH_SERDC0_RESET_PLL 0x10000000ULL /* pll reset */ | 273 | #define INFINIPATH_SERDC0_RESET_PLL 0x10000000ULL /* pll reset */ |
| 270 | #define INFINIPATH_SERDC0_TXIDLE 0xF000ULL /* tx idle enables (per lane) */ | 274 | /* tx idle enables (per lane) */ |
| 271 | #define INFINIPATH_SERDC0_RXDETECT_EN 0xF0000ULL /* rx detect enables (per lane) */ | 275 | #define INFINIPATH_SERDC0_TXIDLE 0xF000ULL |
| 272 | #define INFINIPATH_SERDC0_L1PWR_DN 0xF0ULL /* L1 Power down; use with RXDETECT, | 276 | /* rx detect enables (per lane) */ |
| 273 | Otherwise not used on IB side */ | 277 | #define INFINIPATH_SERDC0_RXDETECT_EN 0xF0000ULL |
| 278 | /* L1 Power down; use with RXDETECT, Otherwise not used on IB side */ | ||
| 279 | #define INFINIPATH_SERDC0_L1PWR_DN 0xF0ULL | ||
| 274 | 280 | ||
| 275 | /* kr_xgxsconfig bits */ | 281 | /* kr_xgxsconfig bits */ |
| 276 | #define INFINIPATH_XGXS_RESET 0x7ULL | 282 | #define INFINIPATH_XGXS_RESET 0x7ULL |
| @@ -390,12 +396,13 @@ struct ipath_kregs { | |||
| 390 | ipath_kreg kr_txintmemsize; | 396 | ipath_kreg kr_txintmemsize; |
| 391 | ipath_kreg kr_xgxsconfig; | 397 | ipath_kreg kr_xgxsconfig; |
| 392 | ipath_kreg kr_ibpllcfg; | 398 | ipath_kreg kr_ibpllcfg; |
| 393 | /* use these two (and the following N ports) only with ipath_k*_kreg64_port(); | 399 | /* use these two (and the following N ports) only with |
| 394 | * not *kreg64() */ | 400 | * ipath_k*_kreg64_port(); not *kreg64() */ |
| 395 | ipath_kreg kr_rcvhdraddr; | 401 | ipath_kreg kr_rcvhdraddr; |
| 396 | ipath_kreg kr_rcvhdrtailaddr; | 402 | ipath_kreg kr_rcvhdrtailaddr; |
| 397 | 403 | ||
| 398 | /* remaining registers are not present on all types of infinipath chips */ | 404 | /* remaining registers are not present on all types of infinipath |
| 405 | chips */ | ||
| 399 | ipath_kreg kr_rcvpktledcnt; | 406 | ipath_kreg kr_rcvpktledcnt; |
| 400 | ipath_kreg kr_pcierbuftestreg0; | 407 | ipath_kreg kr_pcierbuftestreg0; |
| 401 | ipath_kreg kr_pcierbuftestreg1; | 408 | ipath_kreg kr_pcierbuftestreg1; |
diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c index f232e77b78ee..eb81424b3c5b 100644 --- a/drivers/infiniband/hw/ipath/ipath_ruc.c +++ b/drivers/infiniband/hw/ipath/ipath_ruc.c | |||
| @@ -531,19 +531,12 @@ int ipath_post_rc_send(struct ipath_qp *qp, struct ib_send_wr *wr) | |||
| 531 | } | 531 | } |
| 532 | wqe->wr.num_sge = j; | 532 | wqe->wr.num_sge = j; |
| 533 | qp->s_head = next; | 533 | qp->s_head = next; |
| 534 | /* | ||
| 535 | * Wake up the send tasklet if the QP is not waiting | ||
| 536 | * for an RNR timeout. | ||
| 537 | */ | ||
| 538 | next = qp->s_rnr_timeout; | ||
| 539 | spin_unlock_irqrestore(&qp->s_lock, flags); | 534 | spin_unlock_irqrestore(&qp->s_lock, flags); |
| 540 | 535 | ||
| 541 | if (next == 0) { | 536 | if (qp->ibqp.qp_type == IB_QPT_UC) |
| 542 | if (qp->ibqp.qp_type == IB_QPT_UC) | 537 | ipath_do_uc_send((unsigned long) qp); |
| 543 | ipath_do_uc_send((unsigned long) qp); | 538 | else |
| 544 | else | 539 | ipath_do_rc_send((unsigned long) qp); |
| 545 | ipath_do_rc_send((unsigned long) qp); | ||
| 546 | } | ||
| 547 | 540 | ||
| 548 | ret = 0; | 541 | ret = 0; |
| 549 | 542 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c index 32acd8048b49..f323791cc495 100644 --- a/drivers/infiniband/hw/ipath/ipath_sysfs.c +++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c | |||
| @@ -711,10 +711,22 @@ static struct attribute_group dev_attr_group = { | |||
| 711 | * enters diag mode. A device reset is quite likely to crash the | 711 | * enters diag mode. A device reset is quite likely to crash the |
| 712 | * machine entirely, so we don't want to normally make it | 712 | * machine entirely, so we don't want to normally make it |
| 713 | * available. | 713 | * available. |
| 714 | * | ||
| 715 | * Called with ipath_mutex held. | ||
| 714 | */ | 716 | */ |
| 715 | int ipath_expose_reset(struct device *dev) | 717 | int ipath_expose_reset(struct device *dev) |
| 716 | { | 718 | { |
| 717 | return device_create_file(dev, &dev_attr_reset); | 719 | static int exposed; |
| 720 | int ret; | ||
| 721 | |||
| 722 | if (!exposed) { | ||
| 723 | ret = device_create_file(dev, &dev_attr_reset); | ||
| 724 | exposed = 1; | ||
| 725 | } | ||
| 726 | else | ||
| 727 | ret = 0; | ||
| 728 | |||
| 729 | return ret; | ||
| 718 | } | 730 | } |
| 719 | 731 | ||
| 720 | int ipath_driver_create_group(struct device_driver *drv) | 732 | int ipath_driver_create_group(struct device_driver *drv) |
diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c index 01cfb30ee160..e606daf83210 100644 --- a/drivers/infiniband/hw/ipath/ipath_ud.c +++ b/drivers/infiniband/hw/ipath/ipath_ud.c | |||
| @@ -46,8 +46,10 @@ | |||
| 46 | * This is called from ipath_post_ud_send() to forward a WQE addressed | 46 | * This is called from ipath_post_ud_send() to forward a WQE addressed |
| 47 | * to the same HCA. | 47 | * to the same HCA. |
| 48 | */ | 48 | */ |
| 49 | static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_sge_state *ss, | 49 | static void ipath_ud_loopback(struct ipath_qp *sqp, |
| 50 | u32 length, struct ib_send_wr *wr, struct ib_wc *wc) | 50 | struct ipath_sge_state *ss, |
| 51 | u32 length, struct ib_send_wr *wr, | ||
| 52 | struct ib_wc *wc) | ||
| 51 | { | 53 | { |
| 52 | struct ipath_ibdev *dev = to_idev(sqp->ibqp.device); | 54 | struct ipath_ibdev *dev = to_idev(sqp->ibqp.device); |
| 53 | struct ipath_qp *qp; | 55 | struct ipath_qp *qp; |
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c index 8d2558a01f35..cb9e387c301f 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/drivers/infiniband/hw/ipath/ipath_verbs.c | |||
| @@ -449,7 +449,6 @@ static void ipath_ib_timer(void *arg) | |||
| 449 | { | 449 | { |
| 450 | struct ipath_ibdev *dev = (struct ipath_ibdev *) arg; | 450 | struct ipath_ibdev *dev = (struct ipath_ibdev *) arg; |
| 451 | struct ipath_qp *resend = NULL; | 451 | struct ipath_qp *resend = NULL; |
| 452 | struct ipath_qp *rnr = NULL; | ||
| 453 | struct list_head *last; | 452 | struct list_head *last; |
| 454 | struct ipath_qp *qp; | 453 | struct ipath_qp *qp; |
| 455 | unsigned long flags; | 454 | unsigned long flags; |
| @@ -465,32 +464,18 @@ static void ipath_ib_timer(void *arg) | |||
| 465 | last = &dev->pending[dev->pending_index]; | 464 | last = &dev->pending[dev->pending_index]; |
| 466 | while (!list_empty(last)) { | 465 | while (!list_empty(last)) { |
| 467 | qp = list_entry(last->next, struct ipath_qp, timerwait); | 466 | qp = list_entry(last->next, struct ipath_qp, timerwait); |
| 468 | if (last->next == LIST_POISON1 || | 467 | list_del(&qp->timerwait); |
| 469 | last->next != &qp->timerwait || | 468 | qp->timer_next = resend; |
| 470 | qp->timerwait.prev != last) { | 469 | resend = qp; |
| 471 | INIT_LIST_HEAD(last); | 470 | atomic_inc(&qp->refcount); |
| 472 | } else { | ||
| 473 | list_del(&qp->timerwait); | ||
| 474 | qp->timerwait.prev = (struct list_head *) resend; | ||
| 475 | resend = qp; | ||
| 476 | atomic_inc(&qp->refcount); | ||
| 477 | } | ||
| 478 | } | 471 | } |
| 479 | last = &dev->rnrwait; | 472 | last = &dev->rnrwait; |
| 480 | if (!list_empty(last)) { | 473 | if (!list_empty(last)) { |
| 481 | qp = list_entry(last->next, struct ipath_qp, timerwait); | 474 | qp = list_entry(last->next, struct ipath_qp, timerwait); |
| 482 | if (--qp->s_rnr_timeout == 0) { | 475 | if (--qp->s_rnr_timeout == 0) { |
| 483 | do { | 476 | do { |
| 484 | if (last->next == LIST_POISON1 || | ||
| 485 | last->next != &qp->timerwait || | ||
| 486 | qp->timerwait.prev != last) { | ||
| 487 | INIT_LIST_HEAD(last); | ||
| 488 | break; | ||
| 489 | } | ||
| 490 | list_del(&qp->timerwait); | 477 | list_del(&qp->timerwait); |
| 491 | qp->timerwait.prev = | 478 | tasklet_hi_schedule(&qp->s_task); |
| 492 | (struct list_head *) rnr; | ||
| 493 | rnr = qp; | ||
| 494 | if (list_empty(last)) | 479 | if (list_empty(last)) |
| 495 | break; | 480 | break; |
| 496 | qp = list_entry(last->next, struct ipath_qp, | 481 | qp = list_entry(last->next, struct ipath_qp, |
| @@ -530,8 +515,7 @@ static void ipath_ib_timer(void *arg) | |||
| 530 | spin_unlock_irqrestore(&dev->pending_lock, flags); | 515 | spin_unlock_irqrestore(&dev->pending_lock, flags); |
| 531 | 516 | ||
| 532 | /* XXX What if timer fires again while this is running? */ | 517 | /* XXX What if timer fires again while this is running? */ |
| 533 | for (qp = resend; qp != NULL; | 518 | for (qp = resend; qp != NULL; qp = qp->timer_next) { |
| 534 | qp = (struct ipath_qp *) qp->timerwait.prev) { | ||
| 535 | struct ib_wc wc; | 519 | struct ib_wc wc; |
| 536 | 520 | ||
| 537 | spin_lock_irqsave(&qp->s_lock, flags); | 521 | spin_lock_irqsave(&qp->s_lock, flags); |
| @@ -545,9 +529,6 @@ static void ipath_ib_timer(void *arg) | |||
| 545 | if (atomic_dec_and_test(&qp->refcount)) | 529 | if (atomic_dec_and_test(&qp->refcount)) |
| 546 | wake_up(&qp->wait); | 530 | wake_up(&qp->wait); |
| 547 | } | 531 | } |
| 548 | for (qp = rnr; qp != NULL; | ||
| 549 | qp = (struct ipath_qp *) qp->timerwait.prev) | ||
| 550 | tasklet_hi_schedule(&qp->s_task); | ||
| 551 | } | 532 | } |
| 552 | 533 | ||
| 553 | /** | 534 | /** |
| @@ -556,9 +537,9 @@ static void ipath_ib_timer(void *arg) | |||
| 556 | * | 537 | * |
| 557 | * This is called from ipath_intr() at interrupt level when a PIO buffer is | 538 | * This is called from ipath_intr() at interrupt level when a PIO buffer is |
| 558 | * available after ipath_verbs_send() returned an error that no buffers were | 539 | * available after ipath_verbs_send() returned an error that no buffers were |
| 559 | * available. Return 0 if we consumed all the PIO buffers and we still have | 540 | * available. Return 1 if we consumed all the PIO buffers and we still have |
| 560 | * QPs waiting for buffers (for now, just do a tasklet_hi_schedule and | 541 | * QPs waiting for buffers (for now, just do a tasklet_hi_schedule and |
| 561 | * return one). | 542 | * return zero). |
| 562 | */ | 543 | */ |
| 563 | static int ipath_ib_piobufavail(void *arg) | 544 | static int ipath_ib_piobufavail(void *arg) |
| 564 | { | 545 | { |
| @@ -579,7 +560,7 @@ static int ipath_ib_piobufavail(void *arg) | |||
| 579 | spin_unlock_irqrestore(&dev->pending_lock, flags); | 560 | spin_unlock_irqrestore(&dev->pending_lock, flags); |
| 580 | 561 | ||
| 581 | bail: | 562 | bail: |
| 582 | return 1; | 563 | return 0; |
| 583 | } | 564 | } |
| 584 | 565 | ||
| 585 | static int ipath_query_device(struct ib_device *ibdev, | 566 | static int ipath_query_device(struct ib_device *ibdev, |
| @@ -1159,7 +1140,7 @@ static ssize_t show_stats(struct class_device *cdev, char *buf) | |||
| 1159 | 1140 | ||
| 1160 | len = sprintf(buf, | 1141 | len = sprintf(buf, |
| 1161 | "RC resends %d\n" | 1142 | "RC resends %d\n" |
| 1162 | "RC QACKs %d\n" | 1143 | "RC no QACK %d\n" |
| 1163 | "RC ACKs %d\n" | 1144 | "RC ACKs %d\n" |
| 1164 | "RC SEQ NAKs %d\n" | 1145 | "RC SEQ NAKs %d\n" |
| 1165 | "RC RDMA seq %d\n" | 1146 | "RC RDMA seq %d\n" |
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h index fcafbc7c9e71..4f8d59300e9b 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.h +++ b/drivers/infiniband/hw/ipath/ipath_verbs.h | |||
| @@ -282,7 +282,8 @@ struct ipath_srq { | |||
| 282 | */ | 282 | */ |
| 283 | struct ipath_qp { | 283 | struct ipath_qp { |
| 284 | struct ib_qp ibqp; | 284 | struct ib_qp ibqp; |
| 285 | struct ipath_qp *next; /* link list for QPN hash table */ | 285 | struct ipath_qp *next; /* link list for QPN hash table */ |
| 286 | struct ipath_qp *timer_next; /* link list for ipath_ib_timer() */ | ||
| 286 | struct list_head piowait; /* link for wait PIO buf */ | 287 | struct list_head piowait; /* link for wait PIO buf */ |
| 287 | struct list_head timerwait; /* link for waiting for timeouts */ | 288 | struct list_head timerwait; /* link for waiting for timeouts */ |
| 288 | struct ib_ah_attr remote_ah_attr; | 289 | struct ib_ah_attr remote_ah_attr; |
diff --git a/drivers/infiniband/hw/ipath/ips_common.h b/drivers/infiniband/hw/ipath/ips_common.h index 410a764dfcef..ab7cbbbfd03a 100644 --- a/drivers/infiniband/hw/ipath/ips_common.h +++ b/drivers/infiniband/hw/ipath/ips_common.h | |||
| @@ -95,7 +95,7 @@ struct ether_header { | |||
| 95 | __u8 seq_num; | 95 | __u8 seq_num; |
| 96 | __le32 len; | 96 | __le32 len; |
| 97 | /* MUST be of word size due to PIO write requirements */ | 97 | /* MUST be of word size due to PIO write requirements */ |
| 98 | __u32 csum; | 98 | __le32 csum; |
| 99 | __le16 csum_offset; | 99 | __le16 csum_offset; |
| 100 | __le16 flags; | 100 | __le16 flags; |
| 101 | __u16 first_2_bytes; | 101 | __u16 first_2_bytes; |
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 565a24b1756f..a2eae8a30167 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c | |||
| @@ -306,7 +306,7 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port, | |||
| 306 | goto out; | 306 | goto out; |
| 307 | } | 307 | } |
| 308 | 308 | ||
| 309 | memcpy(gid->raw + 8, out_mad->data + (index % 8) * 16, 8); | 309 | memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8); |
| 310 | 310 | ||
| 311 | out: | 311 | out: |
| 312 | kfree(in_mad); | 312 | kfree(in_mad); |
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index a34e3d91d9ed..ba325f16d077 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
| @@ -403,6 +403,27 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd, | |||
| 403 | case EVIOCGID: | 403 | case EVIOCGID: |
| 404 | if (copy_to_user(p, &dev->id, sizeof(struct input_id))) | 404 | if (copy_to_user(p, &dev->id, sizeof(struct input_id))) |
| 405 | return -EFAULT; | 405 | return -EFAULT; |
| 406 | return 0; | ||
| 407 | |||
| 408 | case EVIOCGREP: | ||
| 409 | if (!test_bit(EV_REP, dev->evbit)) | ||
| 410 | return -ENOSYS; | ||
| 411 | if (put_user(dev->rep[REP_DELAY], ip)) | ||
| 412 | return -EFAULT; | ||
| 413 | if (put_user(dev->rep[REP_PERIOD], ip + 1)) | ||
| 414 | return -EFAULT; | ||
| 415 | return 0; | ||
| 416 | |||
| 417 | case EVIOCSREP: | ||
| 418 | if (!test_bit(EV_REP, dev->evbit)) | ||
| 419 | return -ENOSYS; | ||
| 420 | if (get_user(u, ip)) | ||
| 421 | return -EFAULT; | ||
| 422 | if (get_user(v, ip + 1)) | ||
| 423 | return -EFAULT; | ||
| 424 | |||
| 425 | input_event(dev, EV_REP, REP_DELAY, u); | ||
| 426 | input_event(dev, EV_REP, REP_PERIOD, v); | ||
| 406 | 427 | ||
| 407 | return 0; | 428 | return 0; |
| 408 | 429 | ||
diff --git a/drivers/input/input.c b/drivers/input/input.c index a935abeffffc..3038c268917d 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
| @@ -155,6 +155,9 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in | |||
| 155 | if (code > SND_MAX || !test_bit(code, dev->sndbit)) | 155 | if (code > SND_MAX || !test_bit(code, dev->sndbit)) |
| 156 | return; | 156 | return; |
| 157 | 157 | ||
| 158 | if (!!test_bit(code, dev->snd) != !!value) | ||
| 159 | change_bit(code, dev->snd); | ||
| 160 | |||
| 158 | if (dev->event) dev->event(dev, type, code, value); | 161 | if (dev->event) dev->event(dev, type, code, value); |
| 159 | 162 | ||
| 160 | break; | 163 | break; |
| @@ -286,19 +289,19 @@ static struct input_device_id *input_match_device(struct input_device_id *id, st | |||
| 286 | for (; id->flags || id->driver_info; id++) { | 289 | for (; id->flags || id->driver_info; id++) { |
| 287 | 290 | ||
| 288 | if (id->flags & INPUT_DEVICE_ID_MATCH_BUS) | 291 | if (id->flags & INPUT_DEVICE_ID_MATCH_BUS) |
| 289 | if (id->id.bustype != dev->id.bustype) | 292 | if (id->bustype != dev->id.bustype) |
| 290 | continue; | 293 | continue; |
| 291 | 294 | ||
| 292 | if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR) | 295 | if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR) |
| 293 | if (id->id.vendor != dev->id.vendor) | 296 | if (id->vendor != dev->id.vendor) |
| 294 | continue; | 297 | continue; |
| 295 | 298 | ||
| 296 | if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT) | 299 | if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT) |
| 297 | if (id->id.product != dev->id.product) | 300 | if (id->product != dev->id.product) |
| 298 | continue; | 301 | continue; |
| 299 | 302 | ||
| 300 | if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION) | 303 | if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION) |
| 301 | if (id->id.version != dev->id.version) | 304 | if (id->version != dev->id.version) |
| 302 | continue; | 305 | continue; |
| 303 | 306 | ||
| 304 | MATCH_BIT(evbit, EV_MAX); | 307 | MATCH_BIT(evbit, EV_MAX); |
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c index bc61cf8cfc65..1d238a9d52d6 100644 --- a/drivers/input/keyboard/spitzkbd.c +++ b/drivers/input/keyboard/spitzkbd.c | |||
| @@ -53,8 +53,8 @@ static unsigned char spitzkbd_keycode[NR_SCANCODES] = { | |||
| 53 | KEY_LEFTCTRL, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, SPITZ_KEY_EXOK, SPITZ_KEY_EXCANCEL, 0, 0, 0, 0, 0, /* 1-16 */ | 53 | KEY_LEFTCTRL, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, SPITZ_KEY_EXOK, SPITZ_KEY_EXCANCEL, 0, 0, 0, 0, 0, /* 1-16 */ |
| 54 | 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, SPITZ_KEY_EXJOGDOWN, SPITZ_KEY_EXJOGUP, 0, 0, 0, 0, 0, /* 17-32 */ | 54 | 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, SPITZ_KEY_EXJOGDOWN, SPITZ_KEY_EXJOGUP, 0, 0, 0, 0, 0, /* 17-32 */ |
| 55 | KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ | 55 | KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ |
| 56 | SPITZ_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ | 56 | SPITZ_KEY_ADDRESS, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ |
| 57 | SPITZ_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 65-80 */ | 57 | SPITZ_KEY_CALENDER, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 65-80 */ |
| 58 | SPITZ_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, SPITZ_KEY_FN, 0, 0, 0, 0, 0, /* 81-96 */ | 58 | SPITZ_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, SPITZ_KEY_FN, 0, 0, 0, 0, 0, /* 81-96 */ |
| 59 | KEY_SYSRQ, SPITZ_KEY_JAP1, SPITZ_KEY_JAP2, SPITZ_KEY_CANCEL, SPITZ_KEY_OK, SPITZ_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0 /* 97-112 */ | 59 | KEY_SYSRQ, SPITZ_KEY_JAP1, SPITZ_KEY_JAP2, SPITZ_KEY_CANCEL, SPITZ_KEY_OK, SPITZ_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0 /* 97-112 */ |
| 60 | }; | 60 | }; |
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 4b415d9b0123..36cd2e07fce8 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
| @@ -273,6 +273,18 @@ static struct key_entry keymap_fs_amilo_pro_v2000[] = { | |||
| 273 | { KE_END, 0 } | 273 | { KE_END, 0 } |
| 274 | }; | 274 | }; |
| 275 | 275 | ||
| 276 | static struct key_entry keymap_fujitsu_n3510[] = { | ||
| 277 | { KE_KEY, 0x11, KEY_PROG1 }, | ||
| 278 | { KE_KEY, 0x12, KEY_PROG2 }, | ||
| 279 | { KE_KEY, 0x36, KEY_WWW }, | ||
| 280 | { KE_KEY, 0x31, KEY_MAIL }, | ||
| 281 | { KE_KEY, 0x71, KEY_STOPCD }, | ||
| 282 | { KE_KEY, 0x72, KEY_PLAYPAUSE }, | ||
| 283 | { KE_KEY, 0x74, KEY_REWIND }, | ||
| 284 | { KE_KEY, 0x78, KEY_FORWARD }, | ||
| 285 | { KE_END, 0 } | ||
| 286 | }; | ||
| 287 | |||
| 276 | static struct key_entry keymap_wistron_ms2141[] = { | 288 | static struct key_entry keymap_wistron_ms2141[] = { |
| 277 | { KE_KEY, 0x11, KEY_PROG1 }, | 289 | { KE_KEY, 0x11, KEY_PROG1 }, |
| 278 | { KE_KEY, 0x12, KEY_PROG2 }, | 290 | { KE_KEY, 0x12, KEY_PROG2 }, |
| @@ -323,6 +335,24 @@ static struct dmi_system_id dmi_ids[] = { | |||
| 323 | }, | 335 | }, |
| 324 | { | 336 | { |
| 325 | .callback = dmi_matched, | 337 | .callback = dmi_matched, |
| 338 | .ident = "Fujitsu-Siemens Amilo M7400", | ||
| 339 | .matches = { | ||
| 340 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
| 341 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO M "), | ||
| 342 | }, | ||
| 343 | .driver_data = keymap_fs_amilo_pro_v2000 | ||
| 344 | }, | ||
| 345 | { | ||
| 346 | .callback = dmi_matched, | ||
| 347 | .ident = "Fujitsu N3510", | ||
| 348 | .matches = { | ||
| 349 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | ||
| 350 | DMI_MATCH(DMI_PRODUCT_NAME, "N3510"), | ||
| 351 | }, | ||
| 352 | .driver_data = keymap_fujitsu_n3510 | ||
| 353 | }, | ||
| 354 | { | ||
| 355 | .callback = dmi_matched, | ||
| 326 | .ident = "Acer Aspire 1500", | 356 | .ident = "Acer Aspire 1500", |
| 327 | .matches = { | 357 | .matches = { |
| 328 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 358 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 32d70ed8f41d..136321a2cfdb 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
| @@ -302,8 +302,10 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, | |||
| 302 | * Check if this is a new device announcement (0xAA 0x00) | 302 | * Check if this is a new device announcement (0xAA 0x00) |
| 303 | */ | 303 | */ |
| 304 | if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) { | 304 | if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) { |
| 305 | if (psmouse->pktcnt == 1) | 305 | if (psmouse->pktcnt == 1) { |
| 306 | psmouse->last = jiffies; | ||
| 306 | goto out; | 307 | goto out; |
| 308 | } | ||
| 307 | 309 | ||
| 308 | if (psmouse->packet[1] == PSMOUSE_RET_ID) { | 310 | if (psmouse->packet[1] == PSMOUSE_RET_ID) { |
| 309 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); | 311 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); |
diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h index 9a9221644250..cc21914fbc72 100644 --- a/drivers/input/serio/i8042-io.h +++ b/drivers/input/serio/i8042-io.h | |||
| @@ -67,14 +67,14 @@ static inline int i8042_platform_init(void) | |||
| 67 | * On some platforms touching the i8042 data register region can do really | 67 | * On some platforms touching the i8042 data register region can do really |
| 68 | * bad things. Because of this the region is always reserved on such boxes. | 68 | * bad things. Because of this the region is always reserved on such boxes. |
| 69 | */ | 69 | */ |
| 70 | #if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__) && !defined(CONFIG_PPC64) | 70 | #if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__) && !defined(CONFIG_PPC_MERGE) |
| 71 | if (!request_region(I8042_DATA_REG, 16, "i8042")) | 71 | if (!request_region(I8042_DATA_REG, 16, "i8042")) |
| 72 | return -EBUSY; | 72 | return -EBUSY; |
| 73 | #endif | 73 | #endif |
| 74 | 74 | ||
| 75 | i8042_reset = 1; | 75 | i8042_reset = 1; |
| 76 | 76 | ||
| 77 | #if defined(CONFIG_PPC64) | 77 | #if defined(CONFIG_PPC_MERGE) |
| 78 | if (check_legacy_ioport(I8042_DATA_REG)) | 78 | if (check_legacy_ioport(I8042_DATA_REG)) |
| 79 | return -EBUSY; | 79 | return -EBUSY; |
| 80 | if (!request_region(I8042_DATA_REG, 16, "i8042")) | 80 | if (!request_region(I8042_DATA_REG, 16, "i8042")) |
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 46d1fec2cfd8..1494175ac6fe 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | * ADS7846 based touchscreen and sensor driver | 2 | * ADS7846 based touchscreen and sensor driver |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2005 David Brownell | 4 | * Copyright (c) 2005 David Brownell |
| 5 | * Copyright (c) 2006 Nokia Corporation | ||
| 6 | * Various changes: Imre Deak <imre.deak@nokia.com> | ||
| 5 | * | 7 | * |
| 6 | * Using code from: | 8 | * Using code from: |
| 7 | * - corgi_ts.c | 9 | * - corgi_ts.c |
| @@ -34,17 +36,25 @@ | |||
| 34 | 36 | ||
| 35 | 37 | ||
| 36 | /* | 38 | /* |
| 37 | * This code has been lightly tested on an ads7846. | 39 | * This code has been tested on an ads7846 / N770 device. |
| 38 | * Support for ads7843 and ads7845 has only been stubbed in. | 40 | * Support for ads7843 and ads7845 has only been stubbed in. |
| 39 | * | 41 | * |
| 40 | * Not yet done: investigate the values reported. Are x/y/pressure | 42 | * Not yet done: How accurate are the temperature and voltage |
| 41 | * event values sane enough for X11? How accurate are the temperature | 43 | * readings? (System-specific calibration should support |
| 42 | * and voltage readings? (System-specific calibration should support | ||
| 43 | * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.) | 44 | * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.) |
| 44 | * | 45 | * |
| 46 | * IRQ handling needs a workaround because of a shortcoming in handling | ||
| 47 | * edge triggered IRQs on some platforms like the OMAP1/2. These | ||
| 48 | * platforms don't handle the ARM lazy IRQ disabling properly, thus we | ||
| 49 | * have to maintain our own SW IRQ disabled status. This should be | ||
| 50 | * removed as soon as the affected platform's IRQ handling is fixed. | ||
| 51 | * | ||
| 45 | * app note sbaa036 talks in more detail about accurate sampling... | 52 | * app note sbaa036 talks in more detail about accurate sampling... |
| 46 | * that ought to help in situations like LCDs inducing noise (which | 53 | * that ought to help in situations like LCDs inducing noise (which |
| 47 | * can also be helped by using synch signals) and more generally. | 54 | * can also be helped by using synch signals) and more generally. |
| 55 | * This driver tries to utilize the measures described in the app | ||
| 56 | * note. The strength of filtering can be set in the board-* specific | ||
| 57 | * files. | ||
| 48 | */ | 58 | */ |
| 49 | 59 | ||
| 50 | #define TS_POLL_PERIOD msecs_to_jiffies(10) | 60 | #define TS_POLL_PERIOD msecs_to_jiffies(10) |
| @@ -61,6 +71,7 @@ struct ts_event { | |||
| 61 | __be16 x; | 71 | __be16 x; |
| 62 | __be16 y; | 72 | __be16 y; |
| 63 | __be16 z1, z2; | 73 | __be16 z1, z2; |
| 74 | int ignore; | ||
| 64 | }; | 75 | }; |
| 65 | 76 | ||
| 66 | struct ads7846 { | 77 | struct ads7846 { |
| @@ -71,12 +82,23 @@ struct ads7846 { | |||
| 71 | u16 model; | 82 | u16 model; |
| 72 | u16 vref_delay_usecs; | 83 | u16 vref_delay_usecs; |
| 73 | u16 x_plate_ohms; | 84 | u16 x_plate_ohms; |
| 85 | u16 pressure_max; | ||
| 74 | 86 | ||
| 75 | u8 read_x, read_y, read_z1, read_z2; | 87 | u8 read_x, read_y, read_z1, read_z2, pwrdown; |
| 88 | u16 dummy; /* for the pwrdown read */ | ||
| 76 | struct ts_event tc; | 89 | struct ts_event tc; |
| 77 | 90 | ||
| 78 | struct spi_transfer xfer[8]; | 91 | struct spi_transfer xfer[10]; |
| 79 | struct spi_message msg; | 92 | struct spi_message msg[5]; |
| 93 | struct spi_message *last_msg; | ||
| 94 | int msg_idx; | ||
| 95 | int read_cnt; | ||
| 96 | int read_rep; | ||
| 97 | int last_read; | ||
| 98 | |||
| 99 | u16 debounce_max; | ||
| 100 | u16 debounce_tol; | ||
| 101 | u16 debounce_rep; | ||
| 80 | 102 | ||
| 81 | spinlock_t lock; | 103 | spinlock_t lock; |
| 82 | struct timer_list timer; /* P: lock */ | 104 | struct timer_list timer; /* P: lock */ |
| @@ -84,6 +106,9 @@ struct ads7846 { | |||
| 84 | unsigned pending:1; /* P: lock */ | 106 | unsigned pending:1; /* P: lock */ |
| 85 | // FIXME remove "irq_disabled" | 107 | // FIXME remove "irq_disabled" |
| 86 | unsigned irq_disabled:1; /* P: lock */ | 108 | unsigned irq_disabled:1; /* P: lock */ |
| 109 | unsigned disabled:1; | ||
| 110 | |||
| 111 | int (*get_pendown_state)(void); | ||
| 87 | }; | 112 | }; |
| 88 | 113 | ||
| 89 | /* leave chip selected when we're done, for quicker re-select? */ | 114 | /* leave chip selected when we're done, for quicker re-select? */ |
| @@ -125,7 +150,9 @@ struct ads7846 { | |||
| 125 | #define READ_Y (READ_12BIT_DFR(y) | ADS_PD10_ADC_ON) | 150 | #define READ_Y (READ_12BIT_DFR(y) | ADS_PD10_ADC_ON) |
| 126 | #define READ_Z1 (READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON) | 151 | #define READ_Z1 (READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON) |
| 127 | #define READ_Z2 (READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON) | 152 | #define READ_Z2 (READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON) |
| 128 | #define READ_X (READ_12BIT_DFR(x) | ADS_PD10_PDOWN) /* LAST */ | 153 | |
| 154 | #define READ_X (READ_12BIT_DFR(x) | ADS_PD10_ADC_ON) | ||
| 155 | #define PWRDOWN (READ_12BIT_DFR(y) | ADS_PD10_PDOWN) /* LAST */ | ||
| 129 | 156 | ||
| 130 | /* single-ended samples need to first power up reference voltage; | 157 | /* single-ended samples need to first power up reference voltage; |
| 131 | * we leave both ADC and VREF powered | 158 | * we leave both ADC and VREF powered |
| @@ -152,6 +179,15 @@ struct ser_req { | |||
| 152 | struct spi_transfer xfer[6]; | 179 | struct spi_transfer xfer[6]; |
| 153 | }; | 180 | }; |
| 154 | 181 | ||
| 182 | static void ads7846_enable(struct ads7846 *ts); | ||
| 183 | static void ads7846_disable(struct ads7846 *ts); | ||
| 184 | |||
| 185 | static int device_suspended(struct device *dev) | ||
| 186 | { | ||
| 187 | struct ads7846 *ts = dev_get_drvdata(dev); | ||
| 188 | return dev->power.power_state.event != PM_EVENT_ON || ts->disabled; | ||
| 189 | } | ||
| 190 | |||
| 155 | static int ads7846_read12_ser(struct device *dev, unsigned command) | 191 | static int ads7846_read12_ser(struct device *dev, unsigned command) |
| 156 | { | 192 | { |
| 157 | struct spi_device *spi = to_spi_device(dev); | 193 | struct spi_device *spi = to_spi_device(dev); |
| @@ -164,7 +200,7 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) | |||
| 164 | if (!req) | 200 | if (!req) |
| 165 | return -ENOMEM; | 201 | return -ENOMEM; |
| 166 | 202 | ||
| 167 | INIT_LIST_HEAD(&req->msg.transfers); | 203 | spi_message_init(&req->msg); |
| 168 | 204 | ||
| 169 | /* activate reference, so it has time to settle; */ | 205 | /* activate reference, so it has time to settle; */ |
| 170 | req->ref_on = REF_ON; | 206 | req->ref_on = REF_ON; |
| @@ -204,8 +240,10 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) | |||
| 204 | for (i = 0; i < 6; i++) | 240 | for (i = 0; i < 6; i++) |
| 205 | spi_message_add_tail(&req->xfer[i], &req->msg); | 241 | spi_message_add_tail(&req->xfer[i], &req->msg); |
| 206 | 242 | ||
| 243 | ts->irq_disabled = 1; | ||
| 207 | disable_irq(spi->irq); | 244 | disable_irq(spi->irq); |
| 208 | status = spi_sync(spi, &req->msg); | 245 | status = spi_sync(spi, &req->msg); |
| 246 | ts->irq_disabled = 0; | ||
| 209 | enable_irq(spi->irq); | 247 | enable_irq(spi->irq); |
| 210 | 248 | ||
| 211 | if (req->msg.status) | 249 | if (req->msg.status) |
| @@ -233,6 +271,52 @@ SHOW(temp1) | |||
| 233 | SHOW(vaux) | 271 | SHOW(vaux) |
| 234 | SHOW(vbatt) | 272 | SHOW(vbatt) |
| 235 | 273 | ||
| 274 | static int is_pen_down(struct device *dev) | ||
| 275 | { | ||
| 276 | struct ads7846 *ts = dev_get_drvdata(dev); | ||
| 277 | |||
| 278 | return ts->pendown; | ||
| 279 | } | ||
| 280 | |||
| 281 | static ssize_t ads7846_pen_down_show(struct device *dev, | ||
| 282 | struct device_attribute *attr, char *buf) | ||
| 283 | { | ||
| 284 | return sprintf(buf, "%u\n", is_pen_down(dev)); | ||
| 285 | } | ||
| 286 | |||
| 287 | static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL); | ||
| 288 | |||
| 289 | static ssize_t ads7846_disable_show(struct device *dev, | ||
| 290 | struct device_attribute *attr, char *buf) | ||
| 291 | { | ||
| 292 | struct ads7846 *ts = dev_get_drvdata(dev); | ||
| 293 | |||
| 294 | return sprintf(buf, "%u\n", ts->disabled); | ||
| 295 | } | ||
| 296 | |||
| 297 | static ssize_t ads7846_disable_store(struct device *dev, | ||
| 298 | struct device_attribute *attr, | ||
| 299 | const char *buf, size_t count) | ||
| 300 | { | ||
| 301 | struct ads7846 *ts = dev_get_drvdata(dev); | ||
| 302 | char *endp; | ||
| 303 | int i; | ||
| 304 | |||
| 305 | i = simple_strtoul(buf, &endp, 10); | ||
| 306 | spin_lock_irq(&ts->lock); | ||
| 307 | |||
| 308 | if (i) | ||
| 309 | ads7846_disable(ts); | ||
| 310 | else | ||
| 311 | ads7846_enable(ts); | ||
| 312 | |||
| 313 | spin_unlock_irq(&ts->lock); | ||
| 314 | |||
| 315 | return count; | ||
| 316 | } | ||
| 317 | |||
| 318 | static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store); | ||
| 319 | |||
| 236 | /*--------------------------------------------------------------------------*/ | 320 | /*--------------------------------------------------------------------------*/ |
| 237 | 321 | ||
| 238 | /* | 322 | /* |
| @@ -264,7 +348,7 @@ static void ads7846_rx(void *ads) | |||
| 264 | if (x == MAX_12BIT) | 348 | if (x == MAX_12BIT) |
| 265 | x = 0; | 349 | x = 0; |
| 266 | 350 | ||
| 267 | if (x && z1 && ts->spi->dev.power.power_state.event == PM_EVENT_ON) { | 351 | if (likely(x && z1 && !device_suspended(&ts->spi->dev))) { |
| 268 | /* compute touch pressure resistance using equation #2 */ | 352 | /* compute touch pressure resistance using equation #2 */ |
| 269 | Rt = z2; | 353 | Rt = z2; |
| 270 | Rt -= z1; | 354 | Rt -= z1; |
| @@ -275,6 +359,14 @@ static void ads7846_rx(void *ads) | |||
| 275 | } else | 359 | } else |
| 276 | Rt = 0; | 360 | Rt = 0; |
| 277 | 361 | ||
| 362 | /* Sample found inconsistent by debouncing or pressure is beyond | ||
| 363 | * the maximum. Don't report it to user space, repeat at least | ||
| 364 | * once more the measurement */ | ||
| 365 | if (ts->tc.ignore || Rt > ts->pressure_max) { | ||
| 366 | mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); | ||
| 367 | return; | ||
| 368 | } | ||
| 369 | |||
| 278 | /* NOTE: "pendown" is inferred from pressure; we don't rely on | 370 | /* NOTE: "pendown" is inferred from pressure; we don't rely on |
| 279 | * being able to check nPENIRQ status, or "friendly" trigger modes | 371 | * being able to check nPENIRQ status, or "friendly" trigger modes |
| 280 | * (both-edges is much better than just-falling or low-level). | 372 | * (both-edges is much better than just-falling or low-level). |
| @@ -296,11 +388,13 @@ static void ads7846_rx(void *ads) | |||
| 296 | if (Rt) { | 388 | if (Rt) { |
| 297 | input_report_abs(input_dev, ABS_X, x); | 389 | input_report_abs(input_dev, ABS_X, x); |
| 298 | input_report_abs(input_dev, ABS_Y, y); | 390 | input_report_abs(input_dev, ABS_Y, y); |
| 299 | input_report_abs(input_dev, ABS_PRESSURE, Rt); | ||
| 300 | sync = 1; | 391 | sync = 1; |
| 301 | } | 392 | } |
| 302 | if (sync) | 393 | |
| 394 | if (sync) { | ||
| 395 | input_report_abs(input_dev, ABS_PRESSURE, Rt); | ||
| 303 | input_sync(input_dev); | 396 | input_sync(input_dev); |
| 397 | } | ||
| 304 | 398 | ||
| 305 | #ifdef VERBOSE | 399 | #ifdef VERBOSE |
| 306 | if (Rt || ts->pendown) | 400 | if (Rt || ts->pendown) |
| @@ -308,80 +402,138 @@ static void ads7846_rx(void *ads) | |||
| 308 | x, y, Rt, Rt ? "" : " UP"); | 402 | x, y, Rt, Rt ? "" : " UP"); |
| 309 | #endif | 403 | #endif |
| 310 | 404 | ||
| 311 | /* don't retrigger while we're suspended */ | ||
| 312 | spin_lock_irqsave(&ts->lock, flags); | 405 | spin_lock_irqsave(&ts->lock, flags); |
| 313 | 406 | ||
| 314 | ts->pendown = (Rt != 0); | 407 | ts->pendown = (Rt != 0); |
| 315 | ts->pending = 0; | 408 | mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); |
| 316 | 409 | ||
| 317 | if (ts->spi->dev.power.power_state.event == PM_EVENT_ON) { | 410 | spin_unlock_irqrestore(&ts->lock, flags); |
| 318 | if (ts->pendown) | 411 | } |
| 319 | mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); | 412 | |
| 320 | else if (ts->irq_disabled) { | 413 | static void ads7846_debounce(void *ads) |
| 321 | ts->irq_disabled = 0; | 414 | { |
| 322 | enable_irq(ts->spi->irq); | 415 | struct ads7846 *ts = ads; |
| 416 | struct spi_message *m; | ||
| 417 | struct spi_transfer *t; | ||
| 418 | int val; | ||
| 419 | int status; | ||
| 420 | |||
| 421 | m = &ts->msg[ts->msg_idx]; | ||
| 422 | t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list); | ||
| 423 | val = (*(u16 *)t->rx_buf) >> 3; | ||
| 424 | if (!ts->read_cnt || (abs(ts->last_read - val) > ts->debounce_tol)) { | ||
| 425 | /* Repeat it, if this was the first read or the read | ||
| 426 | * wasn't consistent enough. */ | ||
| 427 | if (ts->read_cnt < ts->debounce_max) { | ||
| 428 | ts->last_read = val; | ||
| 429 | ts->read_cnt++; | ||
| 430 | } else { | ||
| 431 | /* Maximum number of debouncing reached and still | ||
| 432 | * not enough number of consistent readings. Abort | ||
| 433 | * the whole sample, repeat it in the next sampling | ||
| 434 | * period. | ||
| 435 | */ | ||
| 436 | ts->tc.ignore = 1; | ||
| 437 | ts->read_cnt = 0; | ||
| 438 | /* Last message will contain ads7846_rx() as the | ||
| 439 | * completion function. | ||
| 440 | */ | ||
| 441 | m = ts->last_msg; | ||
| 323 | } | 442 | } |
| 443 | /* Start over collecting consistent readings. */ | ||
| 444 | ts->read_rep = 0; | ||
| 445 | } else { | ||
| 446 | if (++ts->read_rep > ts->debounce_rep) { | ||
| 447 | /* Got a good reading for this coordinate, | ||
| 448 | * go for the next one. */ | ||
| 449 | ts->tc.ignore = 0; | ||
| 450 | ts->msg_idx++; | ||
| 451 | ts->read_cnt = 0; | ||
| 452 | ts->read_rep = 0; | ||
| 453 | m++; | ||
| 454 | } else | ||
| 455 | /* Read more values that are consistent. */ | ||
| 456 | ts->read_cnt++; | ||
| 324 | } | 457 | } |
| 325 | 458 | status = spi_async(ts->spi, m); | |
| 326 | spin_unlock_irqrestore(&ts->lock, flags); | 459 | if (status) |
| 460 | dev_err(&ts->spi->dev, "spi_async --> %d\n", | ||
| 461 | status); | ||
| 327 | } | 462 | } |
| 328 | 463 | ||
| 329 | static void ads7846_timer(unsigned long handle) | 464 | static void ads7846_timer(unsigned long handle) |
| 330 | { | 465 | { |
| 331 | struct ads7846 *ts = (void *)handle; | 466 | struct ads7846 *ts = (void *)handle; |
| 332 | int status = 0; | 467 | int status = 0; |
| 333 | unsigned long flags; | 468 | |
| 469 | spin_lock_irq(&ts->lock); | ||
| 470 | |||
| 471 | if (unlikely(ts->msg_idx && !ts->pendown)) { | ||
| 472 | /* measurment cycle ended */ | ||
| 473 | if (!device_suspended(&ts->spi->dev)) { | ||
| 474 | ts->irq_disabled = 0; | ||
| 475 | enable_irq(ts->spi->irq); | ||
| 476 | } | ||
| 477 | ts->pending = 0; | ||
| 478 | ts->msg_idx = 0; | ||
| 479 | } else { | ||
| 480 | /* pen is still down, continue with the measurement */ | ||
| 481 | ts->msg_idx = 0; | ||
| 482 | status = spi_async(ts->spi, &ts->msg[0]); | ||
| 483 | if (status) | ||
| 484 | dev_err(&ts->spi->dev, "spi_async --> %d\n", status); | ||
| 485 | } | ||
| 486 | |||
| 487 | spin_unlock_irq(&ts->lock); | ||
| 488 | } | ||
| 489 | |||
| 490 | static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs) | ||
| 491 | { | ||
| 492 | struct ads7846 *ts = handle; | ||
| 493 | unsigned long flags; | ||
| 334 | 494 | ||
| 335 | spin_lock_irqsave(&ts->lock, flags); | 495 | spin_lock_irqsave(&ts->lock, flags); |
| 336 | if (!ts->pending) { | 496 | if (likely(ts->get_pendown_state())) { |
| 337 | ts->pending = 1; | ||
| 338 | if (!ts->irq_disabled) { | 497 | if (!ts->irq_disabled) { |
| 498 | /* REVISIT irq logic for many ARM chips has cloned a | ||
| 499 | * bug wherein disabling an irq in its handler won't | ||
| 500 | * work;(it's disabled lazily, and too late to work. | ||
| 501 | * until all their irq logic is fixed, we must shadow | ||
| 502 | * that state here. | ||
| 503 | */ | ||
| 339 | ts->irq_disabled = 1; | 504 | ts->irq_disabled = 1; |
| 340 | disable_irq(ts->spi->irq); | 505 | disable_irq(ts->spi->irq); |
| 506 | ts->pending = 1; | ||
| 507 | mod_timer(&ts->timer, jiffies); | ||
| 341 | } | 508 | } |
| 342 | status = spi_async(ts->spi, &ts->msg); | ||
| 343 | if (status) | ||
| 344 | dev_err(&ts->spi->dev, "spi_async --> %d\n", | ||
| 345 | status); | ||
| 346 | } | 509 | } |
| 347 | spin_unlock_irqrestore(&ts->lock, flags); | 510 | spin_unlock_irqrestore(&ts->lock, flags); |
| 348 | } | ||
| 349 | 511 | ||
| 350 | static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs) | ||
| 351 | { | ||
| 352 | ads7846_timer((unsigned long) handle); | ||
| 353 | return IRQ_HANDLED; | 512 | return IRQ_HANDLED; |
| 354 | } | 513 | } |
| 355 | 514 | ||
| 356 | /*--------------------------------------------------------------------------*/ | 515 | /*--------------------------------------------------------------------------*/ |
| 357 | 516 | ||
| 358 | static int | 517 | /* Must be called with ts->lock held */ |
| 359 | ads7846_suspend(struct spi_device *spi, pm_message_t message) | 518 | static void ads7846_disable(struct ads7846 *ts) |
| 360 | { | 519 | { |
| 361 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | 520 | if (ts->disabled) |
| 362 | unsigned long flags; | 521 | return; |
| 363 | 522 | ||
| 364 | spin_lock_irqsave(&ts->lock, flags); | 523 | ts->disabled = 1; |
| 365 | |||
| 366 | spi->dev.power.power_state = message; | ||
| 367 | 524 | ||
| 368 | /* are we waiting for IRQ, or polling? */ | 525 | /* are we waiting for IRQ, or polling? */ |
| 369 | if (!ts->pendown) { | 526 | if (!ts->pending) { |
| 370 | if (!ts->irq_disabled) { | 527 | ts->irq_disabled = 1; |
| 371 | ts->irq_disabled = 1; | 528 | disable_irq(ts->spi->irq); |
| 372 | disable_irq(ts->spi->irq); | ||
| 373 | } | ||
| 374 | } else { | 529 | } else { |
| 375 | /* polling; force a final SPI completion; | 530 | /* the timer will run at least once more, and |
| 376 | * that will clean things up neatly | 531 | * leave everything in a clean state, IRQ disabled |
| 377 | */ | 532 | */ |
| 378 | if (!ts->pending) | 533 | while (ts->pending) { |
| 379 | mod_timer(&ts->timer, jiffies); | 534 | spin_unlock_irq(&ts->lock); |
| 380 | 535 | msleep(1); | |
| 381 | while (ts->pendown || ts->pending) { | 536 | spin_lock_irq(&ts->lock); |
| 382 | spin_unlock_irqrestore(&ts->lock, flags); | ||
| 383 | udelay(10); | ||
| 384 | spin_lock_irqsave(&ts->lock, flags); | ||
| 385 | } | 537 | } |
| 386 | } | 538 | } |
| 387 | 539 | ||
| @@ -389,17 +541,45 @@ ads7846_suspend(struct spi_device *spi, pm_message_t message) | |||
| 389 | * leave it that way after every request | 541 | * leave it that way after every request |
| 390 | */ | 542 | */ |
| 391 | 543 | ||
| 392 | spin_unlock_irqrestore(&ts->lock, flags); | 544 | } |
| 545 | |||
| 546 | /* Must be called with ts->lock held */ | ||
| 547 | static void ads7846_enable(struct ads7846 *ts) | ||
| 548 | { | ||
| 549 | if (!ts->disabled) | ||
| 550 | return; | ||
| 551 | |||
| 552 | ts->disabled = 0; | ||
| 553 | ts->irq_disabled = 0; | ||
| 554 | enable_irq(ts->spi->irq); | ||
| 555 | } | ||
| 556 | |||
| 557 | static int ads7846_suspend(struct spi_device *spi, pm_message_t message) | ||
| 558 | { | ||
| 559 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | ||
| 560 | |||
| 561 | spin_lock_irq(&ts->lock); | ||
| 562 | |||
| 563 | spi->dev.power.power_state = message; | ||
| 564 | ads7846_disable(ts); | ||
| 565 | |||
| 566 | spin_unlock_irq(&ts->lock); | ||
| 567 | |||
| 393 | return 0; | 568 | return 0; |
| 569 | |||
| 394 | } | 570 | } |
| 395 | 571 | ||
| 396 | static int ads7846_resume(struct spi_device *spi) | 572 | static int ads7846_resume(struct spi_device *spi) |
| 397 | { | 573 | { |
| 398 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | 574 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); |
| 399 | 575 | ||
| 400 | ts->irq_disabled = 0; | 576 | spin_lock_irq(&ts->lock); |
| 401 | enable_irq(ts->spi->irq); | 577 | |
| 402 | spi->dev.power.power_state = PMSG_ON; | 578 | spi->dev.power.power_state = PMSG_ON; |
| 579 | ads7846_enable(ts); | ||
| 580 | |||
| 581 | spin_unlock_irq(&ts->lock); | ||
| 582 | |||
| 403 | return 0; | 583 | return 0; |
| 404 | } | 584 | } |
| 405 | 585 | ||
| @@ -408,6 +588,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
| 408 | struct ads7846 *ts; | 588 | struct ads7846 *ts; |
| 409 | struct input_dev *input_dev; | 589 | struct input_dev *input_dev; |
| 410 | struct ads7846_platform_data *pdata = spi->dev.platform_data; | 590 | struct ads7846_platform_data *pdata = spi->dev.platform_data; |
| 591 | struct spi_message *m; | ||
| 411 | struct spi_transfer *x; | 592 | struct spi_transfer *x; |
| 412 | int err; | 593 | int err; |
| 413 | 594 | ||
| @@ -428,6 +609,11 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
| 428 | return -EINVAL; | 609 | return -EINVAL; |
| 429 | } | 610 | } |
| 430 | 611 | ||
| 612 | if (pdata->get_pendown_state == NULL) { | ||
| 613 | dev_dbg(&spi->dev, "no get_pendown_state function?\n"); | ||
| 614 | return -EINVAL; | ||
| 615 | } | ||
| 616 | |||
| 431 | /* We'd set the wordsize to 12 bits ... except that some controllers | 617 | /* We'd set the wordsize to 12 bits ... except that some controllers |
| 432 | * will then treat the 8 bit command words as 12 bits (and drop the | 618 | * will then treat the 8 bit command words as 12 bits (and drop the |
| 433 | * four MSBs of the 12 bit result). Result: inputs must be shifted | 619 | * four MSBs of the 12 bit result). Result: inputs must be shifted |
| @@ -451,9 +637,21 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
| 451 | ts->timer.data = (unsigned long) ts; | 637 | ts->timer.data = (unsigned long) ts; |
| 452 | ts->timer.function = ads7846_timer; | 638 | ts->timer.function = ads7846_timer; |
| 453 | 639 | ||
| 640 | spin_lock_init(&ts->lock); | ||
| 641 | |||
| 454 | ts->model = pdata->model ? : 7846; | 642 | ts->model = pdata->model ? : 7846; |
| 455 | ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; | 643 | ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; |
| 456 | ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; | 644 | ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; |
| 645 | ts->pressure_max = pdata->pressure_max ? : ~0; | ||
| 646 | if (pdata->debounce_max) { | ||
| 647 | ts->debounce_max = pdata->debounce_max; | ||
| 648 | ts->debounce_tol = pdata->debounce_tol; | ||
| 649 | ts->debounce_rep = pdata->debounce_rep; | ||
| 650 | if (ts->debounce_rep > ts->debounce_max + 1) | ||
| 651 | ts->debounce_rep = ts->debounce_max - 1; | ||
| 652 | } else | ||
| 653 | ts->debounce_tol = ~0; | ||
| 654 | ts->get_pendown_state = pdata->get_pendown_state; | ||
| 457 | 655 | ||
| 458 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id); | 656 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id); |
| 459 | 657 | ||
| @@ -477,60 +675,100 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
| 477 | /* set up the transfers to read touchscreen state; this assumes we | 675 | /* set up the transfers to read touchscreen state; this assumes we |
| 478 | * use formula #2 for pressure, not #3. | 676 | * use formula #2 for pressure, not #3. |
| 479 | */ | 677 | */ |
| 480 | INIT_LIST_HEAD(&ts->msg.transfers); | 678 | m = &ts->msg[0]; |
| 481 | x = ts->xfer; | 679 | x = ts->xfer; |
| 482 | 680 | ||
| 681 | spi_message_init(m); | ||
| 682 | |||
| 483 | /* y- still on; turn on only y+ (and ADC) */ | 683 | /* y- still on; turn on only y+ (and ADC) */ |
| 484 | ts->read_y = READ_Y; | 684 | ts->read_y = READ_Y; |
| 485 | x->tx_buf = &ts->read_y; | 685 | x->tx_buf = &ts->read_y; |
| 486 | x->len = 1; | 686 | x->len = 1; |
| 487 | spi_message_add_tail(x, &ts->msg); | 687 | spi_message_add_tail(x, m); |
| 488 | 688 | ||
| 489 | x++; | 689 | x++; |
| 490 | x->rx_buf = &ts->tc.y; | 690 | x->rx_buf = &ts->tc.y; |
| 491 | x->len = 2; | 691 | x->len = 2; |
| 492 | spi_message_add_tail(x, &ts->msg); | 692 | spi_message_add_tail(x, m); |
| 693 | |||
| 694 | m->complete = ads7846_debounce; | ||
| 695 | m->context = ts; | ||
| 696 | |||
| 697 | m++; | ||
| 698 | spi_message_init(m); | ||
| 699 | |||
| 700 | /* turn y- off, x+ on, then leave in lowpower */ | ||
| 701 | x++; | ||
| 702 | ts->read_x = READ_X; | ||
| 703 | x->tx_buf = &ts->read_x; | ||
| 704 | x->len = 1; | ||
| 705 | spi_message_add_tail(x, m); | ||
| 706 | |||
| 707 | x++; | ||
| 708 | x->rx_buf = &ts->tc.x; | ||
| 709 | x->len = 2; | ||
| 710 | spi_message_add_tail(x, m); | ||
| 711 | |||
| 712 | m->complete = ads7846_debounce; | ||
| 713 | m->context = ts; | ||
| 493 | 714 | ||
| 494 | /* turn y+ off, x- on; we'll use formula #2 */ | 715 | /* turn y+ off, x- on; we'll use formula #2 */ |
| 495 | if (ts->model == 7846) { | 716 | if (ts->model == 7846) { |
| 717 | m++; | ||
| 718 | spi_message_init(m); | ||
| 719 | |||
| 496 | x++; | 720 | x++; |
| 497 | ts->read_z1 = READ_Z1; | 721 | ts->read_z1 = READ_Z1; |
| 498 | x->tx_buf = &ts->read_z1; | 722 | x->tx_buf = &ts->read_z1; |
| 499 | x->len = 1; | 723 | x->len = 1; |
| 500 | spi_message_add_tail(x, &ts->msg); | 724 | spi_message_add_tail(x, m); |
| 501 | 725 | ||
| 502 | x++; | 726 | x++; |
| 503 | x->rx_buf = &ts->tc.z1; | 727 | x->rx_buf = &ts->tc.z1; |
| 504 | x->len = 2; | 728 | x->len = 2; |
| 505 | spi_message_add_tail(x, &ts->msg); | 729 | spi_message_add_tail(x, m); |
| 730 | |||
| 731 | m->complete = ads7846_debounce; | ||
| 732 | m->context = ts; | ||
| 733 | |||
| 734 | m++; | ||
| 735 | spi_message_init(m); | ||
| 506 | 736 | ||
| 507 | x++; | 737 | x++; |
| 508 | ts->read_z2 = READ_Z2; | 738 | ts->read_z2 = READ_Z2; |
| 509 | x->tx_buf = &ts->read_z2; | 739 | x->tx_buf = &ts->read_z2; |
| 510 | x->len = 1; | 740 | x->len = 1; |
| 511 | spi_message_add_tail(x, &ts->msg); | 741 | spi_message_add_tail(x, m); |
| 512 | 742 | ||
| 513 | x++; | 743 | x++; |
| 514 | x->rx_buf = &ts->tc.z2; | 744 | x->rx_buf = &ts->tc.z2; |
| 515 | x->len = 2; | 745 | x->len = 2; |
| 516 | spi_message_add_tail(x, &ts->msg); | 746 | spi_message_add_tail(x, m); |
| 747 | |||
| 748 | m->complete = ads7846_debounce; | ||
| 749 | m->context = ts; | ||
| 517 | } | 750 | } |
| 518 | 751 | ||
| 519 | /* turn y- off, x+ on, then leave in lowpower */ | 752 | /* power down */ |
| 753 | m++; | ||
| 754 | spi_message_init(m); | ||
| 755 | |||
| 520 | x++; | 756 | x++; |
| 521 | ts->read_x = READ_X; | 757 | ts->pwrdown = PWRDOWN; |
| 522 | x->tx_buf = &ts->read_x; | 758 | x->tx_buf = &ts->pwrdown; |
| 523 | x->len = 1; | 759 | x->len = 1; |
| 524 | spi_message_add_tail(x, &ts->msg); | 760 | spi_message_add_tail(x, m); |
| 525 | 761 | ||
| 526 | x++; | 762 | x++; |
| 527 | x->rx_buf = &ts->tc.x; | 763 | x->rx_buf = &ts->dummy; |
| 528 | x->len = 2; | 764 | x->len = 2; |
| 529 | CS_CHANGE(*x); | 765 | CS_CHANGE(*x); |
| 530 | spi_message_add_tail(x, &ts->msg); | 766 | spi_message_add_tail(x, m); |
| 531 | 767 | ||
| 532 | ts->msg.complete = ads7846_rx; | 768 | m->complete = ads7846_rx; |
| 533 | ts->msg.context = ts; | 769 | m->context = ts; |
| 770 | |||
| 771 | ts->last_msg = m; | ||
| 534 | 772 | ||
| 535 | if (request_irq(spi->irq, ads7846_irq, | 773 | if (request_irq(spi->irq, ads7846_irq, |
| 536 | SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING, | 774 | SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING, |
| @@ -559,13 +797,27 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
| 559 | device_create_file(&spi->dev, &dev_attr_vbatt); | 797 | device_create_file(&spi->dev, &dev_attr_vbatt); |
| 560 | device_create_file(&spi->dev, &dev_attr_vaux); | 798 | device_create_file(&spi->dev, &dev_attr_vaux); |
| 561 | 799 | ||
| 800 | device_create_file(&spi->dev, &dev_attr_pen_down); | ||
| 801 | |||
| 802 | device_create_file(&spi->dev, &dev_attr_disable); | ||
| 803 | |||
| 562 | err = input_register_device(input_dev); | 804 | err = input_register_device(input_dev); |
| 563 | if (err) | 805 | if (err) |
| 564 | goto err_free_irq; | 806 | goto err_remove_attr; |
| 565 | 807 | ||
| 566 | return 0; | 808 | return 0; |
| 567 | 809 | ||
| 568 | err_free_irq: | 810 | err_remove_attr: |
| 811 | device_remove_file(&spi->dev, &dev_attr_disable); | ||
| 812 | device_remove_file(&spi->dev, &dev_attr_pen_down); | ||
| 813 | if (ts->model == 7846) { | ||
| 814 | device_remove_file(&spi->dev, &dev_attr_temp1); | ||
| 815 | device_remove_file(&spi->dev, &dev_attr_temp0); | ||
| 816 | } | ||
| 817 | if (ts->model != 7845) | ||
| 818 | device_remove_file(&spi->dev, &dev_attr_vbatt); | ||
| 819 | device_remove_file(&spi->dev, &dev_attr_vaux); | ||
| 820 | |||
| 569 | free_irq(spi->irq, ts); | 821 | free_irq(spi->irq, ts); |
| 570 | err_free_mem: | 822 | err_free_mem: |
| 571 | input_free_device(input_dev); | 823 | input_free_device(input_dev); |
| @@ -577,20 +829,24 @@ static int __devexit ads7846_remove(struct spi_device *spi) | |||
| 577 | { | 829 | { |
| 578 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | 830 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); |
| 579 | 831 | ||
| 832 | input_unregister_device(ts->input); | ||
| 833 | |||
| 580 | ads7846_suspend(spi, PMSG_SUSPEND); | 834 | ads7846_suspend(spi, PMSG_SUSPEND); |
| 581 | free_irq(ts->spi->irq, ts); | ||
| 582 | if (ts->irq_disabled) | ||
| 583 | enable_irq(ts->spi->irq); | ||
| 584 | 835 | ||
| 836 | device_remove_file(&spi->dev, &dev_attr_disable); | ||
| 837 | device_remove_file(&spi->dev, &dev_attr_pen_down); | ||
| 585 | if (ts->model == 7846) { | 838 | if (ts->model == 7846) { |
| 586 | device_remove_file(&spi->dev, &dev_attr_temp0); | ||
| 587 | device_remove_file(&spi->dev, &dev_attr_temp1); | 839 | device_remove_file(&spi->dev, &dev_attr_temp1); |
| 840 | device_remove_file(&spi->dev, &dev_attr_temp0); | ||
| 588 | } | 841 | } |
| 589 | if (ts->model != 7845) | 842 | if (ts->model != 7845) |
| 590 | device_remove_file(&spi->dev, &dev_attr_vbatt); | 843 | device_remove_file(&spi->dev, &dev_attr_vbatt); |
| 591 | device_remove_file(&spi->dev, &dev_attr_vaux); | 844 | device_remove_file(&spi->dev, &dev_attr_vaux); |
| 592 | 845 | ||
| 593 | input_unregister_device(ts->input); | 846 | free_irq(ts->spi->irq, ts); |
| 847 | /* suspend left the IRQ disabled */ | ||
| 848 | enable_irq(ts->spi->irq); | ||
| 849 | |||
| 594 | kfree(ts); | 850 | kfree(ts); |
| 595 | 851 | ||
| 596 | dev_dbg(&spi->dev, "unregistered touchscreen\n"); | 852 | dev_dbg(&spi->dev, "unregistered touchscreen\n"); |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 6081941de1b3..4070eff6f0f8 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
| @@ -315,10 +315,11 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int | |||
| 315 | if (r1_bio->bios[mirror] == bio) | 315 | if (r1_bio->bios[mirror] == bio) |
| 316 | break; | 316 | break; |
| 317 | 317 | ||
| 318 | if (error == -ENOTSUPP && test_bit(R1BIO_Barrier, &r1_bio->state)) { | 318 | if (error == -EOPNOTSUPP && test_bit(R1BIO_Barrier, &r1_bio->state)) { |
| 319 | set_bit(BarriersNotsupp, &conf->mirrors[mirror].rdev->flags); | 319 | set_bit(BarriersNotsupp, &conf->mirrors[mirror].rdev->flags); |
| 320 | set_bit(R1BIO_BarrierRetry, &r1_bio->state); | 320 | set_bit(R1BIO_BarrierRetry, &r1_bio->state); |
| 321 | r1_bio->mddev->barriers_work = 0; | 321 | r1_bio->mddev->barriers_work = 0; |
| 322 | /* Don't rdev_dec_pending in this branch - keep it for the retry */ | ||
| 322 | } else { | 323 | } else { |
| 323 | /* | 324 | /* |
| 324 | * this branch is our 'one mirror IO has finished' event handler: | 325 | * this branch is our 'one mirror IO has finished' event handler: |
| @@ -365,6 +366,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int | |||
| 365 | } | 366 | } |
| 366 | } | 367 | } |
| 367 | } | 368 | } |
| 369 | rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev); | ||
| 368 | } | 370 | } |
| 369 | /* | 371 | /* |
| 370 | * | 372 | * |
| @@ -374,11 +376,9 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int | |||
| 374 | if (atomic_dec_and_test(&r1_bio->remaining)) { | 376 | if (atomic_dec_and_test(&r1_bio->remaining)) { |
| 375 | if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) { | 377 | if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) { |
| 376 | reschedule_retry(r1_bio); | 378 | reschedule_retry(r1_bio); |
| 377 | /* Don't dec_pending yet, we want to hold | ||
| 378 | * the reference over the retry | ||
| 379 | */ | ||
| 380 | goto out; | 379 | goto out; |
| 381 | } | 380 | } |
| 381 | /* it really is the end of this request */ | ||
| 382 | if (test_bit(R1BIO_BehindIO, &r1_bio->state)) { | 382 | if (test_bit(R1BIO_BehindIO, &r1_bio->state)) { |
| 383 | /* free extra copy of the data pages */ | 383 | /* free extra copy of the data pages */ |
| 384 | int i = bio->bi_vcnt; | 384 | int i = bio->bi_vcnt; |
| @@ -393,8 +393,6 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int | |||
| 393 | md_write_end(r1_bio->mddev); | 393 | md_write_end(r1_bio->mddev); |
| 394 | raid_end_bio_io(r1_bio); | 394 | raid_end_bio_io(r1_bio); |
| 395 | } | 395 | } |
| 396 | |||
| 397 | rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev); | ||
| 398 | out: | 396 | out: |
| 399 | if (to_put) | 397 | if (to_put) |
| 400 | bio_put(to_put); | 398 | bio_put(to_put); |
| @@ -753,18 +751,24 @@ static int make_request(request_queue_t *q, struct bio * bio) | |||
| 753 | const int rw = bio_data_dir(bio); | 751 | const int rw = bio_data_dir(bio); |
| 754 | int do_barriers; | 752 | int do_barriers; |
| 755 | 753 | ||
| 756 | if (unlikely(!mddev->barriers_work && bio_barrier(bio))) { | ||
| 757 | bio_endio(bio, bio->bi_size, -EOPNOTSUPP); | ||
| 758 | return 0; | ||
| 759 | } | ||
| 760 | |||
| 761 | /* | 754 | /* |
| 762 | * Register the new request and wait if the reconstruction | 755 | * Register the new request and wait if the reconstruction |
| 763 | * thread has put up a bar for new requests. | 756 | * thread has put up a bar for new requests. |
| 764 | * Continue immediately if no resync is active currently. | 757 | * Continue immediately if no resync is active currently. |
| 758 | * We test barriers_work *after* md_write_start as md_write_start | ||
| 759 | * may cause the first superblock write, and that will check out | ||
| 760 | * if barriers work. | ||
| 765 | */ | 761 | */ |
| 762 | |||
| 766 | md_write_start(mddev, bio); /* wait on superblock update early */ | 763 | md_write_start(mddev, bio); /* wait on superblock update early */ |
| 767 | 764 | ||
| 765 | if (unlikely(!mddev->barriers_work && bio_barrier(bio))) { | ||
| 766 | if (rw == WRITE) | ||
| 767 | md_write_end(mddev); | ||
| 768 | bio_endio(bio, bio->bi_size, -EOPNOTSUPP); | ||
| 769 | return 0; | ||
| 770 | } | ||
| 771 | |||
| 768 | wait_barrier(conf); | 772 | wait_barrier(conf); |
| 769 | 773 | ||
| 770 | disk_stat_inc(mddev->gendisk, ios[rw]); | 774 | disk_stat_inc(mddev->gendisk, ios[rw]); |
| @@ -1404,10 +1408,11 @@ static void raid1d(mddev_t *mddev) | |||
| 1404 | unplug = 1; | 1408 | unplug = 1; |
| 1405 | } else if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) { | 1409 | } else if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) { |
| 1406 | /* some requests in the r1bio were BIO_RW_BARRIER | 1410 | /* some requests in the r1bio were BIO_RW_BARRIER |
| 1407 | * requests which failed with -ENOTSUPP. Hohumm.. | 1411 | * requests which failed with -EOPNOTSUPP. Hohumm.. |
| 1408 | * Better resubmit without the barrier. | 1412 | * Better resubmit without the barrier. |
| 1409 | * We know which devices to resubmit for, because | 1413 | * We know which devices to resubmit for, because |
| 1410 | * all others have had their bios[] entry cleared. | 1414 | * all others have had their bios[] entry cleared. |
| 1415 | * We already have a nr_pending reference on these rdevs. | ||
| 1411 | */ | 1416 | */ |
| 1412 | int i; | 1417 | int i; |
| 1413 | clear_bit(R1BIO_BarrierRetry, &r1_bio->state); | 1418 | clear_bit(R1BIO_BarrierRetry, &r1_bio->state); |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 617012bc107a..1440935414e6 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
| @@ -1407,43 +1407,54 @@ static void raid10d(mddev_t *mddev) | |||
| 1407 | if (s > (PAGE_SIZE>>9)) | 1407 | if (s > (PAGE_SIZE>>9)) |
| 1408 | s = PAGE_SIZE >> 9; | 1408 | s = PAGE_SIZE >> 9; |
| 1409 | 1409 | ||
| 1410 | rcu_read_lock(); | ||
| 1410 | do { | 1411 | do { |
| 1411 | int d = r10_bio->devs[sl].devnum; | 1412 | int d = r10_bio->devs[sl].devnum; |
| 1412 | rdev = conf->mirrors[d].rdev; | 1413 | rdev = rcu_dereference(conf->mirrors[d].rdev); |
| 1413 | if (rdev && | 1414 | if (rdev && |
| 1414 | test_bit(In_sync, &rdev->flags) && | 1415 | test_bit(In_sync, &rdev->flags)) { |
| 1415 | sync_page_io(rdev->bdev, | 1416 | atomic_inc(&rdev->nr_pending); |
| 1416 | r10_bio->devs[sl].addr + | 1417 | rcu_read_unlock(); |
| 1417 | sect + rdev->data_offset, | 1418 | success = sync_page_io(rdev->bdev, |
| 1418 | s<<9, | 1419 | r10_bio->devs[sl].addr + |
| 1419 | conf->tmppage, READ)) | 1420 | sect + rdev->data_offset, |
| 1420 | success = 1; | 1421 | s<<9, |
| 1421 | else { | 1422 | conf->tmppage, READ); |
| 1422 | sl++; | 1423 | rdev_dec_pending(rdev, mddev); |
| 1423 | if (sl == conf->copies) | 1424 | rcu_read_lock(); |
| 1424 | sl = 0; | 1425 | if (success) |
| 1426 | break; | ||
| 1425 | } | 1427 | } |
| 1428 | sl++; | ||
| 1429 | if (sl == conf->copies) | ||
| 1430 | sl = 0; | ||
| 1426 | } while (!success && sl != r10_bio->read_slot); | 1431 | } while (!success && sl != r10_bio->read_slot); |
| 1432 | rcu_read_unlock(); | ||
| 1427 | 1433 | ||
| 1428 | if (success) { | 1434 | if (success) { |
| 1429 | int start = sl; | 1435 | int start = sl; |
| 1430 | /* write it back and re-read */ | 1436 | /* write it back and re-read */ |
| 1437 | rcu_read_lock(); | ||
| 1431 | while (sl != r10_bio->read_slot) { | 1438 | while (sl != r10_bio->read_slot) { |
| 1432 | int d; | 1439 | int d; |
| 1433 | if (sl==0) | 1440 | if (sl==0) |
| 1434 | sl = conf->copies; | 1441 | sl = conf->copies; |
| 1435 | sl--; | 1442 | sl--; |
| 1436 | d = r10_bio->devs[sl].devnum; | 1443 | d = r10_bio->devs[sl].devnum; |
| 1437 | rdev = conf->mirrors[d].rdev; | 1444 | rdev = rcu_dereference(conf->mirrors[d].rdev); |
| 1438 | atomic_add(s, &rdev->corrected_errors); | ||
| 1439 | if (rdev && | 1445 | if (rdev && |
| 1440 | test_bit(In_sync, &rdev->flags)) { | 1446 | test_bit(In_sync, &rdev->flags)) { |
| 1447 | atomic_inc(&rdev->nr_pending); | ||
| 1448 | rcu_read_unlock(); | ||
| 1449 | atomic_add(s, &rdev->corrected_errors); | ||
| 1441 | if (sync_page_io(rdev->bdev, | 1450 | if (sync_page_io(rdev->bdev, |
| 1442 | r10_bio->devs[sl].addr + | 1451 | r10_bio->devs[sl].addr + |
| 1443 | sect + rdev->data_offset, | 1452 | sect + rdev->data_offset, |
| 1444 | s<<9, conf->tmppage, WRITE) == 0) | 1453 | s<<9, conf->tmppage, WRITE) == 0) |
| 1445 | /* Well, this device is dead */ | 1454 | /* Well, this device is dead */ |
| 1446 | md_error(mddev, rdev); | 1455 | md_error(mddev, rdev); |
| 1456 | rdev_dec_pending(rdev, mddev); | ||
| 1457 | rcu_read_lock(); | ||
| 1447 | } | 1458 | } |
| 1448 | } | 1459 | } |
| 1449 | sl = start; | 1460 | sl = start; |
| @@ -1453,17 +1464,22 @@ static void raid10d(mddev_t *mddev) | |||
| 1453 | sl = conf->copies; | 1464 | sl = conf->copies; |
| 1454 | sl--; | 1465 | sl--; |
| 1455 | d = r10_bio->devs[sl].devnum; | 1466 | d = r10_bio->devs[sl].devnum; |
| 1456 | rdev = conf->mirrors[d].rdev; | 1467 | rdev = rcu_dereference(conf->mirrors[d].rdev); |
| 1457 | if (rdev && | 1468 | if (rdev && |
| 1458 | test_bit(In_sync, &rdev->flags)) { | 1469 | test_bit(In_sync, &rdev->flags)) { |
| 1470 | atomic_inc(&rdev->nr_pending); | ||
| 1471 | rcu_read_unlock(); | ||
| 1459 | if (sync_page_io(rdev->bdev, | 1472 | if (sync_page_io(rdev->bdev, |
| 1460 | r10_bio->devs[sl].addr + | 1473 | r10_bio->devs[sl].addr + |
| 1461 | sect + rdev->data_offset, | 1474 | sect + rdev->data_offset, |
| 1462 | s<<9, conf->tmppage, READ) == 0) | 1475 | s<<9, conf->tmppage, READ) == 0) |
| 1463 | /* Well, this device is dead */ | 1476 | /* Well, this device is dead */ |
| 1464 | md_error(mddev, rdev); | 1477 | md_error(mddev, rdev); |
| 1478 | rdev_dec_pending(rdev, mddev); | ||
| 1479 | rcu_read_lock(); | ||
| 1465 | } | 1480 | } |
| 1466 | } | 1481 | } |
| 1482 | rcu_read_unlock(); | ||
| 1467 | } else { | 1483 | } else { |
| 1468 | /* Cannot read from anywhere -- bye bye array */ | 1484 | /* Cannot read from anywhere -- bye bye array */ |
| 1469 | md_error(mddev, conf->mirrors[r10_bio->devs[r10_bio->read_slot].devnum].rdev); | 1485 | md_error(mddev, conf->mirrors[r10_bio->devs[r10_bio->read_slot].devnum].rdev); |
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index f9d87b86492c..320b3d9384ba 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c | |||
| @@ -616,7 +616,7 @@ static struct snd_kcontrol_new snd_cx88_capture_volume = { | |||
| 616 | * Only boards with eeprom and byte 1 at eeprom=1 have it | 616 | * Only boards with eeprom and byte 1 at eeprom=1 have it |
| 617 | */ | 617 | */ |
| 618 | 618 | ||
| 619 | static struct pci_device_id cx88_audio_pci_tbl[] = { | 619 | static struct pci_device_id cx88_audio_pci_tbl[] __devinitdata = { |
| 620 | {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, | 620 | {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, |
| 621 | {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, | 621 | {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, |
| 622 | {0, } | 622 | {0, } |
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 73e271e59c6a..beeb612be98f 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
| @@ -69,8 +69,8 @@ | |||
| 69 | 69 | ||
| 70 | #define DRV_MODULE_NAME "tg3" | 70 | #define DRV_MODULE_NAME "tg3" |
| 71 | #define PFX DRV_MODULE_NAME ": " | 71 | #define PFX DRV_MODULE_NAME ": " |
| 72 | #define DRV_MODULE_VERSION "3.56" | 72 | #define DRV_MODULE_VERSION "3.57" |
| 73 | #define DRV_MODULE_RELDATE "Apr 1, 2006" | 73 | #define DRV_MODULE_RELDATE "Apr 28, 2006" |
| 74 | 74 | ||
| 75 | #define TG3_DEF_MAC_MODE 0 | 75 | #define TG3_DEF_MAC_MODE 0 |
| 76 | #define TG3_DEF_RX_MODE 0 | 76 | #define TG3_DEF_RX_MODE 0 |
| @@ -974,6 +974,8 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) | |||
| 974 | return err; | 974 | return err; |
| 975 | } | 975 | } |
| 976 | 976 | ||
| 977 | static void tg3_link_report(struct tg3 *); | ||
| 978 | |||
| 977 | /* This will reset the tigon3 PHY if there is no valid | 979 | /* This will reset the tigon3 PHY if there is no valid |
| 978 | * link unless the FORCE argument is non-zero. | 980 | * link unless the FORCE argument is non-zero. |
| 979 | */ | 981 | */ |
| @@ -987,6 +989,11 @@ static int tg3_phy_reset(struct tg3 *tp) | |||
| 987 | if (err != 0) | 989 | if (err != 0) |
| 988 | return -EBUSY; | 990 | return -EBUSY; |
| 989 | 991 | ||
| 992 | if (netif_running(tp->dev) && netif_carrier_ok(tp->dev)) { | ||
| 993 | netif_carrier_off(tp->dev); | ||
| 994 | tg3_link_report(tp); | ||
| 995 | } | ||
| 996 | |||
| 990 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 || | 997 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 || |
| 991 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || | 998 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || |
| 992 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { | 999 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { |
| @@ -1023,6 +1030,12 @@ out: | |||
| 1023 | tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x14e2); | 1030 | tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x14e2); |
| 1024 | tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400); | 1031 | tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400); |
| 1025 | } | 1032 | } |
| 1033 | else if (tp->tg3_flags2 & TG3_FLG2_PHY_JITTER_BUG) { | ||
| 1034 | tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); | ||
| 1035 | tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a); | ||
| 1036 | tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b); | ||
| 1037 | tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400); | ||
| 1038 | } | ||
| 1026 | /* Set Extended packet length bit (bit 14) on all chips that */ | 1039 | /* Set Extended packet length bit (bit 14) on all chips that */ |
| 1027 | /* support jumbo frames */ | 1040 | /* support jumbo frames */ |
| 1028 | if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { | 1041 | if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { |
| @@ -3531,7 +3544,7 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id, | |||
| 3531 | return IRQ_RETVAL(0); | 3544 | return IRQ_RETVAL(0); |
| 3532 | } | 3545 | } |
| 3533 | 3546 | ||
| 3534 | static int tg3_init_hw(struct tg3 *); | 3547 | static int tg3_init_hw(struct tg3 *, int); |
| 3535 | static int tg3_halt(struct tg3 *, int, int); | 3548 | static int tg3_halt(struct tg3 *, int, int); |
| 3536 | 3549 | ||
| 3537 | #ifdef CONFIG_NET_POLL_CONTROLLER | 3550 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| @@ -3567,7 +3580,7 @@ static void tg3_reset_task(void *_data) | |||
| 3567 | tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER; | 3580 | tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER; |
| 3568 | 3581 | ||
| 3569 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 0); | 3582 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 0); |
| 3570 | tg3_init_hw(tp); | 3583 | tg3_init_hw(tp, 1); |
| 3571 | 3584 | ||
| 3572 | tg3_netif_start(tp); | 3585 | tg3_netif_start(tp); |
| 3573 | 3586 | ||
| @@ -4042,7 +4055,7 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu) | |||
| 4042 | 4055 | ||
| 4043 | tg3_set_mtu(dev, tp, new_mtu); | 4056 | tg3_set_mtu(dev, tp, new_mtu); |
| 4044 | 4057 | ||
| 4045 | tg3_init_hw(tp); | 4058 | tg3_init_hw(tp, 0); |
| 4046 | 4059 | ||
| 4047 | tg3_netif_start(tp); | 4060 | tg3_netif_start(tp); |
| 4048 | 4061 | ||
| @@ -5719,9 +5732,23 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p) | |||
| 5719 | if (!netif_running(dev)) | 5732 | if (!netif_running(dev)) |
| 5720 | return 0; | 5733 | return 0; |
| 5721 | 5734 | ||
| 5722 | spin_lock_bh(&tp->lock); | 5735 | if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { |
| 5723 | __tg3_set_mac_addr(tp); | 5736 | /* Reset chip so that ASF can re-init any MAC addresses it |
| 5724 | spin_unlock_bh(&tp->lock); | 5737 | * needs. |
| 5738 | */ | ||
| 5739 | tg3_netif_stop(tp); | ||
| 5740 | tg3_full_lock(tp, 1); | ||
| 5741 | |||
| 5742 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); | ||
| 5743 | tg3_init_hw(tp, 0); | ||
| 5744 | |||
| 5745 | tg3_netif_start(tp); | ||
| 5746 | tg3_full_unlock(tp); | ||
| 5747 | } else { | ||
| 5748 | spin_lock_bh(&tp->lock); | ||
| 5749 | __tg3_set_mac_addr(tp); | ||
| 5750 | spin_unlock_bh(&tp->lock); | ||
| 5751 | } | ||
| 5725 | 5752 | ||
| 5726 | return 0; | 5753 | return 0; |
| 5727 | } | 5754 | } |
| @@ -5771,7 +5798,7 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) | |||
| 5771 | } | 5798 | } |
| 5772 | 5799 | ||
| 5773 | /* tp->lock is held. */ | 5800 | /* tp->lock is held. */ |
| 5774 | static int tg3_reset_hw(struct tg3 *tp) | 5801 | static int tg3_reset_hw(struct tg3 *tp, int reset_phy) |
| 5775 | { | 5802 | { |
| 5776 | u32 val, rdmac_mode; | 5803 | u32 val, rdmac_mode; |
| 5777 | int i, err, limit; | 5804 | int i, err, limit; |
| @@ -5786,7 +5813,7 @@ static int tg3_reset_hw(struct tg3 *tp) | |||
| 5786 | tg3_abort_hw(tp, 1); | 5813 | tg3_abort_hw(tp, 1); |
| 5787 | } | 5814 | } |
| 5788 | 5815 | ||
| 5789 | if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) | 5816 | if ((tp->tg3_flags2 & TG3_FLG2_MII_SERDES) && reset_phy) |
| 5790 | tg3_phy_reset(tp); | 5817 | tg3_phy_reset(tp); |
| 5791 | 5818 | ||
| 5792 | err = tg3_chip_reset(tp); | 5819 | err = tg3_chip_reset(tp); |
| @@ -6327,7 +6354,7 @@ static int tg3_reset_hw(struct tg3 *tp) | |||
| 6327 | tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl); | 6354 | tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl); |
| 6328 | } | 6355 | } |
| 6329 | 6356 | ||
| 6330 | err = tg3_setup_phy(tp, 1); | 6357 | err = tg3_setup_phy(tp, reset_phy); |
| 6331 | if (err) | 6358 | if (err) |
| 6332 | return err; | 6359 | return err; |
| 6333 | 6360 | ||
| @@ -6400,7 +6427,7 @@ static int tg3_reset_hw(struct tg3 *tp) | |||
| 6400 | /* Called at device open time to get the chip ready for | 6427 | /* Called at device open time to get the chip ready for |
| 6401 | * packet processing. Invoked with tp->lock held. | 6428 | * packet processing. Invoked with tp->lock held. |
| 6402 | */ | 6429 | */ |
| 6403 | static int tg3_init_hw(struct tg3 *tp) | 6430 | static int tg3_init_hw(struct tg3 *tp, int reset_phy) |
| 6404 | { | 6431 | { |
| 6405 | int err; | 6432 | int err; |
| 6406 | 6433 | ||
| @@ -6413,7 +6440,7 @@ static int tg3_init_hw(struct tg3 *tp) | |||
| 6413 | 6440 | ||
| 6414 | tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0); | 6441 | tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0); |
| 6415 | 6442 | ||
| 6416 | err = tg3_reset_hw(tp); | 6443 | err = tg3_reset_hw(tp, reset_phy); |
| 6417 | 6444 | ||
| 6418 | out: | 6445 | out: |
| 6419 | return err; | 6446 | return err; |
| @@ -6683,7 +6710,7 @@ static int tg3_test_msi(struct tg3 *tp) | |||
| 6683 | tg3_full_lock(tp, 1); | 6710 | tg3_full_lock(tp, 1); |
| 6684 | 6711 | ||
| 6685 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); | 6712 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); |
| 6686 | err = tg3_init_hw(tp); | 6713 | err = tg3_init_hw(tp, 1); |
| 6687 | 6714 | ||
| 6688 | tg3_full_unlock(tp); | 6715 | tg3_full_unlock(tp); |
| 6689 | 6716 | ||
| @@ -6748,7 +6775,7 @@ static int tg3_open(struct net_device *dev) | |||
| 6748 | 6775 | ||
| 6749 | tg3_full_lock(tp, 0); | 6776 | tg3_full_lock(tp, 0); |
| 6750 | 6777 | ||
| 6751 | err = tg3_init_hw(tp); | 6778 | err = tg3_init_hw(tp, 1); |
| 6752 | if (err) { | 6779 | if (err) { |
| 6753 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); | 6780 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); |
| 6754 | tg3_free_rings(tp); | 6781 | tg3_free_rings(tp); |
| @@ -7839,7 +7866,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e | |||
| 7839 | 7866 | ||
| 7840 | if (netif_running(dev)) { | 7867 | if (netif_running(dev)) { |
| 7841 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); | 7868 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); |
| 7842 | tg3_init_hw(tp); | 7869 | tg3_init_hw(tp, 1); |
| 7843 | tg3_netif_start(tp); | 7870 | tg3_netif_start(tp); |
| 7844 | } | 7871 | } |
| 7845 | 7872 | ||
| @@ -7884,7 +7911,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam | |||
| 7884 | 7911 | ||
| 7885 | if (netif_running(dev)) { | 7912 | if (netif_running(dev)) { |
| 7886 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); | 7913 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); |
| 7887 | tg3_init_hw(tp); | 7914 | tg3_init_hw(tp, 1); |
| 7888 | tg3_netif_start(tp); | 7915 | tg3_netif_start(tp); |
| 7889 | } | 7916 | } |
| 7890 | 7917 | ||
| @@ -8522,7 +8549,7 @@ static int tg3_test_loopback(struct tg3 *tp) | |||
| 8522 | if (!netif_running(tp->dev)) | 8549 | if (!netif_running(tp->dev)) |
| 8523 | return TG3_LOOPBACK_FAILED; | 8550 | return TG3_LOOPBACK_FAILED; |
| 8524 | 8551 | ||
| 8525 | tg3_reset_hw(tp); | 8552 | tg3_reset_hw(tp, 1); |
| 8526 | 8553 | ||
| 8527 | if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK)) | 8554 | if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK)) |
| 8528 | err |= TG3_MAC_LOOPBACK_FAILED; | 8555 | err |= TG3_MAC_LOOPBACK_FAILED; |
| @@ -8596,7 +8623,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, | |||
| 8596 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); | 8623 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); |
| 8597 | if (netif_running(dev)) { | 8624 | if (netif_running(dev)) { |
| 8598 | tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; | 8625 | tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; |
| 8599 | tg3_init_hw(tp); | 8626 | tg3_init_hw(tp, 1); |
| 8600 | tg3_netif_start(tp); | 8627 | tg3_netif_start(tp); |
| 8601 | } | 8628 | } |
| 8602 | 8629 | ||
| @@ -9377,7 +9404,7 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, | |||
| 9377 | 9404 | ||
| 9378 | if ((page_off == 0) || (i == 0)) | 9405 | if ((page_off == 0) || (i == 0)) |
| 9379 | nvram_cmd |= NVRAM_CMD_FIRST; | 9406 | nvram_cmd |= NVRAM_CMD_FIRST; |
| 9380 | else if (page_off == (tp->nvram_pagesize - 4)) | 9407 | if (page_off == (tp->nvram_pagesize - 4)) |
| 9381 | nvram_cmd |= NVRAM_CMD_LAST; | 9408 | nvram_cmd |= NVRAM_CMD_LAST; |
| 9382 | 9409 | ||
| 9383 | if (i == (len - 4)) | 9410 | if (i == (len - 4)) |
| @@ -10353,10 +10380,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
| 10353 | if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) | 10380 | if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) |
| 10354 | tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG; | 10381 | tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG; |
| 10355 | 10382 | ||
| 10356 | if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && | 10383 | if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { |
| 10357 | (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755) && | 10384 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || |
| 10358 | (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787)) | 10385 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) |
| 10359 | tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG; | 10386 | tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG; |
| 10387 | else | ||
| 10388 | tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG; | ||
| 10389 | } | ||
| 10360 | 10390 | ||
| 10361 | tp->coalesce_mode = 0; | 10391 | tp->coalesce_mode = 0; |
| 10362 | if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_AX && | 10392 | if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_AX && |
| @@ -11569,7 +11599,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) | |||
| 11569 | tg3_full_lock(tp, 0); | 11599 | tg3_full_lock(tp, 0); |
| 11570 | 11600 | ||
| 11571 | tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; | 11601 | tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; |
| 11572 | tg3_init_hw(tp); | 11602 | tg3_init_hw(tp, 1); |
| 11573 | 11603 | ||
| 11574 | tp->timer.expires = jiffies + tp->timer_offset; | 11604 | tp->timer.expires = jiffies + tp->timer_offset; |
| 11575 | add_timer(&tp->timer); | 11605 | add_timer(&tp->timer); |
| @@ -11603,7 +11633,7 @@ static int tg3_resume(struct pci_dev *pdev) | |||
| 11603 | tg3_full_lock(tp, 0); | 11633 | tg3_full_lock(tp, 0); |
| 11604 | 11634 | ||
| 11605 | tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; | 11635 | tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; |
| 11606 | tg3_init_hw(tp); | 11636 | tg3_init_hw(tp, 1); |
| 11607 | 11637 | ||
| 11608 | tp->timer.expires = jiffies + tp->timer_offset; | 11638 | tp->timer.expires = jiffies + tp->timer_offset; |
| 11609 | add_timer(&tp->timer); | 11639 | add_timer(&tp->timer); |
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 8c8b987d1250..0e29b885d449 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h | |||
| @@ -2215,6 +2215,7 @@ struct tg3 { | |||
| 2215 | #define TG3_FLG2_HW_TSO_2 0x08000000 | 2215 | #define TG3_FLG2_HW_TSO_2 0x08000000 |
| 2216 | #define TG3_FLG2_HW_TSO (TG3_FLG2_HW_TSO_1 | TG3_FLG2_HW_TSO_2) | 2216 | #define TG3_FLG2_HW_TSO (TG3_FLG2_HW_TSO_1 | TG3_FLG2_HW_TSO_2) |
| 2217 | #define TG3_FLG2_1SHOT_MSI 0x10000000 | 2217 | #define TG3_FLG2_1SHOT_MSI 0x10000000 |
| 2218 | #define TG3_FLG2_PHY_JITTER_BUG 0x20000000 | ||
| 2218 | 2219 | ||
| 2219 | u32 split_mode_max_reqs; | 2220 | u32 split_mode_max_reqs; |
| 2220 | #define SPLIT_MODE_5704_MAX_REQ 3 | 2221 | #define SPLIT_MODE_5704_MAX_REQ 3 |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 2087a397ef16..9855c4c920b8 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
| @@ -793,8 +793,10 @@ static int msix_capability_init(struct pci_dev *dev, | |||
| 793 | if (!entry) | 793 | if (!entry) |
| 794 | break; | 794 | break; |
| 795 | vector = get_msi_vector(dev); | 795 | vector = get_msi_vector(dev); |
| 796 | if (vector < 0) | 796 | if (vector < 0) { |
| 797 | kmem_cache_free(msi_cachep, entry); | ||
| 797 | break; | 798 | break; |
| 799 | } | ||
| 798 | 800 | ||
| 799 | j = entries[i].entry; | 801 | j = entries[i].entry; |
| 800 | entries[i].vector = vector; | 802 | entries[i].vector = vector; |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index c42ae2cf8d64..19e2b174d33c 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
| @@ -642,13 +642,15 @@ static void quirk_via_irq(struct pci_dev *dev) | |||
| 642 | new_irq = dev->irq & 0xf; | 642 | new_irq = dev->irq & 0xf; |
| 643 | pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); | 643 | pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); |
| 644 | if (new_irq != irq) { | 644 | if (new_irq != irq) { |
| 645 | printk(KERN_INFO "PCI: Via IRQ fixup for %s, from %d to %d\n", | 645 | printk(KERN_INFO "PCI: VIA IRQ fixup for %s, from %d to %d\n", |
| 646 | pci_name(dev), irq, new_irq); | 646 | pci_name(dev), irq, new_irq); |
| 647 | udelay(15); /* unknown if delay really needed */ | 647 | udelay(15); /* unknown if delay really needed */ |
| 648 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); | 648 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); |
| 649 | } | 649 | } |
| 650 | } | 650 | } |
| 651 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq); | 651 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_irq); |
| 652 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_irq); | ||
| 653 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irq); | ||
| 652 | 654 | ||
| 653 | /* | 655 | /* |
| 654 | * VIA VT82C598 has its device ID settable and many BIOSes | 656 | * VIA VT82C598 has its device ID settable and many BIOSes |
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index bd0308e89815..a2f05f485156 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c | |||
| @@ -509,7 +509,8 @@ static irqreturn_t i365_count_irq(int irq, void *dev, struct pt_regs *regs) | |||
| 509 | static u_int __init test_irq(u_short sock, int irq) | 509 | static u_int __init test_irq(u_short sock, int irq) |
| 510 | { | 510 | { |
| 511 | debug(2, " testing ISA irq %d\n", irq); | 511 | debug(2, " testing ISA irq %d\n", irq); |
| 512 | if (request_irq(irq, i365_count_irq, 0, "scan", i365_count_irq) != 0) | 512 | if (request_irq(irq, i365_count_irq, SA_PROBEIRQ, "scan", |
| 513 | i365_count_irq) != 0) | ||
| 513 | return 1; | 514 | return 1; |
| 514 | irq_hits = 0; irq_sock = sock; | 515 | irq_hits = 0; irq_sock = sock; |
| 515 | msleep(10); | 516 | msleep(10); |
| @@ -561,7 +562,7 @@ static u_int __init isa_scan(u_short sock, u_int mask0) | |||
| 561 | } else { | 562 | } else { |
| 562 | /* Fallback: just find interrupts that aren't in use */ | 563 | /* Fallback: just find interrupts that aren't in use */ |
| 563 | for (i = 0; i < 16; i++) | 564 | for (i = 0; i < 16; i++) |
| 564 | if ((mask0 & (1 << i)) && (_check_irq(i, 0) == 0)) | 565 | if ((mask0 & (1 << i)) && (_check_irq(i, SA_PROBEIRQ) == 0)) |
| 565 | mask1 |= (1 << i); | 566 | mask1 |= (1 << i); |
| 566 | printk("default"); | 567 | printk("default"); |
| 567 | /* If scan failed, default to polled status */ | 568 | /* If scan failed, default to polled status */ |
| @@ -725,7 +726,7 @@ static void __init add_pcic(int ns, int type) | |||
| 725 | u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12)); | 726 | u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12)); |
| 726 | for (cs_irq = 15; cs_irq > 0; cs_irq--) | 727 | for (cs_irq = 15; cs_irq > 0; cs_irq--) |
| 727 | if ((cs_mask & (1 << cs_irq)) && | 728 | if ((cs_mask & (1 << cs_irq)) && |
| 728 | (_check_irq(cs_irq, 0) == 0)) | 729 | (_check_irq(cs_irq, SA_PROBEIRQ) == 0)) |
| 729 | break; | 730 | break; |
| 730 | if (cs_irq) { | 731 | if (cs_irq) { |
| 731 | grab_irq = 1; | 732 | grab_irq = 1; |
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index b1e3e6179e56..6c9ad92747fd 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c | |||
| @@ -58,7 +58,7 @@ rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
| 58 | unsigned long data; | 58 | unsigned long data; |
| 59 | ssize_t ret; | 59 | ssize_t ret; |
| 60 | 60 | ||
| 61 | if (count < sizeof(unsigned long)) | 61 | if (count != sizeof(unsigned int) && count < sizeof(unsigned long)) |
| 62 | return -EINVAL; | 62 | return -EINVAL; |
| 63 | 63 | ||
| 64 | add_wait_queue(&rtc->irq_queue, &wait); | 64 | add_wait_queue(&rtc->irq_queue, &wait); |
| @@ -90,11 +90,16 @@ rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
| 90 | if (ret == 0) { | 90 | if (ret == 0) { |
| 91 | /* Check for any data updates */ | 91 | /* Check for any data updates */ |
| 92 | if (rtc->ops->read_callback) | 92 | if (rtc->ops->read_callback) |
| 93 | data = rtc->ops->read_callback(rtc->class_dev.dev, data); | 93 | data = rtc->ops->read_callback(rtc->class_dev.dev, |
| 94 | 94 | data); | |
| 95 | ret = put_user(data, (unsigned long __user *)buf); | 95 | |
| 96 | if (ret == 0) | 96 | if (sizeof(int) != sizeof(long) && |
| 97 | ret = sizeof(unsigned long); | 97 | count == sizeof(unsigned int)) |
| 98 | ret = put_user(data, (unsigned int __user *)buf) ?: | ||
| 99 | sizeof(unsigned int); | ||
| 100 | else | ||
| 101 | ret = put_user(data, (unsigned long __user *)buf) ?: | ||
| 102 | sizeof(unsigned long); | ||
| 98 | } | 103 | } |
| 99 | return ret; | 104 | return ret; |
| 100 | } | 105 | } |
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index a3bfebcf31ef..cfb1fff3787c 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
| @@ -315,6 +315,11 @@ dasd_increase_state(struct dasd_device *device) | |||
| 315 | rc = dasd_state_basic_to_ready(device); | 315 | rc = dasd_state_basic_to_ready(device); |
| 316 | 316 | ||
| 317 | if (!rc && | 317 | if (!rc && |
| 318 | device->state == DASD_STATE_UNFMT && | ||
| 319 | device->target > DASD_STATE_UNFMT) | ||
| 320 | rc = -EPERM; | ||
| 321 | |||
| 322 | if (!rc && | ||
| 318 | device->state == DASD_STATE_READY && | 323 | device->state == DASD_STATE_READY && |
| 319 | device->target >= DASD_STATE_ONLINE) | 324 | device->target >= DASD_STATE_ONLINE) |
| 320 | rc = dasd_state_ready_to_online(device); | 325 | rc = dasd_state_ready_to_online(device); |
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index c1c6f1381150..216bc4fba199 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c | |||
| @@ -45,6 +45,7 @@ struct dasd_devmap { | |||
| 45 | unsigned int devindex; | 45 | unsigned int devindex; |
| 46 | unsigned short features; | 46 | unsigned short features; |
| 47 | struct dasd_device *device; | 47 | struct dasd_device *device; |
| 48 | struct dasd_uid uid; | ||
| 48 | }; | 49 | }; |
| 49 | 50 | ||
| 50 | /* | 51 | /* |
| @@ -716,6 +717,68 @@ dasd_discipline_show(struct device *dev, struct device_attribute *attr, char *bu | |||
| 716 | 717 | ||
| 717 | static DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL); | 718 | static DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL); |
| 718 | 719 | ||
| 720 | static ssize_t | ||
| 721 | dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 722 | { | ||
| 723 | struct dasd_devmap *devmap; | ||
| 724 | int alias; | ||
| 725 | |||
| 726 | devmap = dasd_find_busid(dev->bus_id); | ||
| 727 | spin_lock(&dasd_devmap_lock); | ||
| 728 | if (!IS_ERR(devmap)) | ||
| 729 | alias = devmap->uid.alias; | ||
| 730 | else | ||
| 731 | alias = 0; | ||
| 732 | spin_unlock(&dasd_devmap_lock); | ||
| 733 | |||
| 734 | return sprintf(buf, alias ? "1\n" : "0\n"); | ||
| 735 | } | ||
| 736 | |||
| 737 | static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL); | ||
| 738 | |||
| 739 | static ssize_t | ||
| 740 | dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 741 | { | ||
| 742 | struct dasd_devmap *devmap; | ||
| 743 | char *vendor; | ||
| 744 | |||
| 745 | devmap = dasd_find_busid(dev->bus_id); | ||
| 746 | spin_lock(&dasd_devmap_lock); | ||
| 747 | if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0) | ||
| 748 | vendor = devmap->uid.vendor; | ||
| 749 | else | ||
| 750 | vendor = ""; | ||
| 751 | spin_unlock(&dasd_devmap_lock); | ||
| 752 | |||
| 753 | return snprintf(buf, PAGE_SIZE, "%s\n", vendor); | ||
| 754 | } | ||
| 755 | |||
| 756 | static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL); | ||
| 757 | |||
| 758 | #define UID_STRLEN ( /* vendor */ 3 + 1 + /* serial */ 14 + 1 +\ | ||
| 759 | /* SSID */ 4 + 1 + /* unit addr */ 2 + 1) | ||
| 760 | |||
| 761 | static ssize_t | ||
| 762 | dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 763 | { | ||
| 764 | struct dasd_devmap *devmap; | ||
| 765 | char uid[UID_STRLEN]; | ||
| 766 | |||
| 767 | devmap = dasd_find_busid(dev->bus_id); | ||
| 768 | spin_lock(&dasd_devmap_lock); | ||
| 769 | if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0) | ||
| 770 | snprintf(uid, sizeof(uid), "%s.%s.%04x.%02x", | ||
| 771 | devmap->uid.vendor, devmap->uid.serial, | ||
| 772 | devmap->uid.ssid, devmap->uid.unit_addr); | ||
| 773 | else | ||
| 774 | uid[0] = 0; | ||
| 775 | spin_unlock(&dasd_devmap_lock); | ||
| 776 | |||
| 777 | return snprintf(buf, PAGE_SIZE, "%s\n", uid); | ||
| 778 | } | ||
| 779 | |||
| 780 | static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL); | ||
| 781 | |||
| 719 | /* | 782 | /* |
| 720 | * extended error-reporting | 783 | * extended error-reporting |
| 721 | */ | 784 | */ |
| @@ -759,6 +822,9 @@ static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store); | |||
| 759 | static struct attribute * dasd_attrs[] = { | 822 | static struct attribute * dasd_attrs[] = { |
| 760 | &dev_attr_readonly.attr, | 823 | &dev_attr_readonly.attr, |
| 761 | &dev_attr_discipline.attr, | 824 | &dev_attr_discipline.attr, |
| 825 | &dev_attr_alias.attr, | ||
| 826 | &dev_attr_vendor.attr, | ||
| 827 | &dev_attr_uid.attr, | ||
| 762 | &dev_attr_use_diag.attr, | 828 | &dev_attr_use_diag.attr, |
| 763 | &dev_attr_eer_enabled.attr, | 829 | &dev_attr_eer_enabled.attr, |
| 764 | NULL, | 830 | NULL, |
| @@ -768,6 +834,42 @@ static struct attribute_group dasd_attr_group = { | |||
| 768 | .attrs = dasd_attrs, | 834 | .attrs = dasd_attrs, |
| 769 | }; | 835 | }; |
| 770 | 836 | ||
| 837 | |||
| 838 | /* | ||
| 839 | * Return copy of the device unique identifier. | ||
| 840 | */ | ||
| 841 | int | ||
| 842 | dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid) | ||
| 843 | { | ||
| 844 | struct dasd_devmap *devmap; | ||
| 845 | |||
| 846 | devmap = dasd_find_busid(cdev->dev.bus_id); | ||
| 847 | if (IS_ERR(devmap)) | ||
| 848 | return PTR_ERR(devmap); | ||
| 849 | spin_lock(&dasd_devmap_lock); | ||
| 850 | *uid = devmap->uid; | ||
| 851 | spin_unlock(&dasd_devmap_lock); | ||
| 852 | return 0; | ||
| 853 | } | ||
| 854 | |||
| 855 | /* | ||
| 856 | * Register the given device unique identifier into devmap struct. | ||
| 857 | */ | ||
| 858 | int | ||
| 859 | dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid) | ||
| 860 | { | ||
| 861 | struct dasd_devmap *devmap; | ||
| 862 | |||
| 863 | devmap = dasd_find_busid(cdev->dev.bus_id); | ||
| 864 | if (IS_ERR(devmap)) | ||
| 865 | return PTR_ERR(devmap); | ||
| 866 | spin_lock(&dasd_devmap_lock); | ||
| 867 | devmap->uid = *uid; | ||
| 868 | spin_unlock(&dasd_devmap_lock); | ||
| 869 | return 0; | ||
| 870 | } | ||
| 871 | EXPORT_SYMBOL(dasd_set_uid); | ||
| 872 | |||
| 771 | /* | 873 | /* |
| 772 | * Return value of the specified feature. | 874 | * Return value of the specified feature. |
| 773 | */ | 875 | */ |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index ee09ef33d08d..7d5a6cee4bd8 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
| @@ -446,6 +446,39 @@ dasd_eckd_cdl_reclen(int recid) | |||
| 446 | return LABEL_SIZE; | 446 | return LABEL_SIZE; |
| 447 | } | 447 | } |
| 448 | 448 | ||
| 449 | /* | ||
| 450 | * Generate device unique id that specifies the physical device. | ||
| 451 | */ | ||
| 452 | static int | ||
| 453 | dasd_eckd_generate_uid(struct dasd_device *device, struct dasd_uid *uid) | ||
| 454 | { | ||
| 455 | struct dasd_eckd_private *private; | ||
| 456 | struct dasd_eckd_confdata *confdata; | ||
| 457 | |||
| 458 | private = (struct dasd_eckd_private *) device->private; | ||
| 459 | if (!private) | ||
| 460 | return -ENODEV; | ||
| 461 | confdata = &private->conf_data; | ||
| 462 | if (!confdata) | ||
| 463 | return -ENODEV; | ||
| 464 | |||
| 465 | memset(uid, 0, sizeof(struct dasd_uid)); | ||
| 466 | strncpy(uid->vendor, confdata->ned1.HDA_manufacturer, | ||
| 467 | sizeof(uid->vendor) - 1); | ||
| 468 | EBCASC(uid->vendor, sizeof(uid->vendor) - 1); | ||
| 469 | strncpy(uid->serial, confdata->ned1.HDA_location, | ||
| 470 | sizeof(uid->serial) - 1); | ||
| 471 | EBCASC(uid->serial, sizeof(uid->serial) - 1); | ||
| 472 | uid->ssid = confdata->neq.subsystemID; | ||
| 473 | if (confdata->ned2.sneq.flags == 0x40) { | ||
| 474 | uid->alias = 1; | ||
| 475 | uid->unit_addr = confdata->ned2.sneq.base_unit_addr; | ||
| 476 | } else | ||
| 477 | uid->unit_addr = confdata->ned1.unit_addr; | ||
| 478 | |||
| 479 | return 0; | ||
| 480 | } | ||
| 481 | |||
| 449 | static int | 482 | static int |
| 450 | dasd_eckd_read_conf(struct dasd_device *device) | 483 | dasd_eckd_read_conf(struct dasd_device *device) |
| 451 | { | 484 | { |
| @@ -507,11 +540,15 @@ dasd_eckd_read_conf(struct dasd_device *device) | |||
| 507 | return 0; | 540 | return 0; |
| 508 | } | 541 | } |
| 509 | 542 | ||
| 510 | 543 | /* | |
| 544 | * Check device characteristics. | ||
| 545 | * If the device is accessible using ECKD discipline, the device is enabled. | ||
| 546 | */ | ||
| 511 | static int | 547 | static int |
| 512 | dasd_eckd_check_characteristics(struct dasd_device *device) | 548 | dasd_eckd_check_characteristics(struct dasd_device *device) |
| 513 | { | 549 | { |
| 514 | struct dasd_eckd_private *private; | 550 | struct dasd_eckd_private *private; |
| 551 | struct dasd_uid uid; | ||
| 515 | void *rdc_data; | 552 | void *rdc_data; |
| 516 | int rc; | 553 | int rc; |
| 517 | 554 | ||
| @@ -536,6 +573,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
| 536 | 573 | ||
| 537 | /* Read Device Characteristics */ | 574 | /* Read Device Characteristics */ |
| 538 | rdc_data = (void *) &(private->rdc_data); | 575 | rdc_data = (void *) &(private->rdc_data); |
| 576 | memset(rdc_data, 0, sizeof(rdc_data)); | ||
| 539 | rc = read_dev_chars(device->cdev, &rdc_data, 64); | 577 | rc = read_dev_chars(device->cdev, &rdc_data, 64); |
| 540 | if (rc) { | 578 | if (rc) { |
| 541 | DEV_MESSAGE(KERN_WARNING, device, | 579 | DEV_MESSAGE(KERN_WARNING, device, |
| @@ -556,8 +594,17 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
| 556 | 594 | ||
| 557 | /* Read Configuration Data */ | 595 | /* Read Configuration Data */ |
| 558 | rc = dasd_eckd_read_conf (device); | 596 | rc = dasd_eckd_read_conf (device); |
| 559 | return rc; | 597 | if (rc) |
| 598 | return rc; | ||
| 599 | |||
| 600 | /* Generate device unique id and register in devmap */ | ||
| 601 | rc = dasd_eckd_generate_uid(device, &uid); | ||
| 602 | if (rc) | ||
| 603 | return rc; | ||
| 560 | 604 | ||
| 605 | rc = dasd_set_uid(device->cdev, &uid); | ||
| 606 | |||
| 607 | return rc; | ||
| 561 | } | 608 | } |
| 562 | 609 | ||
| 563 | static struct dasd_ccw_req * | 610 | static struct dasd_ccw_req * |
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index ad8524bb7bb3..d5734e976e1c 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h | |||
| @@ -228,26 +228,36 @@ struct dasd_eckd_confdata { | |||
| 228 | unsigned char HDA_manufacturer[3]; | 228 | unsigned char HDA_manufacturer[3]; |
| 229 | unsigned char HDA_location[2]; | 229 | unsigned char HDA_location[2]; |
| 230 | unsigned char HDA_seqno[12]; | 230 | unsigned char HDA_seqno[12]; |
| 231 | __u16 ID; | 231 | __u8 ID; |
| 232 | __u8 unit_addr; | ||
| 232 | } __attribute__ ((packed)) ned1; | 233 | } __attribute__ ((packed)) ned1; |
| 233 | struct { | 234 | union { |
| 234 | struct { | 235 | struct { |
| 235 | unsigned char identifier:2; | 236 | struct { |
| 236 | unsigned char token_id:1; | 237 | unsigned char identifier:2; |
| 237 | unsigned char sno_valid:1; | 238 | unsigned char token_id:1; |
| 238 | unsigned char subst_sno:1; | 239 | unsigned char sno_valid:1; |
| 239 | unsigned char recNED:1; | 240 | unsigned char subst_sno:1; |
| 240 | unsigned char emuNED:1; | 241 | unsigned char recNED:1; |
| 241 | unsigned char reserved:1; | 242 | unsigned char emuNED:1; |
| 242 | } __attribute__ ((packed)) flags; | 243 | unsigned char reserved:1; |
| 243 | __u8 descriptor; | 244 | } __attribute__ ((packed)) flags; |
| 244 | __u8 reserved[2]; | 245 | __u8 descriptor; |
| 245 | unsigned char dev_type[6]; | 246 | __u8 reserved[2]; |
| 246 | unsigned char dev_model[3]; | 247 | unsigned char dev_type[6]; |
| 247 | unsigned char DASD_manufacturer[3]; | 248 | unsigned char dev_model[3]; |
| 248 | unsigned char DASD_location[2]; | 249 | unsigned char DASD_manufacturer[3]; |
| 249 | unsigned char DASD_seqno[12]; | 250 | unsigned char DASD_location[2]; |
| 250 | __u16 ID; | 251 | unsigned char DASD_seqno[12]; |
| 252 | __u16 ID; | ||
| 253 | } __attribute__ ((packed)) ned; | ||
| 254 | struct { | ||
| 255 | unsigned char flags; /* byte 0 */ | ||
| 256 | unsigned char res2[7]; /* byte 1- 7 */ | ||
| 257 | unsigned char sua_flags; /* byte 8 */ | ||
| 258 | __u8 base_unit_addr; /* byte 9 */ | ||
| 259 | unsigned char res3[22]; /* byte 10-31 */ | ||
| 260 | } __attribute__ ((packed)) sneq; | ||
| 251 | } __attribute__ ((packed)) ned2; | 261 | } __attribute__ ((packed)) ned2; |
| 252 | struct { | 262 | struct { |
| 253 | struct { | 263 | struct { |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 4293ba827523..d4b13e300a76 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
| @@ -268,6 +268,16 @@ struct dasd_discipline { | |||
| 268 | 268 | ||
| 269 | extern struct dasd_discipline *dasd_diag_discipline_pointer; | 269 | extern struct dasd_discipline *dasd_diag_discipline_pointer; |
| 270 | 270 | ||
| 271 | /* | ||
| 272 | * Unique identifier for dasd device. | ||
| 273 | */ | ||
| 274 | struct dasd_uid { | ||
| 275 | __u8 alias; | ||
| 276 | char vendor[4]; | ||
| 277 | char serial[15]; | ||
| 278 | __u16 ssid; | ||
| 279 | __u8 unit_addr; | ||
| 280 | }; | ||
| 271 | 281 | ||
| 272 | /* | 282 | /* |
| 273 | * Notification numbers for extended error reporting notifications: | 283 | * Notification numbers for extended error reporting notifications: |
| @@ -516,6 +526,8 @@ void dasd_devmap_exit(void); | |||
| 516 | struct dasd_device *dasd_create_device(struct ccw_device *); | 526 | struct dasd_device *dasd_create_device(struct ccw_device *); |
| 517 | void dasd_delete_device(struct dasd_device *); | 527 | void dasd_delete_device(struct dasd_device *); |
| 518 | 528 | ||
| 529 | int dasd_get_uid(struct ccw_device *, struct dasd_uid *); | ||
| 530 | int dasd_set_uid(struct ccw_device *, struct dasd_uid *); | ||
| 519 | int dasd_get_feature(struct ccw_device *, int); | 531 | int dasd_get_feature(struct ccw_device *, int); |
| 520 | int dasd_set_feature(struct ccw_device *, int, int); | 532 | int dasd_set_feature(struct ccw_device *, int, int); |
| 521 | 533 | ||
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index c3915f60a3aa..d71ef1adea59 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c | |||
| @@ -230,14 +230,16 @@ tape_3590_read_attmsg(struct tape_device *device) | |||
| 230 | * These functions are used to schedule follow-up actions from within an | 230 | * These functions are used to schedule follow-up actions from within an |
| 231 | * interrupt context (like unsolicited interrupts). | 231 | * interrupt context (like unsolicited interrupts). |
| 232 | */ | 232 | */ |
| 233 | struct work_handler_data { | ||
| 234 | struct tape_device *device; | ||
| 235 | enum tape_op op; | ||
| 236 | struct work_struct work; | ||
| 237 | }; | ||
| 238 | |||
| 233 | static void | 239 | static void |
| 234 | tape_3590_work_handler(void *data) | 240 | tape_3590_work_handler(void *data) |
| 235 | { | 241 | { |
| 236 | struct { | 242 | struct work_handler_data *p = data; |
| 237 | struct tape_device *device; | ||
| 238 | enum tape_op op; | ||
| 239 | struct work_struct work; | ||
| 240 | } *p = data; | ||
| 241 | 243 | ||
| 242 | switch (p->op) { | 244 | switch (p->op) { |
| 243 | case TO_MSEN: | 245 | case TO_MSEN: |
| @@ -257,11 +259,7 @@ tape_3590_work_handler(void *data) | |||
| 257 | static int | 259 | static int |
| 258 | tape_3590_schedule_work(struct tape_device *device, enum tape_op op) | 260 | tape_3590_schedule_work(struct tape_device *device, enum tape_op op) |
| 259 | { | 261 | { |
| 260 | struct { | 262 | struct work_handler_data *p; |
| 261 | struct tape_device *device; | ||
| 262 | enum tape_op op; | ||
| 263 | struct work_struct work; | ||
| 264 | } *p; | ||
| 265 | 263 | ||
| 266 | if ((p = kzalloc(sizeof(*p), GFP_ATOMIC)) == NULL) | 264 | if ((p = kzalloc(sizeof(*p), GFP_ATOMIC)) == NULL) |
| 267 | return -ENOMEM; | 265 | return -ENOMEM; |
| @@ -316,7 +314,7 @@ tape_3590_bread(struct tape_device *device, struct request *req) | |||
| 316 | 314 | ||
| 317 | rq_for_each_bio(bio, req) { | 315 | rq_for_each_bio(bio, req) { |
| 318 | bio_for_each_segment(bv, bio, i) { | 316 | bio_for_each_segment(bv, bio, i) { |
| 319 | dst = kmap(bv->bv_page) + bv->bv_offset; | 317 | dst = page_address(bv->bv_page) + bv->bv_offset; |
| 320 | for (off = 0; off < bv->bv_len; | 318 | for (off = 0; off < bv->bv_len; |
| 321 | off += TAPEBLOCK_HSEC_SIZE) { | 319 | off += TAPEBLOCK_HSEC_SIZE) { |
| 322 | ccw->flags = CCW_FLAG_CC; | 320 | ccw->flags = CCW_FLAG_CC; |
| @@ -1168,6 +1166,7 @@ tape_3590_setup_device(struct tape_device *device) | |||
| 1168 | static void | 1166 | static void |
| 1169 | tape_3590_cleanup_device(struct tape_device *device) | 1167 | tape_3590_cleanup_device(struct tape_device *device) |
| 1170 | { | 1168 | { |
| 1169 | flush_scheduled_work(); | ||
| 1171 | tape_std_unassign(device); | 1170 | tape_std_unassign(device); |
| 1172 | 1171 | ||
| 1173 | kfree(device->discdata); | 1172 | kfree(device->discdata); |
| @@ -1234,6 +1233,7 @@ static struct tape_discipline tape_discipline_3590 = { | |||
| 1234 | 1233 | ||
| 1235 | static struct ccw_device_id tape_3590_ids[] = { | 1234 | static struct ccw_device_id tape_3590_ids[] = { |
| 1236 | {CCW_DEVICE_DEVTYPE(0x3590, 0, 0x3590, 0), .driver_info = tape_3590}, | 1235 | {CCW_DEVICE_DEVTYPE(0x3590, 0, 0x3590, 0), .driver_info = tape_3590}, |
| 1236 | {CCW_DEVICE_DEVTYPE(0x3592, 0, 0x3592, 0), .driver_info = tape_3592}, | ||
| 1237 | { /* end of list */ } | 1237 | { /* end of list */ } |
| 1238 | }; | 1238 | }; |
| 1239 | 1239 | ||
diff --git a/drivers/s390/char/tape_std.h b/drivers/s390/char/tape_std.h index 2d311798edf4..1fc952359341 100644 --- a/drivers/s390/char/tape_std.h +++ b/drivers/s390/char/tape_std.h | |||
| @@ -153,6 +153,7 @@ enum s390_tape_type { | |||
| 153 | tape_3480, | 153 | tape_3480, |
| 154 | tape_3490, | 154 | tape_3490, |
| 155 | tape_3590, | 155 | tape_3590, |
| 156 | tape_3592, | ||
| 156 | }; | 157 | }; |
| 157 | 158 | ||
| 158 | #endif // _TAPE_STD_H | 159 | #endif // _TAPE_STD_H |
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 6412b2c3edd3..72187e54dcac 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
| @@ -242,28 +242,10 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) | |||
| 242 | if (sch->vpm == mask) | 242 | if (sch->vpm == mask) |
| 243 | goto out_unreg; | 243 | goto out_unreg; |
| 244 | 244 | ||
| 245 | if ((sch->schib.scsw.actl & (SCSW_ACTL_CLEAR_PEND | | 245 | if ((sch->schib.scsw.actl & SCSW_ACTL_DEVACT) && |
| 246 | SCSW_ACTL_HALT_PEND | | 246 | (sch->schib.scsw.actl & SCSW_ACTL_SCHACT) && |
| 247 | SCSW_ACTL_START_PEND | | 247 | (sch->schib.pmcw.lpum == mask) && |
| 248 | SCSW_ACTL_RESUME_PEND)) && | 248 | (sch->vpm == 0)) { |
| 249 | (sch->schib.pmcw.lpum == mask)) { | ||
| 250 | int cc = cio_cancel(sch); | ||
| 251 | |||
| 252 | if (cc == -ENODEV) | ||
| 253 | goto out_unreg; | ||
| 254 | |||
| 255 | if (cc == -EINVAL) { | ||
| 256 | cc = cio_clear(sch); | ||
| 257 | if (cc == -ENODEV) | ||
| 258 | goto out_unreg; | ||
| 259 | /* Call handler. */ | ||
| 260 | if (sch->driver && sch->driver->termination) | ||
| 261 | sch->driver->termination(&sch->dev); | ||
| 262 | goto out_unlock; | ||
| 263 | } | ||
| 264 | } else if ((sch->schib.scsw.actl & SCSW_ACTL_DEVACT) && | ||
| 265 | (sch->schib.scsw.actl & SCSW_ACTL_SCHACT) && | ||
| 266 | (sch->schib.pmcw.lpum == mask)) { | ||
| 267 | int cc; | 249 | int cc; |
| 268 | 250 | ||
| 269 | cc = cio_clear(sch); | 251 | cc = cio_clear(sch); |
| @@ -653,13 +635,13 @@ __chp_add(struct subchannel_id schid, void *data) | |||
| 653 | if (sch->schib.pmcw.chpid[i] == chp->id) { | 635 | if (sch->schib.pmcw.chpid[i] == chp->id) { |
| 654 | if (stsch(sch->schid, &sch->schib) != 0) { | 636 | if (stsch(sch->schid, &sch->schib) != 0) { |
| 655 | /* Endgame. */ | 637 | /* Endgame. */ |
| 656 | spin_unlock(&sch->lock); | 638 | spin_unlock_irq(&sch->lock); |
| 657 | return -ENXIO; | 639 | return -ENXIO; |
| 658 | } | 640 | } |
| 659 | break; | 641 | break; |
| 660 | } | 642 | } |
| 661 | if (i==8) { | 643 | if (i==8) { |
| 662 | spin_unlock(&sch->lock); | 644 | spin_unlock_irq(&sch->lock); |
| 663 | return 0; | 645 | return 0; |
| 664 | } | 646 | } |
| 665 | sch->lpm = ((sch->schib.pmcw.pim & | 647 | sch->lpm = ((sch->schib.pmcw.pim & |
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 814f9258ce00..96f519281d92 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/kernel.h> | 38 | #include <linux/kernel.h> |
| 39 | #include <linux/proc_fs.h> | 39 | #include <linux/proc_fs.h> |
| 40 | #include <linux/timer.h> | 40 | #include <linux/timer.h> |
| 41 | #include <linux/mempool.h> | ||
| 41 | 42 | ||
| 42 | #include <asm/ccwdev.h> | 43 | #include <asm/ccwdev.h> |
| 43 | #include <asm/io.h> | 44 | #include <asm/io.h> |
| @@ -80,6 +81,8 @@ static int indicator_used[INDICATORS_PER_CACHELINE]; | |||
| 80 | static __u32 * volatile indicators; | 81 | static __u32 * volatile indicators; |
| 81 | static __u32 volatile spare_indicator; | 82 | static __u32 volatile spare_indicator; |
| 82 | static atomic_t spare_indicator_usecount; | 83 | static atomic_t spare_indicator_usecount; |
| 84 | #define QDIO_MEMPOOL_SCSSC_ELEMENTS 2 | ||
| 85 | static mempool_t *qdio_mempool_scssc; | ||
| 83 | 86 | ||
| 84 | static debug_info_t *qdio_dbf_setup; | 87 | static debug_info_t *qdio_dbf_setup; |
| 85 | static debug_info_t *qdio_dbf_sbal; | 88 | static debug_info_t *qdio_dbf_sbal; |
| @@ -1637,7 +1640,7 @@ next: | |||
| 1637 | 1640 | ||
| 1638 | } | 1641 | } |
| 1639 | kfree(irq_ptr->qdr); | 1642 | kfree(irq_ptr->qdr); |
| 1640 | kfree(irq_ptr); | 1643 | free_page((unsigned long) irq_ptr); |
| 1641 | } | 1644 | } |
| 1642 | 1645 | ||
| 1643 | static void | 1646 | static void |
| @@ -2304,7 +2307,7 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr) | |||
| 2304 | 2307 | ||
| 2305 | QDIO_DBF_TEXT0(0,setup,"getssqd"); | 2308 | QDIO_DBF_TEXT0(0,setup,"getssqd"); |
| 2306 | qdioac = 0; | 2309 | qdioac = 0; |
| 2307 | ssqd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); | 2310 | ssqd_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC); |
| 2308 | if (!ssqd_area) { | 2311 | if (!ssqd_area) { |
| 2309 | QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \ | 2312 | QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \ |
| 2310 | "SIGAs for sch x%x.\n", irq_ptr->schid.sch_no); | 2313 | "SIGAs for sch x%x.\n", irq_ptr->schid.sch_no); |
| @@ -2364,7 +2367,7 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr) | |||
| 2364 | out: | 2367 | out: |
| 2365 | qdio_check_subchannel_qebsm(irq_ptr, qdioac, | 2368 | qdio_check_subchannel_qebsm(irq_ptr, qdioac, |
| 2366 | ssqd_area->sch_token); | 2369 | ssqd_area->sch_token); |
| 2367 | free_page ((unsigned long) ssqd_area); | 2370 | mempool_free(ssqd_area, qdio_mempool_scssc); |
| 2368 | irq_ptr->qdioac = qdioac; | 2371 | irq_ptr->qdioac = qdioac; |
| 2369 | } | 2372 | } |
| 2370 | 2373 | ||
| @@ -2458,7 +2461,7 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero) | |||
| 2458 | virt_to_phys((volatile void *)irq_ptr->dev_st_chg_ind); | 2461 | virt_to_phys((volatile void *)irq_ptr->dev_st_chg_ind); |
| 2459 | } | 2462 | } |
| 2460 | 2463 | ||
| 2461 | scssc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); | 2464 | scssc_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC); |
| 2462 | if (!scssc_area) { | 2465 | if (!scssc_area) { |
| 2463 | QDIO_PRINT_WARN("No memory for setting indicators on " \ | 2466 | QDIO_PRINT_WARN("No memory for setting indicators on " \ |
| 2464 | "subchannel 0.%x.%x.\n", | 2467 | "subchannel 0.%x.%x.\n", |
| @@ -2514,7 +2517,7 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero) | |||
| 2514 | QDIO_DBF_HEX2(0,setup,&real_addr_dev_st_chg_ind,sizeof(unsigned long)); | 2517 | QDIO_DBF_HEX2(0,setup,&real_addr_dev_st_chg_ind,sizeof(unsigned long)); |
| 2515 | result = 0; | 2518 | result = 0; |
| 2516 | out: | 2519 | out: |
| 2517 | free_page ((unsigned long) scssc_area); | 2520 | mempool_free(scssc_area, qdio_mempool_scssc); |
| 2518 | return result; | 2521 | return result; |
| 2519 | 2522 | ||
| 2520 | } | 2523 | } |
| @@ -2543,7 +2546,7 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target) | |||
| 2543 | if (!irq_ptr->is_thinint_irq) | 2546 | if (!irq_ptr->is_thinint_irq) |
| 2544 | return -ENODEV; | 2547 | return -ENODEV; |
| 2545 | 2548 | ||
| 2546 | scsscf_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); | 2549 | scsscf_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC); |
| 2547 | if (!scsscf_area) { | 2550 | if (!scsscf_area) { |
| 2548 | QDIO_PRINT_WARN("No memory for setting delay target on " \ | 2551 | QDIO_PRINT_WARN("No memory for setting delay target on " \ |
| 2549 | "subchannel 0.%x.%x.\n", | 2552 | "subchannel 0.%x.%x.\n", |
| @@ -2581,7 +2584,7 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target) | |||
| 2581 | QDIO_DBF_HEX2(0,trace,&delay_target,sizeof(unsigned long)); | 2584 | QDIO_DBF_HEX2(0,trace,&delay_target,sizeof(unsigned long)); |
| 2582 | result = 0; /* not critical */ | 2585 | result = 0; /* not critical */ |
| 2583 | out: | 2586 | out: |
| 2584 | free_page ((unsigned long) scsscf_area); | 2587 | mempool_free(scsscf_area, qdio_mempool_scssc); |
| 2585 | return result; | 2588 | return result; |
| 2586 | } | 2589 | } |
| 2587 | 2590 | ||
| @@ -2980,7 +2983,7 @@ qdio_allocate(struct qdio_initialize *init_data) | |||
| 2980 | qdio_allocate_do_dbf(init_data); | 2983 | qdio_allocate_do_dbf(init_data); |
| 2981 | 2984 | ||
| 2982 | /* create irq */ | 2985 | /* create irq */ |
| 2983 | irq_ptr = kzalloc(sizeof(struct qdio_irq), GFP_KERNEL | GFP_DMA); | 2986 | irq_ptr = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); |
| 2984 | 2987 | ||
| 2985 | QDIO_DBF_TEXT0(0,setup,"irq_ptr:"); | 2988 | QDIO_DBF_TEXT0(0,setup,"irq_ptr:"); |
| 2986 | QDIO_DBF_HEX0(0,setup,&irq_ptr,sizeof(void*)); | 2989 | QDIO_DBF_HEX0(0,setup,&irq_ptr,sizeof(void*)); |
| @@ -2995,7 +2998,7 @@ qdio_allocate(struct qdio_initialize *init_data) | |||
| 2995 | /* QDR must be in DMA area since CCW data address is only 32 bit */ | 2998 | /* QDR must be in DMA area since CCW data address is only 32 bit */ |
| 2996 | irq_ptr->qdr=kmalloc(sizeof(struct qdr), GFP_KERNEL | GFP_DMA); | 2999 | irq_ptr->qdr=kmalloc(sizeof(struct qdr), GFP_KERNEL | GFP_DMA); |
| 2997 | if (!(irq_ptr->qdr)) { | 3000 | if (!(irq_ptr->qdr)) { |
| 2998 | kfree(irq_ptr); | 3001 | free_page((unsigned long) irq_ptr); |
| 2999 | QDIO_PRINT_ERR("kmalloc of irq_ptr->qdr failed!\n"); | 3002 | QDIO_PRINT_ERR("kmalloc of irq_ptr->qdr failed!\n"); |
| 3000 | return -ENOMEM; | 3003 | return -ENOMEM; |
| 3001 | } | 3004 | } |
| @@ -3780,6 +3783,16 @@ oom: | |||
| 3780 | return -ENOMEM; | 3783 | return -ENOMEM; |
| 3781 | } | 3784 | } |
| 3782 | 3785 | ||
| 3786 | static void *qdio_mempool_alloc(gfp_t gfp_mask, void *size) | ||
| 3787 | { | ||
| 3788 | return (void *) get_zeroed_page(gfp_mask|GFP_DMA); | ||
| 3789 | } | ||
| 3790 | |||
| 3791 | static void qdio_mempool_free(void *element, void *size) | ||
| 3792 | { | ||
| 3793 | free_page((unsigned long) element); | ||
| 3794 | } | ||
| 3795 | |||
| 3783 | static int __init | 3796 | static int __init |
| 3784 | init_QDIO(void) | 3797 | init_QDIO(void) |
| 3785 | { | 3798 | { |
| @@ -3809,6 +3822,10 @@ init_QDIO(void) | |||
| 3809 | 3822 | ||
| 3810 | qdio_add_procfs_entry(); | 3823 | qdio_add_procfs_entry(); |
| 3811 | 3824 | ||
| 3825 | qdio_mempool_scssc = mempool_create(QDIO_MEMPOOL_SCSSC_ELEMENTS, | ||
| 3826 | qdio_mempool_alloc, | ||
| 3827 | qdio_mempool_free, NULL); | ||
| 3828 | |||
| 3812 | if (tiqdio_check_chsc_availability()) | 3829 | if (tiqdio_check_chsc_availability()) |
| 3813 | QDIO_PRINT_ERR("Not all CHSCs supported. Continuing.\n"); | 3830 | QDIO_PRINT_ERR("Not all CHSCs supported. Continuing.\n"); |
| 3814 | 3831 | ||
| @@ -3824,6 +3841,7 @@ cleanup_QDIO(void) | |||
| 3824 | qdio_remove_procfs_entry(); | 3841 | qdio_remove_procfs_entry(); |
| 3825 | qdio_release_qdio_memory(); | 3842 | qdio_release_qdio_memory(); |
| 3826 | qdio_unregister_dbf_views(); | 3843 | qdio_unregister_dbf_views(); |
| 3844 | mempool_destroy(qdio_mempool_scssc); | ||
| 3827 | 3845 | ||
| 3828 | printk("qdio: %s: module removed\n",version); | 3846 | printk("qdio: %s: module removed\n",version); |
| 3829 | } | 3847 | } |
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index b3c6e7907790..cb14642d97aa 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c | |||
| @@ -8014,7 +8014,6 @@ static int (*qeth_old_arp_constructor) (struct neighbour *); | |||
| 8014 | 8014 | ||
| 8015 | static struct neigh_ops arp_direct_ops_template = { | 8015 | static struct neigh_ops arp_direct_ops_template = { |
| 8016 | .family = AF_INET, | 8016 | .family = AF_INET, |
| 8017 | .destructor = NULL, | ||
| 8018 | .solicit = NULL, | 8017 | .solicit = NULL, |
| 8019 | .error_report = NULL, | 8018 | .error_report = NULL, |
| 8020 | .output = dev_queue_xmit, | 8019 | .output = dev_queue_xmit, |
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c index 3bf466603512..f99e55308b32 100644 --- a/drivers/s390/s390mach.c +++ b/drivers/s390/s390mach.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
| 14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
| 15 | #include <linux/workqueue.h> | 15 | #include <linux/workqueue.h> |
| 16 | #include <linux/time.h> | ||
| 16 | 17 | ||
| 17 | #include <asm/lowcore.h> | 18 | #include <asm/lowcore.h> |
| 18 | 19 | ||
| @@ -362,12 +363,19 @@ s390_revalidate_registers(struct mci *mci) | |||
| 362 | return kill_task; | 363 | return kill_task; |
| 363 | } | 364 | } |
| 364 | 365 | ||
| 366 | #define MAX_IPD_COUNT 29 | ||
| 367 | #define MAX_IPD_TIME (5 * 60 * USEC_PER_SEC) /* 5 minutes */ | ||
| 368 | |||
| 365 | /* | 369 | /* |
| 366 | * machine check handler. | 370 | * machine check handler. |
| 367 | */ | 371 | */ |
| 368 | void | 372 | void |
| 369 | s390_do_machine_check(struct pt_regs *regs) | 373 | s390_do_machine_check(struct pt_regs *regs) |
| 370 | { | 374 | { |
| 375 | static DEFINE_SPINLOCK(ipd_lock); | ||
| 376 | static unsigned long long last_ipd; | ||
| 377 | static int ipd_count; | ||
| 378 | unsigned long long tmp; | ||
| 371 | struct mci *mci; | 379 | struct mci *mci; |
| 372 | struct mcck_struct *mcck; | 380 | struct mcck_struct *mcck; |
| 373 | int umode; | 381 | int umode; |
| @@ -404,11 +412,27 @@ s390_do_machine_check(struct pt_regs *regs) | |||
| 404 | s390_handle_damage("processing backup machine " | 412 | s390_handle_damage("processing backup machine " |
| 405 | "check with damage."); | 413 | "check with damage."); |
| 406 | } | 414 | } |
| 407 | if (!umode) | 415 | |
| 408 | s390_handle_damage("processing backup machine " | 416 | /* |
| 409 | "check in kernel mode."); | 417 | * Nullifying exigent condition, therefore we might |
| 410 | mcck->kill_task = 1; | 418 | * retry this instruction. |
| 411 | mcck->mcck_code = *(unsigned long long *) mci; | 419 | */ |
| 420 | |||
| 421 | spin_lock(&ipd_lock); | ||
| 422 | |||
| 423 | tmp = get_clock(); | ||
| 424 | |||
| 425 | if (((tmp - last_ipd) >> 12) < MAX_IPD_TIME) | ||
| 426 | ipd_count++; | ||
| 427 | else | ||
| 428 | ipd_count = 1; | ||
| 429 | |||
| 430 | last_ipd = tmp; | ||
| 431 | |||
| 432 | if (ipd_count == MAX_IPD_COUNT) | ||
| 433 | s390_handle_damage("too many ipd retries."); | ||
| 434 | |||
| 435 | spin_unlock(&ipd_lock); | ||
| 412 | } | 436 | } |
| 413 | else { | 437 | else { |
| 414 | /* Processing damage -> stopping machine */ | 438 | /* Processing damage -> stopping machine */ |
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 3e7302692dbe..a480a3742d47 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
| @@ -446,7 +446,9 @@ config SCSI_DPT_I2O | |||
| 446 | 446 | ||
| 447 | config SCSI_ADVANSYS | 447 | config SCSI_ADVANSYS |
| 448 | tristate "AdvanSys SCSI support" | 448 | tristate "AdvanSys SCSI support" |
| 449 | depends on (ISA || EISA || PCI) && SCSI && BROKEN | 449 | depends on SCSI |
| 450 | depends on ISA || EISA || PCI | ||
| 451 | depends on BROKEN || X86_32 | ||
| 450 | help | 452 | help |
| 451 | This is a driver for all SCSI host adapters manufactured by | 453 | This is a driver for all SCSI host adapters manufactured by |
| 452 | AdvanSys. It is documented in the kernel source in | 454 | AdvanSys. It is documented in the kernel source in |
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 28b93057b607..2a419634b256 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c | |||
| @@ -2051,7 +2051,7 @@ STATIC ASC_DCNT AscGetMaxDmaCount(ushort); | |||
| 2051 | #define ADV_VADDR_TO_U32 virt_to_bus | 2051 | #define ADV_VADDR_TO_U32 virt_to_bus |
| 2052 | #define ADV_U32_TO_VADDR bus_to_virt | 2052 | #define ADV_U32_TO_VADDR bus_to_virt |
| 2053 | 2053 | ||
| 2054 | #define AdvPortAddr ulong /* Virtual memory address size */ | 2054 | #define AdvPortAddr void __iomem * /* Virtual memory address size */ |
| 2055 | 2055 | ||
| 2056 | /* | 2056 | /* |
| 2057 | * Define Adv Library required memory access macros. | 2057 | * Define Adv Library required memory access macros. |
diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h index 73c8a088c160..aa5eb7ddeda9 100644 --- a/drivers/serial/cpm_uart/cpm_uart.h +++ b/drivers/serial/cpm_uart/cpm_uart.h | |||
| @@ -10,6 +10,8 @@ | |||
| 10 | #define CPM_UART_H | 10 | #define CPM_UART_H |
| 11 | 11 | ||
| 12 | #include <linux/config.h> | 12 | #include <linux/config.h> |
| 13 | #include <linux/platform_device.h> | ||
| 14 | #include <linux/fs_uart_pd.h> | ||
| 13 | 15 | ||
| 14 | #if defined(CONFIG_CPM2) | 16 | #if defined(CONFIG_CPM2) |
| 15 | #include "cpm_uart_cpm2.h" | 17 | #include "cpm_uart_cpm2.h" |
| @@ -26,14 +28,14 @@ | |||
| 26 | #define FLAG_SMC 0x00000002 | 28 | #define FLAG_SMC 0x00000002 |
| 27 | #define FLAG_CONSOLE 0x00000001 | 29 | #define FLAG_CONSOLE 0x00000001 |
| 28 | 30 | ||
| 29 | #define UART_SMC1 0 | 31 | #define UART_SMC1 fsid_smc1_uart |
| 30 | #define UART_SMC2 1 | 32 | #define UART_SMC2 fsid_smc2_uart |
| 31 | #define UART_SCC1 2 | 33 | #define UART_SCC1 fsid_scc1_uart |
| 32 | #define UART_SCC2 3 | 34 | #define UART_SCC2 fsid_scc2_uart |
| 33 | #define UART_SCC3 4 | 35 | #define UART_SCC3 fsid_scc3_uart |
| 34 | #define UART_SCC4 5 | 36 | #define UART_SCC4 fsid_scc4_uart |
| 35 | 37 | ||
| 36 | #define UART_NR 6 | 38 | #define UART_NR fs_uart_nr |
| 37 | 39 | ||
| 38 | #define RX_NUM_FIFO 4 | 40 | #define RX_NUM_FIFO 4 |
| 39 | #define RX_BUF_SIZE 32 | 41 | #define RX_BUF_SIZE 32 |
| @@ -64,6 +66,7 @@ struct uart_cpm_port { | |||
| 64 | uint dp_addr; | 66 | uint dp_addr; |
| 65 | void *mem_addr; | 67 | void *mem_addr; |
| 66 | dma_addr_t dma_addr; | 68 | dma_addr_t dma_addr; |
| 69 | u32 mem_size; | ||
| 67 | /* helpers */ | 70 | /* helpers */ |
| 68 | int baud; | 71 | int baud; |
| 69 | int bits; | 72 | int bits; |
| @@ -90,4 +93,36 @@ void scc2_lineif(struct uart_cpm_port *pinfo); | |||
| 90 | void scc3_lineif(struct uart_cpm_port *pinfo); | 93 | void scc3_lineif(struct uart_cpm_port *pinfo); |
| 91 | void scc4_lineif(struct uart_cpm_port *pinfo); | 94 | void scc4_lineif(struct uart_cpm_port *pinfo); |
| 92 | 95 | ||
| 96 | /* | ||
| 97 | virtual to phys transtalion | ||
| 98 | */ | ||
| 99 | static inline unsigned long cpu2cpm_addr(void* addr, struct uart_cpm_port *pinfo) | ||
| 100 | { | ||
| 101 | int offset; | ||
| 102 | u32 val = (u32)addr; | ||
| 103 | /* sane check */ | ||
| 104 | if ((val >= (u32)pinfo->mem_addr) && | ||
| 105 | (val<((u32)pinfo->mem_addr + pinfo->mem_size))) { | ||
| 106 | offset = val - (u32)pinfo->mem_addr; | ||
| 107 | return pinfo->dma_addr+offset; | ||
| 108 | } | ||
| 109 | printk("%s(): address %x to translate out of range!\n", __FUNCTION__, val); | ||
| 110 | return 0; | ||
| 111 | } | ||
| 112 | |||
| 113 | static inline void *cpm2cpu_addr(unsigned long addr, struct uart_cpm_port *pinfo) | ||
| 114 | { | ||
| 115 | int offset; | ||
| 116 | u32 val = addr; | ||
| 117 | /* sane check */ | ||
| 118 | if ((val >= pinfo->dma_addr) && | ||
| 119 | (val<(pinfo->dma_addr + pinfo->mem_size))) { | ||
| 120 | offset = val - (u32)pinfo->dma_addr; | ||
| 121 | return (void*)(pinfo->mem_addr+offset); | ||
| 122 | } | ||
| 123 | printk("%s(): address %x to translate out of range!\n", __FUNCTION__, val); | ||
| 124 | return 0; | ||
| 125 | } | ||
| 126 | |||
| 127 | |||
| 93 | #endif /* CPM_UART_H */ | 128 | #endif /* CPM_UART_H */ |
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index b7bf4c698a47..ced193bf9e1e 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #include <linux/device.h> | 41 | #include <linux/device.h> |
| 42 | #include <linux/bootmem.h> | 42 | #include <linux/bootmem.h> |
| 43 | #include <linux/dma-mapping.h> | 43 | #include <linux/dma-mapping.h> |
| 44 | #include <linux/fs_uart_pd.h> | ||
| 44 | 45 | ||
| 45 | #include <asm/io.h> | 46 | #include <asm/io.h> |
| 46 | #include <asm/irq.h> | 47 | #include <asm/irq.h> |
| @@ -60,7 +61,7 @@ | |||
| 60 | /* Track which ports are configured as uarts */ | 61 | /* Track which ports are configured as uarts */ |
| 61 | int cpm_uart_port_map[UART_NR]; | 62 | int cpm_uart_port_map[UART_NR]; |
| 62 | /* How many ports did we config as uarts */ | 63 | /* How many ports did we config as uarts */ |
| 63 | int cpm_uart_nr; | 64 | int cpm_uart_nr = 0; |
| 64 | 65 | ||
| 65 | /**************************************************************/ | 66 | /**************************************************************/ |
| 66 | 67 | ||
| @@ -71,18 +72,36 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo); | |||
| 71 | 72 | ||
| 72 | /**************************************************************/ | 73 | /**************************************************************/ |
| 73 | 74 | ||
| 74 | static inline unsigned long cpu2cpm_addr(void *addr) | 75 | |
| 76 | /* Place-holder for board-specific stuff */ | ||
| 77 | struct platform_device* __attribute__ ((weak)) __init | ||
| 78 | early_uart_get_pdev(int index) | ||
| 75 | { | 79 | { |
| 76 | if ((unsigned long)addr >= CPM_ADDR) | 80 | return NULL; |
| 77 | return (unsigned long)addr; | ||
| 78 | return virt_to_bus(addr); | ||
| 79 | } | 81 | } |
| 80 | 82 | ||
| 81 | static inline void *cpm2cpu_addr(unsigned long addr) | 83 | |
| 84 | void cpm_uart_count(void) | ||
| 82 | { | 85 | { |
| 83 | if (addr >= CPM_ADDR) | 86 | cpm_uart_nr = 0; |
| 84 | return (void *)addr; | 87 | #ifdef CONFIG_SERIAL_CPM_SMC1 |
| 85 | return bus_to_virt(addr); | 88 | cpm_uart_port_map[cpm_uart_nr++] = UART_SMC1; |
| 89 | #endif | ||
| 90 | #ifdef CONFIG_SERIAL_CPM_SMC2 | ||
| 91 | cpm_uart_port_map[cpm_uart_nr++] = UART_SMC2; | ||
| 92 | #endif | ||
| 93 | #ifdef CONFIG_SERIAL_CPM_SCC1 | ||
| 94 | cpm_uart_port_map[cpm_uart_nr++] = UART_SCC1; | ||
| 95 | #endif | ||
| 96 | #ifdef CONFIG_SERIAL_CPM_SCC2 | ||
| 97 | cpm_uart_port_map[cpm_uart_nr++] = UART_SCC2; | ||
| 98 | #endif | ||
| 99 | #ifdef CONFIG_SERIAL_CPM_SCC3 | ||
| 100 | cpm_uart_port_map[cpm_uart_nr++] = UART_SCC3; | ||
| 101 | #endif | ||
| 102 | #ifdef CONFIG_SERIAL_CPM_SCC4 | ||
| 103 | cpm_uart_port_map[cpm_uart_nr++] = UART_SCC4; | ||
| 104 | #endif | ||
| 86 | } | 105 | } |
| 87 | 106 | ||
| 88 | /* | 107 | /* |
| @@ -258,7 +277,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) | |||
| 258 | } | 277 | } |
| 259 | 278 | ||
| 260 | /* get pointer */ | 279 | /* get pointer */ |
| 261 | cp = cpm2cpu_addr(bdp->cbd_bufaddr); | 280 | cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); |
| 262 | 281 | ||
| 263 | /* loop through the buffer */ | 282 | /* loop through the buffer */ |
| 264 | while (i-- > 0) { | 283 | while (i-- > 0) { |
| @@ -601,7 +620,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) | |||
| 601 | /* Pick next descriptor and fill from buffer */ | 620 | /* Pick next descriptor and fill from buffer */ |
| 602 | bdp = pinfo->tx_cur; | 621 | bdp = pinfo->tx_cur; |
| 603 | 622 | ||
| 604 | p = cpm2cpu_addr(bdp->cbd_bufaddr); | 623 | p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); |
| 605 | 624 | ||
| 606 | *p++ = port->x_char; | 625 | *p++ = port->x_char; |
| 607 | bdp->cbd_datlen = 1; | 626 | bdp->cbd_datlen = 1; |
| @@ -628,7 +647,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) | |||
| 628 | 647 | ||
| 629 | while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) { | 648 | while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) { |
| 630 | count = 0; | 649 | count = 0; |
| 631 | p = cpm2cpu_addr(bdp->cbd_bufaddr); | 650 | p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); |
| 632 | while (count < pinfo->tx_fifosize) { | 651 | while (count < pinfo->tx_fifosize) { |
| 633 | *p++ = xmit->buf[xmit->tail]; | 652 | *p++ = xmit->buf[xmit->tail]; |
| 634 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 653 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
| @@ -677,12 +696,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo) | |||
| 677 | mem_addr = pinfo->mem_addr; | 696 | mem_addr = pinfo->mem_addr; |
| 678 | bdp = pinfo->rx_cur = pinfo->rx_bd_base; | 697 | bdp = pinfo->rx_cur = pinfo->rx_bd_base; |
| 679 | for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) { | 698 | for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) { |
| 680 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); | 699 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo); |
| 681 | bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT; | 700 | bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT; |
| 682 | mem_addr += pinfo->rx_fifosize; | 701 | mem_addr += pinfo->rx_fifosize; |
| 683 | } | 702 | } |
| 684 | 703 | ||
| 685 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); | 704 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo); |
| 686 | bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; | 705 | bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; |
| 687 | 706 | ||
| 688 | /* Set the physical address of the host memory | 707 | /* Set the physical address of the host memory |
| @@ -692,12 +711,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo) | |||
| 692 | mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize); | 711 | mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize); |
| 693 | bdp = pinfo->tx_cur = pinfo->tx_bd_base; | 712 | bdp = pinfo->tx_cur = pinfo->tx_bd_base; |
| 694 | for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) { | 713 | for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) { |
| 695 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); | 714 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo); |
| 696 | bdp->cbd_sc = BD_SC_INTRPT; | 715 | bdp->cbd_sc = BD_SC_INTRPT; |
| 697 | mem_addr += pinfo->tx_fifosize; | 716 | mem_addr += pinfo->tx_fifosize; |
| 698 | } | 717 | } |
| 699 | 718 | ||
| 700 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); | 719 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo); |
| 701 | bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT; | 720 | bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT; |
| 702 | } | 721 | } |
| 703 | 722 | ||
| @@ -829,14 +848,6 @@ static int cpm_uart_request_port(struct uart_port *port) | |||
| 829 | if (pinfo->flags & FLAG_CONSOLE) | 848 | if (pinfo->flags & FLAG_CONSOLE) |
| 830 | return 0; | 849 | return 0; |
| 831 | 850 | ||
| 832 | /* | ||
| 833 | * Setup any port IO, connect any baud rate generators, | ||
| 834 | * etc. This is expected to be handled by board | ||
| 835 | * dependant code | ||
| 836 | */ | ||
| 837 | if (pinfo->set_lineif) | ||
| 838 | pinfo->set_lineif(pinfo); | ||
| 839 | |||
| 840 | if (IS_SMC(pinfo)) { | 851 | if (IS_SMC(pinfo)) { |
| 841 | pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX); | 852 | pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX); |
| 842 | pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); | 853 | pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); |
| @@ -988,6 +999,54 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { | |||
| 988 | }, | 999 | }, |
| 989 | }; | 1000 | }; |
| 990 | 1001 | ||
| 1002 | int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con) | ||
| 1003 | { | ||
| 1004 | struct resource *r; | ||
| 1005 | struct fs_uart_platform_info *pdata = pdev->dev.platform_data; | ||
| 1006 | int idx = pdata->fs_no; /* It is UART_SMCx or UART_SCCx index */ | ||
| 1007 | struct uart_cpm_port *pinfo; | ||
| 1008 | int line; | ||
| 1009 | u32 mem, pram; | ||
| 1010 | |||
| 1011 | for (line=0; line<UART_NR && cpm_uart_port_map[line]!=pdata->fs_no; line++); | ||
| 1012 | |||
| 1013 | pinfo = (struct uart_cpm_port *) &cpm_uart_ports[idx]; | ||
| 1014 | |||
| 1015 | pinfo->brg = pdata->brg; | ||
| 1016 | |||
| 1017 | if (!is_con) { | ||
| 1018 | pinfo->port.line = line; | ||
| 1019 | pinfo->port.flags = UPF_BOOT_AUTOCONF; | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"))) | ||
| 1023 | return -EINVAL; | ||
| 1024 | mem = r->start; | ||
| 1025 | |||
| 1026 | if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram"))) | ||
| 1027 | return -EINVAL; | ||
| 1028 | pram = r->start; | ||
| 1029 | |||
| 1030 | if(idx > fsid_smc2_uart) { | ||
| 1031 | pinfo->sccp = (scc_t *)mem; | ||
| 1032 | pinfo->sccup = (scc_uart_t *)pram; | ||
| 1033 | } else { | ||
| 1034 | pinfo->smcp = (smc_t *)mem; | ||
| 1035 | pinfo->smcup = (smc_uart_t *)pram; | ||
| 1036 | } | ||
| 1037 | pinfo->tx_nrfifos = pdata->tx_num_fifo; | ||
| 1038 | pinfo->tx_fifosize = pdata->tx_buf_size; | ||
| 1039 | |||
| 1040 | pinfo->rx_nrfifos = pdata->rx_num_fifo; | ||
| 1041 | pinfo->rx_fifosize = pdata->rx_buf_size; | ||
| 1042 | |||
| 1043 | pinfo->port.uartclk = pdata->uart_clk; | ||
| 1044 | pinfo->port.mapbase = (unsigned long)mem; | ||
| 1045 | pinfo->port.irq = platform_get_irq(pdev, 0); | ||
| 1046 | |||
| 1047 | return 0; | ||
| 1048 | } | ||
| 1049 | |||
| 991 | #ifdef CONFIG_SERIAL_CPM_CONSOLE | 1050 | #ifdef CONFIG_SERIAL_CPM_CONSOLE |
| 992 | /* | 1051 | /* |
| 993 | * Print a string to the serial port trying not to disturb | 1052 | * Print a string to the serial port trying not to disturb |
| @@ -1027,7 +1086,7 @@ static void cpm_uart_console_write(struct console *co, const char *s, | |||
| 1027 | * If the buffer address is in the CPM DPRAM, don't | 1086 | * If the buffer address is in the CPM DPRAM, don't |
| 1028 | * convert it. | 1087 | * convert it. |
| 1029 | */ | 1088 | */ |
| 1030 | cp = cpm2cpu_addr(bdp->cbd_bufaddr); | 1089 | cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); |
| 1031 | 1090 | ||
| 1032 | *cp = *s; | 1091 | *cp = *s; |
| 1033 | 1092 | ||
| @@ -1044,7 +1103,7 @@ static void cpm_uart_console_write(struct console *co, const char *s, | |||
| 1044 | while ((bdp->cbd_sc & BD_SC_READY) != 0) | 1103 | while ((bdp->cbd_sc & BD_SC_READY) != 0) |
| 1045 | ; | 1104 | ; |
| 1046 | 1105 | ||
| 1047 | cp = cpm2cpu_addr(bdp->cbd_bufaddr); | 1106 | cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); |
| 1048 | 1107 | ||
| 1049 | *cp = 13; | 1108 | *cp = 13; |
| 1050 | bdp->cbd_datlen = 1; | 1109 | bdp->cbd_datlen = 1; |
| @@ -1067,9 +1126,7 @@ static void cpm_uart_console_write(struct console *co, const char *s, | |||
| 1067 | pinfo->tx_cur = (volatile cbd_t *) bdp; | 1126 | pinfo->tx_cur = (volatile cbd_t *) bdp; |
| 1068 | } | 1127 | } |
| 1069 | 1128 | ||
| 1070 | /* | 1129 | |
| 1071 | * Setup console. Be careful is called early ! | ||
| 1072 | */ | ||
| 1073 | static int __init cpm_uart_console_setup(struct console *co, char *options) | 1130 | static int __init cpm_uart_console_setup(struct console *co, char *options) |
| 1074 | { | 1131 | { |
| 1075 | struct uart_port *port; | 1132 | struct uart_port *port; |
| @@ -1080,9 +1137,27 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) | |||
| 1080 | int flow = 'n'; | 1137 | int flow = 'n'; |
| 1081 | int ret; | 1138 | int ret; |
| 1082 | 1139 | ||
| 1140 | struct fs_uart_platform_info *pdata; | ||
| 1141 | struct platform_device* pdev = early_uart_get_pdev(co->index); | ||
| 1142 | |||
| 1083 | port = | 1143 | port = |
| 1084 | (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]]; | 1144 | (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]]; |
| 1085 | pinfo = (struct uart_cpm_port *)port; | 1145 | pinfo = (struct uart_cpm_port *)port; |
| 1146 | if (!pdev) { | ||
| 1147 | pr_info("cpm_uart: console: compat mode\n"); | ||
| 1148 | /* compatibility - will be cleaned up */ | ||
| 1149 | cpm_uart_init_portdesc(); | ||
| 1150 | |||
| 1151 | if (pinfo->set_lineif) | ||
| 1152 | pinfo->set_lineif(pinfo); | ||
| 1153 | } else { | ||
| 1154 | pdata = pdev->dev.platform_data; | ||
| 1155 | if (pdata) | ||
| 1156 | if (pdata->init_ioports) | ||
| 1157 | pdata->init_ioports(); | ||
| 1158 | |||
| 1159 | cpm_uart_drv_get_platform_data(pdev, 1); | ||
| 1160 | } | ||
| 1086 | 1161 | ||
| 1087 | pinfo->flags |= FLAG_CONSOLE; | 1162 | pinfo->flags |= FLAG_CONSOLE; |
| 1088 | 1163 | ||
| @@ -1097,14 +1172,6 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) | |||
| 1097 | baud = 9600; | 1172 | baud = 9600; |
| 1098 | } | 1173 | } |
| 1099 | 1174 | ||
| 1100 | /* | ||
| 1101 | * Setup any port IO, connect any baud rate generators, | ||
| 1102 | * etc. This is expected to be handled by board | ||
| 1103 | * dependant code | ||
| 1104 | */ | ||
| 1105 | if (pinfo->set_lineif) | ||
| 1106 | pinfo->set_lineif(pinfo); | ||
| 1107 | |||
| 1108 | if (IS_SMC(pinfo)) { | 1175 | if (IS_SMC(pinfo)) { |
| 1109 | pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX); | 1176 | pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX); |
| 1110 | pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); | 1177 | pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); |
| @@ -1143,11 +1210,8 @@ static struct console cpm_scc_uart_console = { | |||
| 1143 | 1210 | ||
| 1144 | int __init cpm_uart_console_init(void) | 1211 | int __init cpm_uart_console_init(void) |
| 1145 | { | 1212 | { |
| 1146 | int ret = cpm_uart_init_portdesc(); | 1213 | register_console(&cpm_scc_uart_console); |
| 1147 | 1214 | return 0; | |
| 1148 | if (!ret) | ||
| 1149 | register_console(&cpm_scc_uart_console); | ||
| 1150 | return ret; | ||
| 1151 | } | 1215 | } |
| 1152 | 1216 | ||
| 1153 | console_initcall(cpm_uart_console_init); | 1217 | console_initcall(cpm_uart_console_init); |
| @@ -1165,44 +1229,130 @@ static struct uart_driver cpm_reg = { | |||
| 1165 | .minor = SERIAL_CPM_MINOR, | 1229 | .minor = SERIAL_CPM_MINOR, |
| 1166 | .cons = CPM_UART_CONSOLE, | 1230 | .cons = CPM_UART_CONSOLE, |
| 1167 | }; | 1231 | }; |
| 1168 | 1232 | static int cpm_uart_drv_probe(struct device *dev) | |
| 1169 | static int __init cpm_uart_init(void) | ||
| 1170 | { | 1233 | { |
| 1171 | int ret, i; | 1234 | struct platform_device *pdev = to_platform_device(dev); |
| 1172 | 1235 | struct fs_uart_platform_info *pdata; | |
| 1173 | printk(KERN_INFO "Serial: CPM driver $Revision: 0.01 $\n"); | 1236 | int ret = -ENODEV; |
| 1174 | 1237 | ||
| 1175 | #ifndef CONFIG_SERIAL_CPM_CONSOLE | 1238 | if(!pdev) { |
| 1176 | ret = cpm_uart_init_portdesc(); | 1239 | printk(KERN_ERR"CPM UART: platform data missing!\n"); |
| 1177 | if (ret) | ||
| 1178 | return ret; | 1240 | return ret; |
| 1179 | #endif | 1241 | } |
| 1180 | 1242 | ||
| 1181 | cpm_reg.nr = cpm_uart_nr; | 1243 | pdata = pdev->dev.platform_data; |
| 1182 | ret = uart_register_driver(&cpm_reg); | 1244 | pr_debug("cpm_uart_drv_probe: Adding CPM UART %d\n", |
| 1245 | cpm_uart_port_map[pdata->fs_no]); | ||
| 1183 | 1246 | ||
| 1184 | if (ret) | 1247 | if ((ret = cpm_uart_drv_get_platform_data(pdev, 0))) |
| 1185 | return ret; | 1248 | return ret; |
| 1186 | 1249 | ||
| 1187 | for (i = 0; i < cpm_uart_nr; i++) { | 1250 | if (pdata->init_ioports) |
| 1188 | int con = cpm_uart_port_map[i]; | 1251 | pdata->init_ioports(); |
| 1189 | cpm_uart_ports[con].port.line = i; | ||
| 1190 | cpm_uart_ports[con].port.flags = UPF_BOOT_AUTOCONF; | ||
| 1191 | uart_add_one_port(&cpm_reg, &cpm_uart_ports[con].port); | ||
| 1192 | } | ||
| 1193 | 1252 | ||
| 1194 | return ret; | 1253 | ret = uart_add_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port); |
| 1254 | |||
| 1255 | return ret; | ||
| 1195 | } | 1256 | } |
| 1196 | 1257 | ||
| 1197 | static void __exit cpm_uart_exit(void) | 1258 | static int cpm_uart_drv_remove(struct device *dev) |
| 1259 | { | ||
| 1260 | struct platform_device *pdev = to_platform_device(dev); | ||
| 1261 | struct fs_uart_platform_info *pdata = pdev->dev.platform_data; | ||
| 1262 | |||
| 1263 | pr_debug("cpm_uart_drv_remove: Removing CPM UART %d\n", | ||
| 1264 | cpm_uart_port_map[pdata->fs_no]); | ||
| 1265 | |||
| 1266 | uart_remove_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port); | ||
| 1267 | return 0; | ||
| 1268 | } | ||
| 1269 | |||
| 1270 | static struct device_driver cpm_smc_uart_driver = { | ||
| 1271 | .name = "fsl-cpm-smc:uart", | ||
| 1272 | .bus = &platform_bus_type, | ||
| 1273 | .probe = cpm_uart_drv_probe, | ||
| 1274 | .remove = cpm_uart_drv_remove, | ||
| 1275 | }; | ||
| 1276 | |||
| 1277 | static struct device_driver cpm_scc_uart_driver = { | ||
| 1278 | .name = "fsl-cpm-scc:uart", | ||
| 1279 | .bus = &platform_bus_type, | ||
| 1280 | .probe = cpm_uart_drv_probe, | ||
| 1281 | .remove = cpm_uart_drv_remove, | ||
| 1282 | }; | ||
| 1283 | |||
| 1284 | /* | ||
| 1285 | This is supposed to match uart devices on platform bus, | ||
| 1286 | */ | ||
| 1287 | static int match_is_uart (struct device* dev, void* data) | ||
| 1198 | { | 1288 | { |
| 1289 | struct platform_device* pdev = container_of(dev, struct platform_device, dev); | ||
| 1290 | int ret = 0; | ||
| 1291 | /* this was setfunc as uart */ | ||
| 1292 | if(strstr(pdev->name,":uart")) { | ||
| 1293 | ret = 1; | ||
| 1294 | } | ||
| 1295 | return ret; | ||
| 1296 | } | ||
| 1297 | |||
| 1298 | |||
| 1299 | static int cpm_uart_init(void) { | ||
| 1300 | |||
| 1301 | int ret; | ||
| 1199 | int i; | 1302 | int i; |
| 1303 | struct device *dev; | ||
| 1304 | printk(KERN_INFO "Serial: CPM driver $Revision: 0.02 $\n"); | ||
| 1305 | |||
| 1306 | /* lookup the bus for uart devices */ | ||
| 1307 | dev = bus_find_device(&platform_bus_type, NULL, 0, match_is_uart); | ||
| 1308 | |||
| 1309 | /* There are devices on the bus - all should be OK */ | ||
| 1310 | if (dev) { | ||
| 1311 | cpm_uart_count(); | ||
| 1312 | cpm_reg.nr = cpm_uart_nr; | ||
| 1313 | |||
| 1314 | if (!(ret = uart_register_driver(&cpm_reg))) { | ||
| 1315 | if ((ret = driver_register(&cpm_smc_uart_driver))) { | ||
| 1316 | uart_unregister_driver(&cpm_reg); | ||
| 1317 | return ret; | ||
| 1318 | } | ||
| 1319 | if ((ret = driver_register(&cpm_scc_uart_driver))) { | ||
| 1320 | driver_unregister(&cpm_scc_uart_driver); | ||
| 1321 | uart_unregister_driver(&cpm_reg); | ||
| 1322 | } | ||
| 1323 | } | ||
| 1324 | } else { | ||
| 1325 | /* No capable platform devices found - falling back to legacy mode */ | ||
| 1326 | pr_info("cpm_uart: WARNING: no UART devices found on platform bus!\n"); | ||
| 1327 | pr_info( | ||
| 1328 | "cpm_uart: the driver will guess configuration, but this mode is no longer supported.\n"); | ||
| 1329 | #ifndef CONFIG_SERIAL_CPM_CONSOLE | ||
| 1330 | ret = cpm_uart_init_portdesc(); | ||
| 1331 | if (ret) | ||
| 1332 | return ret; | ||
| 1333 | #endif | ||
| 1334 | |||
| 1335 | cpm_reg.nr = cpm_uart_nr; | ||
| 1336 | ret = uart_register_driver(&cpm_reg); | ||
| 1337 | |||
| 1338 | if (ret) | ||
| 1339 | return ret; | ||
| 1340 | |||
| 1341 | for (i = 0; i < cpm_uart_nr; i++) { | ||
| 1342 | int con = cpm_uart_port_map[i]; | ||
| 1343 | cpm_uart_ports[con].port.line = i; | ||
| 1344 | cpm_uart_ports[con].port.flags = UPF_BOOT_AUTOCONF; | ||
| 1345 | uart_add_one_port(&cpm_reg, &cpm_uart_ports[con].port); | ||
| 1346 | } | ||
| 1200 | 1347 | ||
| 1201 | for (i = 0; i < cpm_uart_nr; i++) { | ||
| 1202 | int con = cpm_uart_port_map[i]; | ||
| 1203 | uart_remove_one_port(&cpm_reg, &cpm_uart_ports[con].port); | ||
| 1204 | } | 1348 | } |
| 1349 | return ret; | ||
| 1350 | } | ||
| 1205 | 1351 | ||
| 1352 | static void __exit cpm_uart_exit(void) | ||
| 1353 | { | ||
| 1354 | driver_unregister(&cpm_scc_uart_driver); | ||
| 1355 | driver_unregister(&cpm_smc_uart_driver); | ||
| 1206 | uart_unregister_driver(&cpm_reg); | 1356 | uart_unregister_driver(&cpm_reg); |
| 1207 | } | 1357 | } |
| 1208 | 1358 | ||
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c index d789ee55cbb7..a5a30622637a 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c | |||
| @@ -81,58 +81,11 @@ void cpm_line_cr_cmd(int line, int cmd) | |||
| 81 | 81 | ||
| 82 | void smc1_lineif(struct uart_cpm_port *pinfo) | 82 | void smc1_lineif(struct uart_cpm_port *pinfo) |
| 83 | { | 83 | { |
| 84 | volatile cpm8xx_t *cp = cpmp; | ||
| 85 | |||
| 86 | (void)cp; /* fix warning */ | ||
| 87 | #if defined (CONFIG_MPC885ADS) | ||
| 88 | /* Enable SMC1 transceivers */ | ||
| 89 | { | ||
| 90 | cp->cp_pepar |= 0x000000c0; | ||
| 91 | cp->cp_pedir &= ~0x000000c0; | ||
| 92 | cp->cp_peso &= ~0x00000040; | ||
| 93 | cp->cp_peso |= 0x00000080; | ||
| 94 | } | ||
| 95 | #elif defined (CONFIG_MPC86XADS) | ||
| 96 | unsigned int iobits = 0x000000c0; | ||
| 97 | |||
| 98 | if (!pinfo->is_portb) { | ||
| 99 | cp->cp_pbpar |= iobits; | ||
| 100 | cp->cp_pbdir &= ~iobits; | ||
| 101 | cp->cp_pbodr &= ~iobits; | ||
| 102 | } else { | ||
| 103 | ((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits; | ||
| 104 | ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits; | ||
| 105 | ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits; | ||
| 106 | } | ||
| 107 | #endif | ||
| 108 | pinfo->brg = 1; | 84 | pinfo->brg = 1; |
| 109 | } | 85 | } |
| 110 | 86 | ||
| 111 | void smc2_lineif(struct uart_cpm_port *pinfo) | 87 | void smc2_lineif(struct uart_cpm_port *pinfo) |
| 112 | { | 88 | { |
| 113 | volatile cpm8xx_t *cp = cpmp; | ||
| 114 | |||
| 115 | (void)cp; /* fix warning */ | ||
| 116 | #if defined (CONFIG_MPC885ADS) | ||
| 117 | cp->cp_pepar |= 0x00000c00; | ||
| 118 | cp->cp_pedir &= ~0x00000c00; | ||
| 119 | cp->cp_peso &= ~0x00000400; | ||
| 120 | cp->cp_peso |= 0x00000800; | ||
| 121 | #elif defined (CONFIG_MPC86XADS) | ||
| 122 | unsigned int iobits = 0x00000c00; | ||
| 123 | |||
| 124 | if (!pinfo->is_portb) { | ||
| 125 | cp->cp_pbpar |= iobits; | ||
| 126 | cp->cp_pbdir &= ~iobits; | ||
| 127 | cp->cp_pbodr &= ~iobits; | ||
| 128 | } else { | ||
| 129 | ((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits; | ||
| 130 | ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits; | ||
| 131 | ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits; | ||
| 132 | } | ||
| 133 | |||
| 134 | #endif | ||
| 135 | |||
| 136 | pinfo->brg = 2; | 89 | pinfo->brg = 2; |
| 137 | } | 90 | } |
| 138 | 91 | ||
| @@ -191,7 +144,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) | |||
| 191 | /* was hostalloc but changed cause it blows away the */ | 144 | /* was hostalloc but changed cause it blows away the */ |
| 192 | /* large tlb mapping when pinning the kernel area */ | 145 | /* large tlb mapping when pinning the kernel area */ |
| 193 | mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8)); | 146 | mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8)); |
| 194 | dma_addr = 0; | 147 | dma_addr = (u32)mem_addr; |
| 195 | } else | 148 | } else |
| 196 | mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr, | 149 | mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr, |
| 197 | GFP_KERNEL); | 150 | GFP_KERNEL); |
| @@ -204,8 +157,9 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) | |||
| 204 | } | 157 | } |
| 205 | 158 | ||
| 206 | pinfo->dp_addr = dp_offset; | 159 | pinfo->dp_addr = dp_offset; |
| 207 | pinfo->mem_addr = mem_addr; | 160 | pinfo->mem_addr = mem_addr; /* virtual address*/ |
| 208 | pinfo->dma_addr = dma_addr; | 161 | pinfo->dma_addr = dma_addr; /* physical address*/ |
| 162 | pinfo->mem_size = memsz; | ||
| 209 | 163 | ||
| 210 | pinfo->rx_buf = mem_addr; | 164 | pinfo->rx_buf = mem_addr; |
| 211 | pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos | 165 | pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos |
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c index fd9e53ed3feb..7c6b07aeea92 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c | |||
| @@ -142,14 +142,6 @@ void scc2_lineif(struct uart_cpm_port *pinfo) | |||
| 142 | * be supported in a sane fashion. | 142 | * be supported in a sane fashion. |
| 143 | */ | 143 | */ |
| 144 | #ifndef CONFIG_STX_GP3 | 144 | #ifndef CONFIG_STX_GP3 |
| 145 | #ifdef CONFIG_MPC8560_ADS | ||
| 146 | volatile iop_cpm2_t *io = &cpm2_immr->im_ioport; | ||
| 147 | io->iop_ppard |= 0x00000018; | ||
| 148 | io->iop_psord &= ~0x00000008; /* Rx */ | ||
| 149 | io->iop_psord &= ~0x00000010; /* Tx */ | ||
| 150 | io->iop_pdird &= ~0x00000008; /* Rx */ | ||
| 151 | io->iop_pdird |= 0x00000010; /* Tx */ | ||
| 152 | #else | ||
| 153 | volatile iop_cpm2_t *io = &cpm2_immr->im_ioport; | 145 | volatile iop_cpm2_t *io = &cpm2_immr->im_ioport; |
| 154 | io->iop_pparb |= 0x008b0000; | 146 | io->iop_pparb |= 0x008b0000; |
| 155 | io->iop_pdirb |= 0x00880000; | 147 | io->iop_pdirb |= 0x00880000; |
| @@ -157,7 +149,6 @@ void scc2_lineif(struct uart_cpm_port *pinfo) | |||
| 157 | io->iop_pdirb &= ~0x00030000; | 149 | io->iop_pdirb &= ~0x00030000; |
| 158 | io->iop_psorb &= ~0x00030000; | 150 | io->iop_psorb &= ~0x00030000; |
| 159 | #endif | 151 | #endif |
| 160 | #endif | ||
| 161 | cpm2_immr->im_cpmux.cmx_scr &= 0xff00ffff; | 152 | cpm2_immr->im_cpmux.cmx_scr &= 0xff00ffff; |
| 162 | cpm2_immr->im_cpmux.cmx_scr |= 0x00090000; | 153 | cpm2_immr->im_cpmux.cmx_scr |= 0x00090000; |
| 163 | pinfo->brg = 2; | 154 | pinfo->brg = 2; |
| @@ -218,8 +209,10 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) | |||
| 218 | 209 | ||
| 219 | memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) + | 210 | memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) + |
| 220 | L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize); | 211 | L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize); |
| 221 | if (is_con) | 212 | if (is_con) { |
| 222 | mem_addr = alloc_bootmem(memsz); | 213 | mem_addr = alloc_bootmem(memsz); |
| 214 | dma_addr = mem_addr; | ||
| 215 | } | ||
| 223 | else | 216 | else |
| 224 | mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr, | 217 | mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr, |
| 225 | GFP_KERNEL); | 218 | GFP_KERNEL); |
| @@ -234,6 +227,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) | |||
| 234 | pinfo->dp_addr = dp_offset; | 227 | pinfo->dp_addr = dp_offset; |
| 235 | pinfo->mem_addr = mem_addr; | 228 | pinfo->mem_addr = mem_addr; |
| 236 | pinfo->dma_addr = dma_addr; | 229 | pinfo->dma_addr = dma_addr; |
| 230 | pinfo->mem_size = memsz; | ||
| 237 | 231 | ||
| 238 | pinfo->rx_buf = mem_addr; | 232 | pinfo->rx_buf = mem_addr; |
| 239 | pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos | 233 | pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos |
diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c index 0b49ff78efc1..501316b198e5 100644 --- a/drivers/sn/ioc3.c +++ b/drivers/sn/ioc3.c | |||
| @@ -678,7 +678,7 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) | |||
| 678 | /* Track PCI-device specific data */ | 678 | /* Track PCI-device specific data */ |
| 679 | pci_set_drvdata(pdev, idd); | 679 | pci_set_drvdata(pdev, idd); |
| 680 | down_write(&ioc3_devices_rwsem); | 680 | down_write(&ioc3_devices_rwsem); |
| 681 | list_add(&idd->list, &ioc3_devices); | 681 | list_add_tail(&idd->list, &ioc3_devices); |
| 682 | idd->id = ioc3_counter++; | 682 | idd->id = ioc3_counter++; |
| 683 | up_write(&ioc3_devices_rwsem); | 683 | up_write(&ioc3_devices_rwsem); |
| 684 | 684 | ||
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 6a4b93ad1082..0b9293493957 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c | |||
| @@ -2166,7 +2166,7 @@ static void handle_ep_small (struct net2280_ep *ep) | |||
| 2166 | ep->stopped = 1; | 2166 | ep->stopped = 1; |
| 2167 | set_halt (ep); | 2167 | set_halt (ep); |
| 2168 | mode = 2; | 2168 | mode = 2; |
| 2169 | } else if (!req && ep->stopped) | 2169 | } else if (!req && !ep->stopped) |
| 2170 | write_fifo (ep, NULL); | 2170 | write_fifo (ep, NULL); |
| 2171 | } | 2171 | } |
| 2172 | } else { | 2172 | } else { |
| @@ -2280,9 +2280,7 @@ static void handle_ep_small (struct net2280_ep *ep) | |||
| 2280 | /* if we wrote it all, we're usually done */ | 2280 | /* if we wrote it all, we're usually done */ |
| 2281 | if (req->req.actual == req->req.length) { | 2281 | if (req->req.actual == req->req.length) { |
| 2282 | if (ep->num == 0) { | 2282 | if (ep->num == 0) { |
| 2283 | /* wait for control status */ | 2283 | /* send zlps until the status stage */ |
| 2284 | if (mode != 2) | ||
| 2285 | req = NULL; | ||
| 2286 | } else if (!req->req.zero || len != ep->ep.maxpacket) | 2284 | } else if (!req->req.zero || len != ep->ep.maxpacket) |
| 2287 | mode = 2; | 2285 | mode = 2; |
| 2288 | } | 2286 | } |
| @@ -2744,6 +2742,10 @@ static irqreturn_t net2280_irq (int irq, void *_dev, struct pt_regs * r) | |||
| 2744 | { | 2742 | { |
| 2745 | struct net2280 *dev = _dev; | 2743 | struct net2280 *dev = _dev; |
| 2746 | 2744 | ||
| 2745 | /* shared interrupt, not ours */ | ||
| 2746 | if (!(readl(&dev->regs->irqstat0) & (1 << INTA_ASSERTED))) | ||
| 2747 | return IRQ_NONE; | ||
| 2748 | |||
| 2747 | spin_lock (&dev->lock); | 2749 | spin_lock (&dev->lock); |
| 2748 | 2750 | ||
| 2749 | /* handle disconnect, dma, and more */ | 2751 | /* handle disconnect, dma, and more */ |
| @@ -2831,13 +2833,13 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 2831 | } | 2833 | } |
| 2832 | 2834 | ||
| 2833 | /* alloc, and start init */ | 2835 | /* alloc, and start init */ |
| 2834 | dev = kmalloc (sizeof *dev, SLAB_KERNEL); | 2836 | dev = kzalloc (sizeof *dev, SLAB_KERNEL); |
| 2835 | if (dev == NULL){ | 2837 | if (dev == NULL){ |
| 2836 | retval = -ENOMEM; | 2838 | retval = -ENOMEM; |
| 2837 | goto done; | 2839 | goto done; |
| 2838 | } | 2840 | } |
| 2839 | 2841 | ||
| 2840 | memset (dev, 0, sizeof *dev); | 2842 | pci_set_drvdata (pdev, dev); |
| 2841 | spin_lock_init (&dev->lock); | 2843 | spin_lock_init (&dev->lock); |
| 2842 | dev->pdev = pdev; | 2844 | dev->pdev = pdev; |
| 2843 | dev->gadget.ops = &net2280_ops; | 2845 | dev->gadget.ops = &net2280_ops; |
| @@ -2950,7 +2952,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 2950 | dev->chiprev = get_idx_reg (dev->regs, REG_CHIPREV) & 0xffff; | 2952 | dev->chiprev = get_idx_reg (dev->regs, REG_CHIPREV) & 0xffff; |
| 2951 | 2953 | ||
| 2952 | /* done */ | 2954 | /* done */ |
| 2953 | pci_set_drvdata (pdev, dev); | ||
| 2954 | INFO (dev, "%s\n", driver_desc); | 2955 | INFO (dev, "%s\n", driver_desc); |
| 2955 | INFO (dev, "irq %s, pci mem %p, chip rev %04x\n", | 2956 | INFO (dev, "irq %s, pci mem %p, chip rev %04x\n", |
| 2956 | bufp, base, dev->chiprev); | 2957 | bufp, base, dev->chiprev); |
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 1e03f1a5a5fd..a1bd2bea6deb 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
| @@ -350,7 +350,7 @@ static const struct hc_driver ehci_pci_hc_driver = { | |||
| 350 | /* PCI driver selection metadata; PCI hotplugging uses this */ | 350 | /* PCI driver selection metadata; PCI hotplugging uses this */ |
| 351 | static const struct pci_device_id pci_ids [] = { { | 351 | static const struct pci_device_id pci_ids [] = { { |
| 352 | /* handle any USB 2.0 EHCI controller */ | 352 | /* handle any USB 2.0 EHCI controller */ |
| 353 | PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x20), ~0), | 353 | PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_EHCI, ~0), |
| 354 | .driver_data = (unsigned long) &ehci_pci_hc_driver, | 354 | .driver_data = (unsigned long) &ehci_pci_hc_driver, |
| 355 | }, | 355 | }, |
| 356 | { /* end: all zeroes */ } | 356 | { /* end: all zeroes */ } |
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 1bfe96f4d045..b268537e389e 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
| @@ -206,7 +206,7 @@ static const struct hc_driver ohci_pci_hc_driver = { | |||
| 206 | 206 | ||
| 207 | static const struct pci_device_id pci_ids [] = { { | 207 | static const struct pci_device_id pci_ids [] = { { |
| 208 | /* handle any USB OHCI controller */ | 208 | /* handle any USB OHCI controller */ |
| 209 | PCI_DEVICE_CLASS((PCI_CLASS_SERIAL_USB << 8) | 0x10, ~0), | 209 | PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_OHCI, ~0), |
| 210 | .driver_data = (unsigned long) &ohci_pci_hc_driver, | 210 | .driver_data = (unsigned long) &ohci_pci_hc_driver, |
| 211 | }, { /* end: all zeroes */ } | 211 | }, { /* end: all zeroes */ } |
| 212 | }; | 212 | }; |
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index c0c4db78b590..d225e11f4055 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
| @@ -858,7 +858,7 @@ static const struct hc_driver uhci_driver = { | |||
| 858 | 858 | ||
| 859 | static const struct pci_device_id uhci_pci_ids[] = { { | 859 | static const struct pci_device_id uhci_pci_ids[] = { { |
| 860 | /* handle any USB UHCI controller */ | 860 | /* handle any USB UHCI controller */ |
| 861 | PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x00), ~0), | 861 | PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_UHCI, ~0), |
| 862 | .driver_data = (unsigned long) &uhci_driver, | 862 | .driver_data = (unsigned long) &uhci_driver, |
| 863 | }, { /* end: all zeroes */ } | 863 | }, { /* end: all zeroes */ } |
| 864 | }; | 864 | }; |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index f5851db67f5b..82151207d814 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
| @@ -308,6 +308,7 @@ static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { | |||
| 308 | 308 | ||
| 309 | static struct usb_device_id id_table_combined [] = { | 309 | static struct usb_device_id id_table_combined [] = { |
| 310 | { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, | 310 | { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, |
| 311 | { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) }, | ||
| 311 | { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) }, | 312 | { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) }, |
| 312 | { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, | 313 | { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, |
| 313 | { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) }, | 314 | { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) }, |
| @@ -493,6 +494,8 @@ static struct usb_device_id id_table_combined [] = { | |||
| 493 | { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_777_PID) }, | 494 | { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_777_PID) }, |
| 494 | { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_8900F_PID) }, | 495 | { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_8900F_PID) }, |
| 495 | { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) }, | 496 | { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) }, |
| 497 | { USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) }, | ||
| 498 | { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) }, | ||
| 496 | { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) }, | 499 | { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) }, |
| 497 | { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) }, | 500 | { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) }, |
| 498 | { }, /* Optional parameter entry */ | 501 | { }, /* Optional parameter entry */ |
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 2155f0e4a378..2c55a5ea9c99 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h | |||
| @@ -39,6 +39,9 @@ | |||
| 39 | /* www.thoughttechnology.com/ TT-USB provide with procomp use ftdi_sio */ | 39 | /* www.thoughttechnology.com/ TT-USB provide with procomp use ftdi_sio */ |
| 40 | #define FTDI_TTUSB_PID 0xFF20 /* Product Id */ | 40 | #define FTDI_TTUSB_PID 0xFF20 /* Product Id */ |
| 41 | 41 | ||
| 42 | /* iPlus device */ | ||
| 43 | #define FTDI_IPLUS_PID 0xD070 /* Product Id */ | ||
| 44 | |||
| 42 | /* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */ | 45 | /* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */ |
| 43 | /* they use the ftdi chipset for the USB interface and the vendor id is the same */ | 46 | /* they use the ftdi chipset for the USB interface and the vendor id is the same */ |
| 44 | #define FTDI_XF_632_PID 0xFC08 /* 632: 16x2 Character Display */ | 47 | #define FTDI_XF_632_PID 0xFC08 /* 632: 16x2 Character Display */ |
| @@ -153,6 +156,11 @@ | |||
| 153 | #define ICOM_ID1_PID 0x0004 | 156 | #define ICOM_ID1_PID 0x0004 |
| 154 | 157 | ||
| 155 | /* | 158 | /* |
| 159 | * ASK.fr devices | ||
| 160 | */ | ||
| 161 | #define FTDI_ASK_RDR400_PID 0xC991 /* ASK RDR 400 series card reader */ | ||
| 162 | |||
| 163 | /* | ||
| 156 | * DSS-20 Sync Station for Sony Ericsson P800 | 164 | * DSS-20 Sync Station for Sony Ericsson P800 |
| 157 | */ | 165 | */ |
| 158 | 166 | ||
| @@ -400,6 +408,11 @@ | |||
| 400 | #define FTDI_WESTREX_MODEL_8900F_PID 0xDC01 /* Model 8900F */ | 408 | #define FTDI_WESTREX_MODEL_8900F_PID 0xDC01 /* Model 8900F */ |
| 401 | 409 | ||
| 402 | /* | 410 | /* |
| 411 | * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com) | ||
| 412 | */ | ||
| 413 | #define FTDI_RRCIRKITS_LOCOBUFFER_PID 0xc7d0 /* LocoBuffer USB */ | ||
| 414 | |||
| 415 | /* | ||
| 403 | * Eclo (http://www.eclo.pt/) product IDs. | 416 | * Eclo (http://www.eclo.pt/) product IDs. |
| 404 | * PID 0xEA90 submitted by Martin Grill. | 417 | * PID 0xEA90 submitted by Martin Grill. |
| 405 | */ | 418 | */ |
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index ccf746b27d4e..c96714bb1cb8 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
| @@ -61,6 +61,7 @@ static struct usb_device_id id_table [] = { | |||
| 61 | { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) }, | 61 | { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) }, |
| 62 | { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) }, | 62 | { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) }, |
| 63 | { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) }, | 63 | { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) }, |
| 64 | { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID_2080) }, | ||
| 64 | { USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) }, | 65 | { USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) }, |
| 65 | { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) }, | 66 | { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) }, |
| 66 | { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) }, | 67 | { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) }, |
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 09f379b19e98..7f29e81d3e35 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | 26 | ||
| 27 | #define ITEGNO_VENDOR_ID 0x0eba | 27 | #define ITEGNO_VENDOR_ID 0x0eba |
| 28 | #define ITEGNO_PRODUCT_ID 0x1080 | 28 | #define ITEGNO_PRODUCT_ID 0x1080 |
| 29 | #define ITEGNO_PRODUCT_ID_2080 0x2080 | ||
| 29 | 30 | ||
| 30 | #define MA620_VENDOR_ID 0x0df7 | 31 | #define MA620_VENDOR_ID 0x0df7 |
| 31 | #define MA620_PRODUCT_ID 0x0620 | 32 | #define MA620_PRODUCT_ID 0x0620 |
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 557411c6e7c7..f806553cd9a4 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c | |||
| @@ -508,6 +508,7 @@ no_firmware: | |||
| 508 | err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->description); | 508 | err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->description); |
| 509 | err("%s: If the firmware is not running (status led not blinking)\n", serial->type->description); | 509 | err("%s: If the firmware is not running (status led not blinking)\n", serial->type->description); |
| 510 | err("%s: please contact support@connecttech.com\n", serial->type->description); | 510 | err("%s: please contact support@connecttech.com\n", serial->type->description); |
| 511 | kfree(result); | ||
| 511 | return -ENODEV; | 512 | return -ENODEV; |
| 512 | 513 | ||
| 513 | no_command_private: | 514 | no_command_private: |
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index c4a9dcff5f2b..aec5ea8682d5 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h | |||
| @@ -411,7 +411,7 @@ UNUSUAL_DEV( 0x050d, 0x0115, 0x0133, 0x0133, | |||
| 411 | UNUSUAL_DEV( 0x0525, 0xa140, 0x0100, 0x0100, | 411 | UNUSUAL_DEV( 0x0525, 0xa140, 0x0100, 0x0100, |
| 412 | "Iomega", | 412 | "Iomega", |
| 413 | "USB Clik! 40", | 413 | "USB Clik! 40", |
| 414 | US_SC_8070, US_PR_BULK, NULL, | 414 | US_SC_8070, US_PR_DEVICE, NULL, |
| 415 | US_FL_FIX_INQUIRY ), | 415 | US_FL_FIX_INQUIRY ), |
| 416 | 416 | ||
| 417 | /* Yakumo Mega Image 37 | 417 | /* Yakumo Mega Image 37 |
| @@ -773,6 +773,13 @@ UNUSUAL_DEV( 0x069b, 0x3004, 0x0001, 0x0001, | |||
| 773 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 773 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
| 774 | US_FL_FIX_CAPACITY ), | 774 | US_FL_FIX_CAPACITY ), |
| 775 | 775 | ||
| 776 | /* Reported by Olivier Blondeau <zeitoun@gmail.com> */ | ||
| 777 | UNUSUAL_DEV( 0x0727, 0x0306, 0x0100, 0x0100, | ||
| 778 | "ATMEL", | ||
| 779 | "SND1 Storage", | ||
| 780 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
| 781 | US_FL_IGNORE_RESIDUE), | ||
| 782 | |||
| 776 | /* Submitted by Roman Hodek <roman@hodek.net> */ | 783 | /* Submitted by Roman Hodek <roman@hodek.net> */ |
| 777 | UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200, | 784 | UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200, |
| 778 | "Sandisk", | 785 | "Sandisk", |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 9060e7137441..4587087d777a 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
| @@ -400,6 +400,8 @@ config FB_ASILIANT | |||
| 400 | select FB_CFB_FILLRECT | 400 | select FB_CFB_FILLRECT |
| 401 | select FB_CFB_COPYAREA | 401 | select FB_CFB_COPYAREA |
| 402 | select FB_CFB_IMAGEBLIT | 402 | select FB_CFB_IMAGEBLIT |
| 403 | help | ||
| 404 | This is the frame buffer device driver for the Asiliant 69030 chipset | ||
| 403 | 405 | ||
| 404 | config FB_IMSTT | 406 | config FB_IMSTT |
| 405 | bool "IMS Twin Turbo display support" | 407 | bool "IMS Twin Turbo display support" |
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c index b367de30b98c..600d3e0e08b7 100644 --- a/drivers/video/au1200fb.c +++ b/drivers/video/au1200fb.c | |||
| @@ -1920,1925 +1920,3 @@ module_exit(au1200fb_cleanup); | |||
| 1920 | 1920 | ||
| 1921 | MODULE_DESCRIPTION(DRIVER_DESC); | 1921 | MODULE_DESCRIPTION(DRIVER_DESC); |
| 1922 | MODULE_LICENSE("GPL"); | 1922 | MODULE_LICENSE("GPL"); |
| 1923 | /* | ||
| 1924 | * BRIEF MODULE DESCRIPTION | ||
| 1925 | * Au1200 LCD Driver. | ||
| 1926 | * | ||
| 1927 | * Copyright 2004-2005 AMD | ||
| 1928 | * Author: AMD | ||
| 1929 | * | ||
| 1930 | * Based on: | ||
| 1931 | * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device | ||
| 1932 | * Created 28 Dec 1997 by Geert Uytterhoeven | ||
| 1933 | * | ||
| 1934 | * This program is free software; you can redistribute it and/or modify it | ||
| 1935 | * under the terms of the GNU General Public License as published by the | ||
| 1936 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 1937 | * option) any later version. | ||
| 1938 | * | ||
| 1939 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
| 1940 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
| 1941 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
| 1942 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
| 1943 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
| 1944 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
| 1945 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
| 1946 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 1947 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
| 1948 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 1949 | * | ||
| 1950 | * You should have received a copy of the GNU General Public License along | ||
| 1951 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 1952 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 1953 | */ | ||
| 1954 | |||
| 1955 | #include <linux/module.h> | ||
| 1956 | #include <linux/platform_device.h> | ||
| 1957 | #include <linux/kernel.h> | ||
| 1958 | #include <linux/errno.h> | ||
| 1959 | #include <linux/string.h> | ||
| 1960 | #include <linux/mm.h> | ||
| 1961 | #include <linux/fb.h> | ||
| 1962 | #include <linux/init.h> | ||
| 1963 | #include <linux/interrupt.h> | ||
| 1964 | #include <linux/ctype.h> | ||
| 1965 | #include <linux/dma-mapping.h> | ||
| 1966 | |||
| 1967 | #include <asm/mach-au1x00/au1000.h> | ||
| 1968 | #include "au1200fb.h" | ||
| 1969 | |||
| 1970 | #ifdef CONFIG_PM | ||
| 1971 | #include <asm/mach-au1x00/au1xxx_pm.h> | ||
| 1972 | #endif | ||
| 1973 | |||
| 1974 | #ifndef CONFIG_FB_AU1200_DEVS | ||
| 1975 | #define CONFIG_FB_AU1200_DEVS 4 | ||
| 1976 | #endif | ||
| 1977 | |||
| 1978 | #define DRIVER_NAME "au1200fb" | ||
| 1979 | #define DRIVER_DESC "LCD controller driver for AU1200 processors" | ||
| 1980 | |||
| 1981 | #define DEBUG 1 | ||
| 1982 | |||
| 1983 | #define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) | ||
| 1984 | #define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) | ||
| 1985 | #define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg) | ||
| 1986 | |||
| 1987 | #if DEBUG | ||
| 1988 | #define print_dbg(f, arg...) printk(KERN_DEBUG __FILE__ ": " f "\n", ## arg) | ||
| 1989 | #else | ||
| 1990 | #define print_dbg(f, arg...) do {} while (0) | ||
| 1991 | #endif | ||
| 1992 | |||
| 1993 | |||
| 1994 | #define AU1200_LCD_FB_IOCTL 0x46FF | ||
| 1995 | |||
| 1996 | #define AU1200_LCD_SET_SCREEN 1 | ||
| 1997 | #define AU1200_LCD_GET_SCREEN 2 | ||
| 1998 | #define AU1200_LCD_SET_WINDOW 3 | ||
| 1999 | #define AU1200_LCD_GET_WINDOW 4 | ||
| 2000 | #define AU1200_LCD_SET_PANEL 5 | ||
| 2001 | #define AU1200_LCD_GET_PANEL 6 | ||
| 2002 | |||
| 2003 | #define SCREEN_SIZE (1<< 1) | ||
| 2004 | #define SCREEN_BACKCOLOR (1<< 2) | ||
| 2005 | #define SCREEN_BRIGHTNESS (1<< 3) | ||
| 2006 | #define SCREEN_COLORKEY (1<< 4) | ||
| 2007 | #define SCREEN_MASK (1<< 5) | ||
| 2008 | |||
| 2009 | struct au1200_lcd_global_regs_t { | ||
| 2010 | unsigned int flags; | ||
| 2011 | unsigned int xsize; | ||
| 2012 | unsigned int ysize; | ||
| 2013 | unsigned int backcolor; | ||
| 2014 | unsigned int brightness; | ||
| 2015 | unsigned int colorkey; | ||
| 2016 | unsigned int mask; | ||
| 2017 | unsigned int panel_choice; | ||
| 2018 | char panel_desc[80]; | ||
| 2019 | |||
| 2020 | }; | ||
| 2021 | |||
| 2022 | #define WIN_POSITION (1<< 0) | ||
| 2023 | #define WIN_ALPHA_COLOR (1<< 1) | ||
| 2024 | #define WIN_ALPHA_MODE (1<< 2) | ||
| 2025 | #define WIN_PRIORITY (1<< 3) | ||
| 2026 | #define WIN_CHANNEL (1<< 4) | ||
| 2027 | #define WIN_BUFFER_FORMAT (1<< 5) | ||
| 2028 | #define WIN_COLOR_ORDER (1<< 6) | ||
| 2029 | #define WIN_PIXEL_ORDER (1<< 7) | ||
| 2030 | #define WIN_SIZE (1<< 8) | ||
| 2031 | #define WIN_COLORKEY_MODE (1<< 9) | ||
| 2032 | #define WIN_DOUBLE_BUFFER_MODE (1<< 10) | ||
| 2033 | #define WIN_RAM_ARRAY_MODE (1<< 11) | ||
| 2034 | #define WIN_BUFFER_SCALE (1<< 12) | ||
| 2035 | #define WIN_ENABLE (1<< 13) | ||
| 2036 | |||
| 2037 | struct au1200_lcd_window_regs_t { | ||
| 2038 | unsigned int flags; | ||
| 2039 | unsigned int xpos; | ||
| 2040 | unsigned int ypos; | ||
| 2041 | unsigned int alpha_color; | ||
| 2042 | unsigned int alpha_mode; | ||
| 2043 | unsigned int priority; | ||
| 2044 | unsigned int channel; | ||
| 2045 | unsigned int buffer_format; | ||
| 2046 | unsigned int color_order; | ||
| 2047 | unsigned int pixel_order; | ||
| 2048 | unsigned int xsize; | ||
| 2049 | unsigned int ysize; | ||
| 2050 | unsigned int colorkey_mode; | ||
| 2051 | unsigned int double_buffer_mode; | ||
| 2052 | unsigned int ram_array_mode; | ||
| 2053 | unsigned int xscale; | ||
| 2054 | unsigned int yscale; | ||
| 2055 | unsigned int enable; | ||
| 2056 | }; | ||
| 2057 | |||
| 2058 | |||
| 2059 | struct au1200_lcd_iodata_t { | ||
| 2060 | unsigned int subcmd; | ||
| 2061 | struct au1200_lcd_global_regs_t global; | ||
| 2062 | struct au1200_lcd_window_regs_t window; | ||
| 2063 | }; | ||
| 2064 | |||
| 2065 | #if defined(__BIG_ENDIAN) | ||
| 2066 | #define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11 | ||
| 2067 | #else | ||
| 2068 | #define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00 | ||
| 2069 | #endif | ||
| 2070 | #define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565 | ||
| 2071 | |||
| 2072 | /* Private, per-framebuffer management information (independent of the panel itself) */ | ||
| 2073 | struct au1200fb_device { | ||
| 2074 | struct fb_info fb_info; /* FB driver info record */ | ||
| 2075 | |||
| 2076 | int plane; | ||
| 2077 | unsigned char* fb_mem; /* FrameBuffer memory map */ | ||
| 2078 | unsigned int fb_len; | ||
| 2079 | dma_addr_t fb_phys; | ||
| 2080 | }; | ||
| 2081 | |||
| 2082 | static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS]; | ||
| 2083 | /********************************************************************/ | ||
| 2084 | |||
| 2085 | /* LCD controller restrictions */ | ||
| 2086 | #define AU1200_LCD_MAX_XRES 1280 | ||
| 2087 | #define AU1200_LCD_MAX_YRES 1024 | ||
| 2088 | #define AU1200_LCD_MAX_BPP 32 | ||
| 2089 | #define AU1200_LCD_MAX_CLK 96000000 /* fixme: this needs to go away ? */ | ||
| 2090 | #define AU1200_LCD_NBR_PALETTE_ENTRIES 256 | ||
| 2091 | |||
| 2092 | /* Default number of visible screen buffer to allocate */ | ||
| 2093 | #define AU1200FB_NBR_VIDEO_BUFFERS 1 | ||
| 2094 | |||
| 2095 | /********************************************************************/ | ||
| 2096 | |||
| 2097 | static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR; | ||
| 2098 | static int window_index = 2; /* default is zero */ | ||
| 2099 | static int panel_index = 2; /* default is zero */ | ||
| 2100 | static struct window_settings *win; | ||
| 2101 | static struct panel_settings *panel; | ||
| 2102 | static int noblanking = 1; | ||
| 2103 | static int nohwcursor = 0; | ||
| 2104 | |||
| 2105 | struct window_settings { | ||
| 2106 | unsigned char name[64]; | ||
| 2107 | uint32 mode_backcolor; | ||
| 2108 | uint32 mode_colorkey; | ||
| 2109 | uint32 mode_colorkeymsk; | ||
| 2110 | struct { | ||
| 2111 | int xres; | ||
| 2112 | int yres; | ||
| 2113 | int xpos; | ||
| 2114 | int ypos; | ||
| 2115 | uint32 mode_winctrl1; /* winctrl1[FRM,CCO,PO,PIPE] */ | ||
| 2116 | uint32 mode_winenable; | ||
| 2117 | } w[4]; | ||
| 2118 | }; | ||
| 2119 | |||
| 2120 | #if defined(__BIG_ENDIAN) | ||
| 2121 | #define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_00 | ||
| 2122 | #else | ||
| 2123 | #define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_01 | ||
| 2124 | #endif | ||
| 2125 | |||
| 2126 | extern int board_au1200fb_panel_init (void); | ||
| 2127 | extern int board_au1200fb_panel_shutdown (void); | ||
| 2128 | |||
| 2129 | #ifdef CONFIG_PM | ||
| 2130 | int au1200fb_pm_callback(au1xxx_power_dev_t *dev, | ||
| 2131 | au1xxx_request_t request, void *data); | ||
| 2132 | au1xxx_power_dev_t *LCD_pm_dev; | ||
| 2133 | #endif | ||
| 2134 | |||
| 2135 | /* | ||
| 2136 | * Default window configurations | ||
| 2137 | */ | ||
| 2138 | static struct window_settings windows[] = { | ||
| 2139 | { /* Index 0 */ | ||
| 2140 | "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", | ||
| 2141 | /* mode_backcolor */ 0x006600ff, | ||
| 2142 | /* mode_colorkey,msk*/ 0, 0, | ||
| 2143 | { | ||
| 2144 | { | ||
| 2145 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 2146 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 2147 | LCD_WINCTRL1_PO_16BPP, | ||
| 2148 | /* mode_winenable*/ LCD_WINENABLE_WEN0, | ||
| 2149 | }, | ||
| 2150 | { | ||
| 2151 | /* xres, yres, xpos, ypos */ 100, 100, 100, 100, | ||
| 2152 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 2153 | LCD_WINCTRL1_PO_16BPP | | ||
| 2154 | LCD_WINCTRL1_PIPE, | ||
| 2155 | /* mode_winenable*/ LCD_WINENABLE_WEN1, | ||
| 2156 | }, | ||
| 2157 | { | ||
| 2158 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 2159 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 2160 | LCD_WINCTRL1_PO_16BPP, | ||
| 2161 | /* mode_winenable*/ 0, | ||
| 2162 | }, | ||
| 2163 | { | ||
| 2164 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 2165 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 2166 | LCD_WINCTRL1_PO_16BPP | | ||
| 2167 | LCD_WINCTRL1_PIPE, | ||
| 2168 | /* mode_winenable*/ 0, | ||
| 2169 | }, | ||
| 2170 | }, | ||
| 2171 | }, | ||
| 2172 | |||
| 2173 | { /* Index 1 */ | ||
| 2174 | "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", | ||
| 2175 | /* mode_backcolor */ 0x006600ff, | ||
| 2176 | /* mode_colorkey,msk*/ 0, 0, | ||
| 2177 | { | ||
| 2178 | { | ||
| 2179 | /* xres, yres, xpos, ypos */ 320, 240, 5, 5, | ||
| 2180 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_24BPP | | ||
| 2181 | LCD_WINCTRL1_PO_00, | ||
| 2182 | /* mode_winenable*/ LCD_WINENABLE_WEN0, | ||
| 2183 | }, | ||
| 2184 | { | ||
| 2185 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 2186 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | ||
| 2187 | | LCD_WINCTRL1_PO_16BPP, | ||
| 2188 | /* mode_winenable*/ 0, | ||
| 2189 | }, | ||
| 2190 | { | ||
| 2191 | /* xres, yres, xpos, ypos */ 100, 100, 0, 0, | ||
| 2192 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 2193 | LCD_WINCTRL1_PO_16BPP | | ||
| 2194 | LCD_WINCTRL1_PIPE, | ||
| 2195 | /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/, | ||
| 2196 | }, | ||
| 2197 | { | ||
| 2198 | /* xres, yres, xpos, ypos */ 200, 25, 0, 0, | ||
| 2199 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 2200 | LCD_WINCTRL1_PO_16BPP | | ||
| 2201 | LCD_WINCTRL1_PIPE, | ||
| 2202 | /* mode_winenable*/ 0, | ||
| 2203 | }, | ||
| 2204 | }, | ||
| 2205 | }, | ||
| 2206 | { /* Index 2 */ | ||
| 2207 | "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", | ||
| 2208 | /* mode_backcolor */ 0x006600ff, | ||
| 2209 | /* mode_colorkey,msk*/ 0, 0, | ||
| 2210 | { | ||
| 2211 | { | ||
| 2212 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 2213 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 2214 | LCD_WINCTRL1_PO_16BPP, | ||
| 2215 | /* mode_winenable*/ LCD_WINENABLE_WEN0, | ||
| 2216 | }, | ||
| 2217 | { | ||
| 2218 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 2219 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 2220 | LCD_WINCTRL1_PO_16BPP, | ||
| 2221 | /* mode_winenable*/ 0, | ||
| 2222 | }, | ||
| 2223 | { | ||
| 2224 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 2225 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_32BPP | | ||
| 2226 | LCD_WINCTRL1_PO_00|LCD_WINCTRL1_PIPE, | ||
| 2227 | /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/, | ||
| 2228 | }, | ||
| 2229 | { | ||
| 2230 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 2231 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 2232 | LCD_WINCTRL1_PO_16BPP | | ||
| 2233 | LCD_WINCTRL1_PIPE, | ||
| 2234 | /* mode_winenable*/ 0, | ||
| 2235 | }, | ||
| 2236 | }, | ||
| 2237 | }, | ||
| 2238 | /* Need VGA 640 @ 24bpp, @ 32bpp */ | ||
| 2239 | /* Need VGA 800 @ 24bpp, @ 32bpp */ | ||
| 2240 | /* Need VGA 1024 @ 24bpp, @ 32bpp */ | ||
| 2241 | }; | ||
| 2242 | |||
| 2243 | /* | ||
| 2244 | * Controller configurations for various panels. | ||
| 2245 | */ | ||
| 2246 | |||
| 2247 | struct panel_settings | ||
| 2248 | { | ||
| 2249 | const char name[25]; /* Full name <vendor>_<model> */ | ||
| 2250 | |||
| 2251 | struct fb_monspecs monspecs; /* FB monitor specs */ | ||
| 2252 | |||
| 2253 | /* panel timings */ | ||
| 2254 | uint32 mode_screen; | ||
| 2255 | uint32 mode_horztiming; | ||
| 2256 | uint32 mode_verttiming; | ||
| 2257 | uint32 mode_clkcontrol; | ||
| 2258 | uint32 mode_pwmdiv; | ||
| 2259 | uint32 mode_pwmhi; | ||
| 2260 | uint32 mode_outmask; | ||
| 2261 | uint32 mode_fifoctrl; | ||
| 2262 | uint32 mode_toyclksrc; | ||
| 2263 | uint32 mode_backlight; | ||
| 2264 | uint32 mode_auxpll; | ||
| 2265 | int (*device_init)(void); | ||
| 2266 | int (*device_shutdown)(void); | ||
| 2267 | #define Xres min_xres | ||
| 2268 | #define Yres min_yres | ||
| 2269 | u32 min_xres; /* Minimum horizontal resolution */ | ||
| 2270 | u32 max_xres; /* Maximum horizontal resolution */ | ||
| 2271 | u32 min_yres; /* Minimum vertical resolution */ | ||
| 2272 | u32 max_yres; /* Maximum vertical resolution */ | ||
| 2273 | }; | ||
| 2274 | |||
| 2275 | /********************************************************************/ | ||
| 2276 | /* fixme: Maybe a modedb for the CRT ? otherwise panels should be as-is */ | ||
| 2277 | |||
| 2278 | /* List of panels known to work with the AU1200 LCD controller. | ||
| 2279 | * To add a new panel, enter the same specifications as the | ||
| 2280 | * Generic_TFT one, and MAKE SURE that it doesn't conflicts | ||
| 2281 | * with the controller restrictions. Restrictions are: | ||
| 2282 | * | ||
| 2283 | * STN color panels: max_bpp <= 12 | ||
| 2284 | * STN mono panels: max_bpp <= 4 | ||
| 2285 | * TFT panels: max_bpp <= 16 | ||
| 2286 | * max_xres <= 800 | ||
| 2287 | * max_yres <= 600 | ||
| 2288 | */ | ||
| 2289 | static struct panel_settings known_lcd_panels[] = | ||
| 2290 | { | ||
| 2291 | [0] = { /* QVGA 320x240 H:33.3kHz V:110Hz */ | ||
| 2292 | .name = "QVGA_320x240", | ||
| 2293 | .monspecs = { | ||
| 2294 | .modedb = NULL, | ||
| 2295 | .modedb_len = 0, | ||
| 2296 | .hfmin = 30000, | ||
| 2297 | .hfmax = 70000, | ||
| 2298 | .vfmin = 60, | ||
| 2299 | .vfmax = 60, | ||
| 2300 | .dclkmin = 6000000, | ||
| 2301 | .dclkmax = 28000000, | ||
| 2302 | .input = FB_DISP_RGB, | ||
| 2303 | }, | ||
| 2304 | .mode_screen = LCD_SCREEN_SX_N(320) | | ||
| 2305 | LCD_SCREEN_SY_N(240), | ||
| 2306 | .mode_horztiming = 0x00c4623b, | ||
| 2307 | .mode_verttiming = 0x00502814, | ||
| 2308 | .mode_clkcontrol = 0x00020002, /* /4=24Mhz */ | ||
| 2309 | .mode_pwmdiv = 0x00000000, | ||
| 2310 | .mode_pwmhi = 0x00000000, | ||
| 2311 | .mode_outmask = 0x00FFFFFF, | ||
| 2312 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 2313 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 2314 | .mode_backlight = 0x00000000, | ||
| 2315 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 2316 | .device_init = NULL, | ||
| 2317 | .device_shutdown = NULL, | ||
| 2318 | 320, 320, | ||
| 2319 | 240, 240, | ||
| 2320 | }, | ||
| 2321 | |||
| 2322 | [1] = { /* VGA 640x480 H:30.3kHz V:58Hz */ | ||
| 2323 | .name = "VGA_640x480", | ||
| 2324 | .monspecs = { | ||
| 2325 | .modedb = NULL, | ||
| 2326 | .modedb_len = 0, | ||
| 2327 | .hfmin = 30000, | ||
| 2328 | .hfmax = 70000, | ||
| 2329 | .vfmin = 60, | ||
| 2330 | .vfmax = 60, | ||
| 2331 | .dclkmin = 6000000, | ||
| 2332 | .dclkmax = 28000000, | ||
| 2333 | .input = FB_DISP_RGB, | ||
| 2334 | }, | ||
| 2335 | .mode_screen = 0x13f9df80, | ||
| 2336 | .mode_horztiming = 0x003c5859, | ||
| 2337 | .mode_verttiming = 0x00741201, | ||
| 2338 | .mode_clkcontrol = 0x00020001, /* /4=24Mhz */ | ||
| 2339 | .mode_pwmdiv = 0x00000000, | ||
| 2340 | .mode_pwmhi = 0x00000000, | ||
| 2341 | .mode_outmask = 0x00FFFFFF, | ||
| 2342 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 2343 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 2344 | .mode_backlight = 0x00000000, | ||
| 2345 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 2346 | .device_init = NULL, | ||
| 2347 | .device_shutdown = NULL, | ||
| 2348 | 640, 480, | ||
| 2349 | 640, 480, | ||
| 2350 | }, | ||
| 2351 | |||
| 2352 | [2] = { /* SVGA 800x600 H:46.1kHz V:69Hz */ | ||
| 2353 | .name = "SVGA_800x600", | ||
| 2354 | .monspecs = { | ||
| 2355 | .modedb = NULL, | ||
| 2356 | .modedb_len = 0, | ||
| 2357 | .hfmin = 30000, | ||
| 2358 | .hfmax = 70000, | ||
| 2359 | .vfmin = 60, | ||
| 2360 | .vfmax = 60, | ||
| 2361 | .dclkmin = 6000000, | ||
| 2362 | .dclkmax = 28000000, | ||
| 2363 | .input = FB_DISP_RGB, | ||
| 2364 | }, | ||
| 2365 | .mode_screen = 0x18fa5780, | ||
| 2366 | .mode_horztiming = 0x00dc7e77, | ||
| 2367 | .mode_verttiming = 0x00584805, | ||
| 2368 | .mode_clkcontrol = 0x00020000, /* /2=48Mhz */ | ||
| 2369 | .mode_pwmdiv = 0x00000000, | ||
| 2370 | .mode_pwmhi = 0x00000000, | ||
| 2371 | .mode_outmask = 0x00FFFFFF, | ||
| 2372 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 2373 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 2374 | .mode_backlight = 0x00000000, | ||
| 2375 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 2376 | .device_init = NULL, | ||
| 2377 | .device_shutdown = NULL, | ||
| 2378 | 800, 800, | ||
| 2379 | 600, 600, | ||
| 2380 | }, | ||
| 2381 | |||
| 2382 | [3] = { /* XVGA 1024x768 H:56.2kHz V:70Hz */ | ||
| 2383 | .name = "XVGA_1024x768", | ||
| 2384 | .monspecs = { | ||
| 2385 | .modedb = NULL, | ||
| 2386 | .modedb_len = 0, | ||
| 2387 | .hfmin = 30000, | ||
| 2388 | .hfmax = 70000, | ||
| 2389 | .vfmin = 60, | ||
| 2390 | .vfmax = 60, | ||
| 2391 | .dclkmin = 6000000, | ||
| 2392 | .dclkmax = 28000000, | ||
| 2393 | .input = FB_DISP_RGB, | ||
| 2394 | }, | ||
| 2395 | .mode_screen = 0x1ffaff80, | ||
| 2396 | .mode_horztiming = 0x007d0e57, | ||
| 2397 | .mode_verttiming = 0x00740a01, | ||
| 2398 | .mode_clkcontrol = 0x000A0000, /* /1 */ | ||
| 2399 | .mode_pwmdiv = 0x00000000, | ||
| 2400 | .mode_pwmhi = 0x00000000, | ||
| 2401 | .mode_outmask = 0x00FFFFFF, | ||
| 2402 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 2403 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 2404 | .mode_backlight = 0x00000000, | ||
| 2405 | .mode_auxpll = 6, /* 72MHz AUXPLL */ | ||
| 2406 | .device_init = NULL, | ||
| 2407 | .device_shutdown = NULL, | ||
| 2408 | 1024, 1024, | ||
| 2409 | 768, 768, | ||
| 2410 | }, | ||
| 2411 | |||
| 2412 | [4] = { /* XVGA XVGA 1280x1024 H:68.5kHz V:65Hz */ | ||
| 2413 | .name = "XVGA_1280x1024", | ||
| 2414 | .monspecs = { | ||
| 2415 | .modedb = NULL, | ||
| 2416 | .modedb_len = 0, | ||
| 2417 | .hfmin = 30000, | ||
| 2418 | .hfmax = 70000, | ||
| 2419 | .vfmin = 60, | ||
| 2420 | .vfmax = 60, | ||
| 2421 | .dclkmin = 6000000, | ||
| 2422 | .dclkmax = 28000000, | ||
| 2423 | .input = FB_DISP_RGB, | ||
| 2424 | }, | ||
| 2425 | .mode_screen = 0x27fbff80, | ||
| 2426 | .mode_horztiming = 0x00cdb2c7, | ||
| 2427 | .mode_verttiming = 0x00600002, | ||
| 2428 | .mode_clkcontrol = 0x000A0000, /* /1 */ | ||
| 2429 | .mode_pwmdiv = 0x00000000, | ||
| 2430 | .mode_pwmhi = 0x00000000, | ||
| 2431 | .mode_outmask = 0x00FFFFFF, | ||
| 2432 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 2433 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 2434 | .mode_backlight = 0x00000000, | ||
| 2435 | .mode_auxpll = 10, /* 120MHz AUXPLL */ | ||
| 2436 | .device_init = NULL, | ||
| 2437 | .device_shutdown = NULL, | ||
| 2438 | 1280, 1280, | ||
| 2439 | 1024, 1024, | ||
| 2440 | }, | ||
| 2441 | |||
| 2442 | [5] = { /* Samsung 1024x768 TFT */ | ||
| 2443 | .name = "Samsung_1024x768_TFT", | ||
| 2444 | .monspecs = { | ||
| 2445 | .modedb = NULL, | ||
| 2446 | .modedb_len = 0, | ||
| 2447 | .hfmin = 30000, | ||
| 2448 | .hfmax = 70000, | ||
| 2449 | .vfmin = 60, | ||
| 2450 | .vfmax = 60, | ||
| 2451 | .dclkmin = 6000000, | ||
| 2452 | .dclkmax = 28000000, | ||
| 2453 | .input = FB_DISP_RGB, | ||
| 2454 | }, | ||
| 2455 | .mode_screen = 0x1ffaff80, | ||
| 2456 | .mode_horztiming = 0x018cc677, | ||
| 2457 | .mode_verttiming = 0x00241217, | ||
| 2458 | .mode_clkcontrol = 0x00000000, /* SCB 0x1 /4=24Mhz */ | ||
| 2459 | .mode_pwmdiv = 0x8000063f, /* SCB 0x0 */ | ||
| 2460 | .mode_pwmhi = 0x03400000, /* SCB 0x0 */ | ||
| 2461 | .mode_outmask = 0x00FFFFFF, | ||
| 2462 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 2463 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 2464 | .mode_backlight = 0x00000000, | ||
| 2465 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 2466 | .device_init = board_au1200fb_panel_init, | ||
| 2467 | .device_shutdown = board_au1200fb_panel_shutdown, | ||
| 2468 | 1024, 1024, | ||
| 2469 | 768, 768, | ||
| 2470 | }, | ||
| 2471 | |||
| 2472 | [6] = { /* Toshiba 640x480 TFT */ | ||
| 2473 | .name = "Toshiba_640x480_TFT", | ||
| 2474 | .monspecs = { | ||
| 2475 | .modedb = NULL, | ||
| 2476 | .modedb_len = 0, | ||
| 2477 | .hfmin = 30000, | ||
| 2478 | .hfmax = 70000, | ||
| 2479 | .vfmin = 60, | ||
| 2480 | .vfmax = 60, | ||
| 2481 | .dclkmin = 6000000, | ||
| 2482 | .dclkmax = 28000000, | ||
| 2483 | .input = FB_DISP_RGB, | ||
| 2484 | }, | ||
| 2485 | .mode_screen = LCD_SCREEN_SX_N(640) | | ||
| 2486 | LCD_SCREEN_SY_N(480), | ||
| 2487 | .mode_horztiming = LCD_HORZTIMING_HPW_N(96) | | ||
| 2488 | LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(51), | ||
| 2489 | .mode_verttiming = LCD_VERTTIMING_VPW_N(2) | | ||
| 2490 | LCD_VERTTIMING_VND1_N(11) | LCD_VERTTIMING_VND2_N(32), | ||
| 2491 | .mode_clkcontrol = 0x00000000, /* /4=24Mhz */ | ||
| 2492 | .mode_pwmdiv = 0x8000063f, | ||
| 2493 | .mode_pwmhi = 0x03400000, | ||
| 2494 | .mode_outmask = 0x00fcfcfc, | ||
| 2495 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 2496 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 2497 | .mode_backlight = 0x00000000, | ||
| 2498 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 2499 | .device_init = board_au1200fb_panel_init, | ||
| 2500 | .device_shutdown = board_au1200fb_panel_shutdown, | ||
| 2501 | 640, 480, | ||
| 2502 | 640, 480, | ||
| 2503 | }, | ||
| 2504 | |||
| 2505 | [7] = { /* Sharp 320x240 TFT */ | ||
| 2506 | .name = "Sharp_320x240_TFT", | ||
| 2507 | .monspecs = { | ||
| 2508 | .modedb = NULL, | ||
| 2509 | .modedb_len = 0, | ||
| 2510 | .hfmin = 12500, | ||
| 2511 | .hfmax = 20000, | ||
| 2512 | .vfmin = 38, | ||
| 2513 | .vfmax = 81, | ||
| 2514 | .dclkmin = 4500000, | ||
| 2515 | .dclkmax = 6800000, | ||
| 2516 | .input = FB_DISP_RGB, | ||
| 2517 | }, | ||
| 2518 | .mode_screen = LCD_SCREEN_SX_N(320) | | ||
| 2519 | LCD_SCREEN_SY_N(240), | ||
| 2520 | .mode_horztiming = LCD_HORZTIMING_HPW_N(60) | | ||
| 2521 | LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(2), | ||
| 2522 | .mode_verttiming = LCD_VERTTIMING_VPW_N(2) | | ||
| 2523 | LCD_VERTTIMING_VND1_N(2) | LCD_VERTTIMING_VND2_N(5), | ||
| 2524 | .mode_clkcontrol = LCD_CLKCONTROL_PCD_N(7), /*16=6Mhz*/ | ||
| 2525 | .mode_pwmdiv = 0x8000063f, | ||
| 2526 | .mode_pwmhi = 0x03400000, | ||
| 2527 | .mode_outmask = 0x00fcfcfc, | ||
| 2528 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 2529 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 2530 | .mode_backlight = 0x00000000, | ||
| 2531 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 2532 | .device_init = board_au1200fb_panel_init, | ||
| 2533 | .device_shutdown = board_au1200fb_panel_shutdown, | ||
| 2534 | 320, 320, | ||
| 2535 | 240, 240, | ||
| 2536 | }, | ||
| 2537 | |||
| 2538 | [8] = { /* Toppoly TD070WGCB2 7" 856x480 TFT */ | ||
| 2539 | .name = "Toppoly_TD070WGCB2", | ||
| 2540 | .monspecs = { | ||
| 2541 | .modedb = NULL, | ||
| 2542 | .modedb_len = 0, | ||
| 2543 | .hfmin = 30000, | ||
| 2544 | .hfmax = 70000, | ||
| 2545 | .vfmin = 60, | ||
| 2546 | .vfmax = 60, | ||
| 2547 | .dclkmin = 6000000, | ||
| 2548 | .dclkmax = 28000000, | ||
| 2549 | .input = FB_DISP_RGB, | ||
| 2550 | }, | ||
| 2551 | .mode_screen = LCD_SCREEN_SX_N(856) | | ||
| 2552 | LCD_SCREEN_SY_N(480), | ||
| 2553 | .mode_horztiming = LCD_HORZTIMING_HND2_N(43) | | ||
| 2554 | LCD_HORZTIMING_HND1_N(43) | LCD_HORZTIMING_HPW_N(114), | ||
| 2555 | .mode_verttiming = LCD_VERTTIMING_VND2_N(20) | | ||
| 2556 | LCD_VERTTIMING_VND1_N(21) | LCD_VERTTIMING_VPW_N(4), | ||
| 2557 | .mode_clkcontrol = 0x00020001, /* /4=24Mhz */ | ||
| 2558 | .mode_pwmdiv = 0x8000063f, | ||
| 2559 | .mode_pwmhi = 0x03400000, | ||
| 2560 | .mode_outmask = 0x00fcfcfc, | ||
| 2561 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 2562 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 2563 | .mode_backlight = 0x00000000, | ||
| 2564 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 2565 | .device_init = board_au1200fb_panel_init, | ||
| 2566 | .device_shutdown = board_au1200fb_panel_shutdown, | ||
| 2567 | 856, 856, | ||
| 2568 | 480, 480, | ||
| 2569 | }, | ||
| 2570 | }; | ||
| 2571 | |||
| 2572 | #define NUM_PANELS (ARRAY_SIZE(known_lcd_panels)) | ||
| 2573 | |||
| 2574 | /********************************************************************/ | ||
| 2575 | |||
| 2576 | #ifdef CONFIG_PM | ||
| 2577 | static int set_brightness(unsigned int brightness) | ||
| 2578 | { | ||
| 2579 | unsigned int hi1, divider; | ||
| 2580 | |||
| 2581 | /* limit brightness pwm duty to >= 30/1600 */ | ||
| 2582 | if (brightness < 30) { | ||
| 2583 | brightness = 30; | ||
| 2584 | } | ||
| 2585 | divider = (lcd->pwmdiv & 0x3FFFF) + 1; | ||
| 2586 | hi1 = (lcd->pwmhi >> 16) + 1; | ||
| 2587 | hi1 = (((brightness & 0xFF) + 1) * divider >> 8); | ||
| 2588 | lcd->pwmhi &= 0xFFFF; | ||
| 2589 | lcd->pwmhi |= (hi1 << 16); | ||
| 2590 | |||
| 2591 | return brightness; | ||
| 2592 | } | ||
| 2593 | #endif /* CONFIG_PM */ | ||
| 2594 | |||
| 2595 | static int winbpp (unsigned int winctrl1) | ||
| 2596 | { | ||
| 2597 | int bits = 0; | ||
| 2598 | |||
| 2599 | /* how many bits are needed for each pixel format */ | ||
| 2600 | switch (winctrl1 & LCD_WINCTRL1_FRM) { | ||
| 2601 | case LCD_WINCTRL1_FRM_1BPP: | ||
| 2602 | bits = 1; | ||
| 2603 | break; | ||
| 2604 | case LCD_WINCTRL1_FRM_2BPP: | ||
| 2605 | bits = 2; | ||
| 2606 | break; | ||
| 2607 | case LCD_WINCTRL1_FRM_4BPP: | ||
| 2608 | bits = 4; | ||
| 2609 | break; | ||
| 2610 | case LCD_WINCTRL1_FRM_8BPP: | ||
| 2611 | bits = 8; | ||
| 2612 | break; | ||
| 2613 | case LCD_WINCTRL1_FRM_12BPP: | ||
| 2614 | case LCD_WINCTRL1_FRM_16BPP655: | ||
| 2615 | case LCD_WINCTRL1_FRM_16BPP565: | ||
| 2616 | case LCD_WINCTRL1_FRM_16BPP556: | ||
| 2617 | case LCD_WINCTRL1_FRM_16BPPI1555: | ||
| 2618 | case LCD_WINCTRL1_FRM_16BPPI5551: | ||
| 2619 | case LCD_WINCTRL1_FRM_16BPPA1555: | ||
| 2620 | case LCD_WINCTRL1_FRM_16BPPA5551: | ||
| 2621 | bits = 16; | ||
| 2622 | break; | ||
| 2623 | case LCD_WINCTRL1_FRM_24BPP: | ||
| 2624 | case LCD_WINCTRL1_FRM_32BPP: | ||
| 2625 | bits = 32; | ||
| 2626 | break; | ||
| 2627 | } | ||
| 2628 | |||
| 2629 | return bits; | ||
| 2630 | } | ||
| 2631 | |||
| 2632 | static int fbinfo2index (struct fb_info *fb_info) | ||
| 2633 | { | ||
| 2634 | int i; | ||
| 2635 | |||
| 2636 | for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i) { | ||
| 2637 | if (fb_info == (struct fb_info *)(&_au1200fb_devices[i].fb_info)) | ||
| 2638 | return i; | ||
| 2639 | } | ||
| 2640 | printk("au1200fb: ERROR: fbinfo2index failed!\n"); | ||
| 2641 | return -1; | ||
| 2642 | } | ||
| 2643 | |||
| 2644 | static int au1200_setlocation (struct au1200fb_device *fbdev, int plane, | ||
| 2645 | int xpos, int ypos) | ||
| 2646 | { | ||
| 2647 | uint32 winctrl0, winctrl1, winenable, fb_offset = 0; | ||
| 2648 | int xsz, ysz; | ||
| 2649 | |||
| 2650 | /* FIX!!! NOT CHECKING FOR COMPLETE OFFSCREEN YET */ | ||
| 2651 | |||
| 2652 | winctrl0 = lcd->window[plane].winctrl0; | ||
| 2653 | winctrl1 = lcd->window[plane].winctrl1; | ||
| 2654 | winctrl0 &= (LCD_WINCTRL0_A | LCD_WINCTRL0_AEN); | ||
| 2655 | winctrl1 &= ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY); | ||
| 2656 | |||
| 2657 | /* Check for off-screen adjustments */ | ||
| 2658 | xsz = win->w[plane].xres; | ||
| 2659 | ysz = win->w[plane].yres; | ||
| 2660 | if ((xpos + win->w[plane].xres) > panel->Xres) { | ||
| 2661 | /* Off-screen to the right */ | ||
| 2662 | xsz = panel->Xres - xpos; /* off by 1 ??? */ | ||
| 2663 | /*printk("off screen right\n");*/ | ||
| 2664 | } | ||
| 2665 | |||
| 2666 | if ((ypos + win->w[plane].yres) > panel->Yres) { | ||
| 2667 | /* Off-screen to the bottom */ | ||
| 2668 | ysz = panel->Yres - ypos; /* off by 1 ??? */ | ||
| 2669 | /*printk("off screen bottom\n");*/ | ||
| 2670 | } | ||
| 2671 | |||
| 2672 | if (xpos < 0) { | ||
| 2673 | /* Off-screen to the left */ | ||
| 2674 | xsz = win->w[plane].xres + xpos; | ||
| 2675 | fb_offset += (((0 - xpos) * winbpp(lcd->window[plane].winctrl1))/8); | ||
| 2676 | xpos = 0; | ||
| 2677 | /*printk("off screen left\n");*/ | ||
| 2678 | } | ||
| 2679 | |||
| 2680 | if (ypos < 0) { | ||
| 2681 | /* Off-screen to the top */ | ||
| 2682 | ysz = win->w[plane].yres + ypos; | ||
| 2683 | /* fixme: fb_offset += ((0-ypos)*fb_pars[plane].line_length); */ | ||
| 2684 | ypos = 0; | ||
| 2685 | /*printk("off screen top\n");*/ | ||
| 2686 | } | ||
| 2687 | |||
| 2688 | /* record settings */ | ||
| 2689 | win->w[plane].xpos = xpos; | ||
| 2690 | win->w[plane].ypos = ypos; | ||
| 2691 | |||
| 2692 | xsz -= 1; | ||
| 2693 | ysz -= 1; | ||
| 2694 | winctrl0 |= (xpos << 21); | ||
| 2695 | winctrl0 |= (ypos << 10); | ||
| 2696 | winctrl1 |= (xsz << 11); | ||
| 2697 | winctrl1 |= (ysz << 0); | ||
| 2698 | |||
| 2699 | /* Disable the window while making changes, then restore WINEN */ | ||
| 2700 | winenable = lcd->winenable & (1 << plane); | ||
| 2701 | au_sync(); | ||
| 2702 | lcd->winenable &= ~(1 << plane); | ||
| 2703 | lcd->window[plane].winctrl0 = winctrl0; | ||
| 2704 | lcd->window[plane].winctrl1 = winctrl1; | ||
| 2705 | lcd->window[plane].winbuf0 = | ||
| 2706 | lcd->window[plane].winbuf1 = fbdev->fb_phys; | ||
| 2707 | lcd->window[plane].winbufctrl = 0; /* select winbuf0 */ | ||
| 2708 | lcd->winenable |= winenable; | ||
| 2709 | au_sync(); | ||
| 2710 | |||
| 2711 | return 0; | ||
| 2712 | } | ||
| 2713 | |||
| 2714 | static void au1200_setpanel (struct panel_settings *newpanel) | ||
| 2715 | { | ||
| 2716 | /* | ||
| 2717 | * Perform global setup/init of LCD controller | ||
| 2718 | */ | ||
| 2719 | uint32 winenable; | ||
| 2720 | |||
| 2721 | /* Make sure all windows disabled */ | ||
| 2722 | winenable = lcd->winenable; | ||
| 2723 | lcd->winenable = 0; | ||
| 2724 | au_sync(); | ||
| 2725 | /* | ||
| 2726 | * Ensure everything is disabled before reconfiguring | ||
| 2727 | */ | ||
| 2728 | if (lcd->screen & LCD_SCREEN_SEN) { | ||
| 2729 | /* Wait for vertical sync period */ | ||
| 2730 | lcd->intstatus = LCD_INT_SS; | ||
| 2731 | while ((lcd->intstatus & LCD_INT_SS) == 0) { | ||
| 2732 | au_sync(); | ||
| 2733 | } | ||
| 2734 | |||
| 2735 | lcd->screen &= ~LCD_SCREEN_SEN; /*disable the controller*/ | ||
| 2736 | |||
| 2737 | do { | ||
| 2738 | lcd->intstatus = lcd->intstatus; /*clear interrupts*/ | ||
| 2739 | au_sync(); | ||
| 2740 | /*wait for controller to shut down*/ | ||
| 2741 | } while ((lcd->intstatus & LCD_INT_SD) == 0); | ||
| 2742 | |||
| 2743 | /* Call shutdown of current panel (if up) */ | ||
| 2744 | /* this must occur last, because if an external clock is driving | ||
| 2745 | the controller, the clock cannot be turned off before first | ||
| 2746 | shutting down the controller. | ||
| 2747 | */ | ||
| 2748 | if (panel->device_shutdown != NULL) | ||
| 2749 | panel->device_shutdown(); | ||
| 2750 | } | ||
| 2751 | |||
| 2752 | /* Newpanel == NULL indicates a shutdown operation only */ | ||
| 2753 | if (newpanel == NULL) | ||
| 2754 | return; | ||
| 2755 | |||
| 2756 | panel = newpanel; | ||
| 2757 | |||
| 2758 | printk("Panel(%s), %dx%d\n", panel->name, panel->Xres, panel->Yres); | ||
| 2759 | |||
| 2760 | /* | ||
| 2761 | * Setup clocking if internal LCD clock source (assumes sys_auxpll valid) | ||
| 2762 | */ | ||
| 2763 | if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT)) | ||
| 2764 | { | ||
| 2765 | uint32 sys_clksrc; | ||
| 2766 | au_writel(panel->mode_auxpll, SYS_AUXPLL); | ||
| 2767 | sys_clksrc = au_readl(SYS_CLKSRC) & ~0x0000001f; | ||
| 2768 | sys_clksrc |= panel->mode_toyclksrc; | ||
| 2769 | au_writel(sys_clksrc, SYS_CLKSRC); | ||
| 2770 | } | ||
| 2771 | |||
| 2772 | /* | ||
| 2773 | * Configure panel timings | ||
| 2774 | */ | ||
| 2775 | lcd->screen = panel->mode_screen; | ||
| 2776 | lcd->horztiming = panel->mode_horztiming; | ||
| 2777 | lcd->verttiming = panel->mode_verttiming; | ||
| 2778 | lcd->clkcontrol = panel->mode_clkcontrol; | ||
| 2779 | lcd->pwmdiv = panel->mode_pwmdiv; | ||
| 2780 | lcd->pwmhi = panel->mode_pwmhi; | ||
| 2781 | lcd->outmask = panel->mode_outmask; | ||
| 2782 | lcd->fifoctrl = panel->mode_fifoctrl; | ||
| 2783 | au_sync(); | ||
| 2784 | |||
| 2785 | /* fixme: Check window settings to make sure still valid | ||
| 2786 | * for new geometry */ | ||
| 2787 | #if 0 | ||
| 2788 | au1200_setlocation(fbdev, 0, win->w[0].xpos, win->w[0].ypos); | ||
| 2789 | au1200_setlocation(fbdev, 1, win->w[1].xpos, win->w[1].ypos); | ||
| 2790 | au1200_setlocation(fbdev, 2, win->w[2].xpos, win->w[2].ypos); | ||
| 2791 | au1200_setlocation(fbdev, 3, win->w[3].xpos, win->w[3].ypos); | ||
| 2792 | #endif | ||
| 2793 | lcd->winenable = winenable; | ||
| 2794 | |||
| 2795 | /* | ||
| 2796 | * Re-enable screen now that it is configured | ||
| 2797 | */ | ||
| 2798 | lcd->screen |= LCD_SCREEN_SEN; | ||
| 2799 | au_sync(); | ||
| 2800 | |||
| 2801 | /* Call init of panel */ | ||
| 2802 | if (panel->device_init != NULL) panel->device_init(); | ||
| 2803 | |||
| 2804 | /* FIX!!!! not appropriate on panel change!!! Global setup/init */ | ||
| 2805 | lcd->intenable = 0; | ||
| 2806 | lcd->intstatus = ~0; | ||
| 2807 | lcd->backcolor = win->mode_backcolor; | ||
| 2808 | |||
| 2809 | /* Setup Color Key - FIX!!! */ | ||
| 2810 | lcd->colorkey = win->mode_colorkey; | ||
| 2811 | lcd->colorkeymsk = win->mode_colorkeymsk; | ||
| 2812 | |||
| 2813 | /* Setup HWCursor - FIX!!! Need to support this eventually */ | ||
| 2814 | lcd->hwc.cursorctrl = 0; | ||
| 2815 | lcd->hwc.cursorpos = 0; | ||
| 2816 | lcd->hwc.cursorcolor0 = 0; | ||
| 2817 | lcd->hwc.cursorcolor1 = 0; | ||
| 2818 | lcd->hwc.cursorcolor2 = 0; | ||
| 2819 | lcd->hwc.cursorcolor3 = 0; | ||
| 2820 | |||
| 2821 | |||
| 2822 | #if 0 | ||
| 2823 | #define D(X) printk("%25s: %08X\n", #X, X) | ||
| 2824 | D(lcd->screen); | ||
| 2825 | D(lcd->horztiming); | ||
| 2826 | D(lcd->verttiming); | ||
| 2827 | D(lcd->clkcontrol); | ||
| 2828 | D(lcd->pwmdiv); | ||
| 2829 | D(lcd->pwmhi); | ||
| 2830 | D(lcd->outmask); | ||
| 2831 | D(lcd->fifoctrl); | ||
| 2832 | D(lcd->window[0].winctrl0); | ||
| 2833 | D(lcd->window[0].winctrl1); | ||
| 2834 | D(lcd->window[0].winctrl2); | ||
| 2835 | D(lcd->window[0].winbuf0); | ||
| 2836 | D(lcd->window[0].winbuf1); | ||
| 2837 | D(lcd->window[0].winbufctrl); | ||
| 2838 | D(lcd->window[1].winctrl0); | ||
| 2839 | D(lcd->window[1].winctrl1); | ||
| 2840 | D(lcd->window[1].winctrl2); | ||
| 2841 | D(lcd->window[1].winbuf0); | ||
| 2842 | D(lcd->window[1].winbuf1); | ||
| 2843 | D(lcd->window[1].winbufctrl); | ||
| 2844 | D(lcd->window[2].winctrl0); | ||
| 2845 | D(lcd->window[2].winctrl1); | ||
| 2846 | D(lcd->window[2].winctrl2); | ||
| 2847 | D(lcd->window[2].winbuf0); | ||
| 2848 | D(lcd->window[2].winbuf1); | ||
| 2849 | D(lcd->window[2].winbufctrl); | ||
| 2850 | D(lcd->window[3].winctrl0); | ||
| 2851 | D(lcd->window[3].winctrl1); | ||
| 2852 | D(lcd->window[3].winctrl2); | ||
| 2853 | D(lcd->window[3].winbuf0); | ||
| 2854 | D(lcd->window[3].winbuf1); | ||
| 2855 | D(lcd->window[3].winbufctrl); | ||
| 2856 | D(lcd->winenable); | ||
| 2857 | D(lcd->intenable); | ||
| 2858 | D(lcd->intstatus); | ||
| 2859 | D(lcd->backcolor); | ||
| 2860 | D(lcd->winenable); | ||
| 2861 | D(lcd->colorkey); | ||
| 2862 | D(lcd->colorkeymsk); | ||
| 2863 | D(lcd->hwc.cursorctrl); | ||
| 2864 | D(lcd->hwc.cursorpos); | ||
| 2865 | D(lcd->hwc.cursorcolor0); | ||
| 2866 | D(lcd->hwc.cursorcolor1); | ||
| 2867 | D(lcd->hwc.cursorcolor2); | ||
| 2868 | D(lcd->hwc.cursorcolor3); | ||
| 2869 | #endif | ||
| 2870 | } | ||
| 2871 | |||
| 2872 | static void au1200_setmode(struct au1200fb_device *fbdev) | ||
| 2873 | { | ||
| 2874 | int plane = fbdev->plane; | ||
| 2875 | /* Window/plane setup */ | ||
| 2876 | lcd->window[plane].winctrl1 = ( 0 | ||
| 2877 | | LCD_WINCTRL1_PRI_N(plane) | ||
| 2878 | | win->w[plane].mode_winctrl1 /* FRM,CCO,PO,PIPE */ | ||
| 2879 | ) ; | ||
| 2880 | |||
| 2881 | au1200_setlocation(fbdev, plane, win->w[plane].xpos, win->w[plane].ypos); | ||
| 2882 | |||
| 2883 | lcd->window[plane].winctrl2 = ( 0 | ||
| 2884 | | LCD_WINCTRL2_CKMODE_00 | ||
| 2885 | | LCD_WINCTRL2_DBM | ||
| 2886 | | LCD_WINCTRL2_BX_N( fbdev->fb_info.fix.line_length) | ||
| 2887 | | LCD_WINCTRL2_SCX_1 | ||
| 2888 | | LCD_WINCTRL2_SCY_1 | ||
| 2889 | ) ; | ||
| 2890 | lcd->winenable |= win->w[plane].mode_winenable; | ||
| 2891 | au_sync(); | ||
| 2892 | } | ||
| 2893 | |||
| 2894 | |||
| 2895 | /* Inline helpers */ | ||
| 2896 | |||
| 2897 | /*#define panel_is_dual(panel) ((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/ | ||
| 2898 | /*#define panel_is_active(panel)((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/ | ||
| 2899 | |||
| 2900 | #define panel_is_color(panel) ((panel->mode_screen & LCD_SCREEN_PT) <= LCD_SCREEN_PT_CDSTN) | ||
| 2901 | |||
| 2902 | /* Bitfields format supported by the controller. */ | ||
| 2903 | static struct fb_bitfield rgb_bitfields[][4] = { | ||
| 2904 | /* Red, Green, Blue, Transp */ | ||
| 2905 | [LCD_WINCTRL1_FRM_16BPP655 >> 25] = | ||
| 2906 | { { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, | ||
| 2907 | |||
| 2908 | [LCD_WINCTRL1_FRM_16BPP565 >> 25] = | ||
| 2909 | { { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, | ||
| 2910 | |||
| 2911 | [LCD_WINCTRL1_FRM_16BPP556 >> 25] = | ||
| 2912 | { { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } }, | ||
| 2913 | |||
| 2914 | [LCD_WINCTRL1_FRM_16BPPI1555 >> 25] = | ||
| 2915 | { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, | ||
| 2916 | |||
| 2917 | [LCD_WINCTRL1_FRM_16BPPI5551 >> 25] = | ||
| 2918 | { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 0, 0 } }, | ||
| 2919 | |||
| 2920 | [LCD_WINCTRL1_FRM_16BPPA1555 >> 25] = | ||
| 2921 | { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } }, | ||
| 2922 | |||
| 2923 | [LCD_WINCTRL1_FRM_16BPPA5551 >> 25] = | ||
| 2924 | { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } }, | ||
| 2925 | |||
| 2926 | [LCD_WINCTRL1_FRM_24BPP >> 25] = | ||
| 2927 | { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 0, 0, 0 } }, | ||
| 2928 | |||
| 2929 | [LCD_WINCTRL1_FRM_32BPP >> 25] = | ||
| 2930 | { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 0, 0 } }, | ||
| 2931 | }; | ||
| 2932 | |||
| 2933 | /*-------------------------------------------------------------------------*/ | ||
| 2934 | |||
| 2935 | /* Helpers */ | ||
| 2936 | |||
| 2937 | static void au1200fb_update_fbinfo(struct fb_info *fbi) | ||
| 2938 | { | ||
| 2939 | /* FIX!!!! This also needs to take the window pixel format into account!!! */ | ||
| 2940 | |||
| 2941 | /* Update var-dependent FB info */ | ||
| 2942 | if (panel_is_color(panel)) { | ||
| 2943 | if (fbi->var.bits_per_pixel <= 8) { | ||
| 2944 | /* palettized */ | ||
| 2945 | fbi->fix.visual = FB_VISUAL_PSEUDOCOLOR; | ||
| 2946 | fbi->fix.line_length = fbi->var.xres_virtual / | ||
| 2947 | (8/fbi->var.bits_per_pixel); | ||
| 2948 | } else { | ||
| 2949 | /* non-palettized */ | ||
| 2950 | fbi->fix.visual = FB_VISUAL_TRUECOLOR; | ||
| 2951 | fbi->fix.line_length = fbi->var.xres_virtual * (fbi->var.bits_per_pixel / 8); | ||
| 2952 | } | ||
| 2953 | } else { | ||
| 2954 | /* mono FIX!!! mono 8 and 4 bits */ | ||
| 2955 | fbi->fix.visual = FB_VISUAL_MONO10; | ||
| 2956 | fbi->fix.line_length = fbi->var.xres_virtual / 8; | ||
| 2957 | } | ||
| 2958 | |||
| 2959 | fbi->screen_size = fbi->fix.line_length * fbi->var.yres_virtual; | ||
| 2960 | print_dbg("line length: %d\n", fbi->fix.line_length); | ||
| 2961 | print_dbg("bits_per_pixel: %d\n", fbi->var.bits_per_pixel); | ||
| 2962 | } | ||
| 2963 | |||
| 2964 | /*-------------------------------------------------------------------------*/ | ||
| 2965 | |||
| 2966 | /* AU1200 framebuffer driver */ | ||
| 2967 | |||
| 2968 | /* fb_check_var | ||
| 2969 | * Validate var settings with hardware restrictions and modify it if necessary | ||
| 2970 | */ | ||
| 2971 | static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, | ||
| 2972 | struct fb_info *fbi) | ||
| 2973 | { | ||
| 2974 | struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; | ||
| 2975 | u32 pixclock; | ||
| 2976 | int screen_size, plane; | ||
| 2977 | |||
| 2978 | plane = fbdev->plane; | ||
| 2979 | |||
| 2980 | /* Make sure that the mode respect all LCD controller and | ||
| 2981 | * panel restrictions. */ | ||
| 2982 | var->xres = win->w[plane].xres; | ||
| 2983 | var->yres = win->w[plane].yres; | ||
| 2984 | |||
| 2985 | /* No need for virtual resolution support */ | ||
| 2986 | var->xres_virtual = var->xres; | ||
| 2987 | var->yres_virtual = var->yres; | ||
| 2988 | |||
| 2989 | var->bits_per_pixel = winbpp(win->w[plane].mode_winctrl1); | ||
| 2990 | |||
| 2991 | screen_size = var->xres_virtual * var->yres_virtual; | ||
| 2992 | if (var->bits_per_pixel > 8) screen_size *= (var->bits_per_pixel / 8); | ||
| 2993 | else screen_size /= (8/var->bits_per_pixel); | ||
| 2994 | |||
| 2995 | if (fbdev->fb_len < screen_size) | ||
| 2996 | return -EINVAL; /* Virtual screen is to big, abort */ | ||
| 2997 | |||
| 2998 | /* FIX!!!! what are the implicaitons of ignoring this for windows ??? */ | ||
| 2999 | /* The max LCD clock is fixed to 48MHz (value of AUX_CLK). The pixel | ||
| 3000 | * clock can only be obtain by dividing this value by an even integer. | ||
| 3001 | * Fallback to a slower pixel clock if necessary. */ | ||
| 3002 | pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin); | ||
| 3003 | pixclock = min(pixclock, min(fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2)); | ||
| 3004 | |||
| 3005 | if (AU1200_LCD_MAX_CLK % pixclock) { | ||
| 3006 | int diff = AU1200_LCD_MAX_CLK % pixclock; | ||
| 3007 | pixclock -= diff; | ||
| 3008 | } | ||
| 3009 | |||
| 3010 | var->pixclock = KHZ2PICOS(pixclock/1000); | ||
| 3011 | #if 0 | ||
| 3012 | if (!panel_is_active(panel)) { | ||
| 3013 | int pcd = AU1200_LCD_MAX_CLK / (pixclock * 2) - 1; | ||
| 3014 | |||
| 3015 | if (!panel_is_color(panel) | ||
| 3016 | && (panel->control_base & LCD_CONTROL_MPI) && (pcd < 3)) { | ||
| 3017 | /* STN 8bit mono panel support is up to 6MHz pixclock */ | ||
| 3018 | var->pixclock = KHZ2PICOS(6000); | ||
| 3019 | } else if (!pcd) { | ||
| 3020 | /* Other STN panel support is up to 12MHz */ | ||
| 3021 | var->pixclock = KHZ2PICOS(12000); | ||
| 3022 | } | ||
| 3023 | } | ||
| 3024 | #endif | ||
| 3025 | /* Set bitfield accordingly */ | ||
| 3026 | switch (var->bits_per_pixel) { | ||
| 3027 | case 16: | ||
| 3028 | { | ||
| 3029 | /* 16bpp True color. | ||
| 3030 | * These must be set to MATCH WINCTRL[FORM] */ | ||
| 3031 | int idx; | ||
| 3032 | idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25; | ||
| 3033 | var->red = rgb_bitfields[idx][0]; | ||
| 3034 | var->green = rgb_bitfields[idx][1]; | ||
| 3035 | var->blue = rgb_bitfields[idx][2]; | ||
| 3036 | var->transp = rgb_bitfields[idx][3]; | ||
| 3037 | break; | ||
| 3038 | } | ||
| 3039 | |||
| 3040 | case 32: | ||
| 3041 | { | ||
| 3042 | /* 32bpp True color. | ||
| 3043 | * These must be set to MATCH WINCTRL[FORM] */ | ||
| 3044 | int idx; | ||
| 3045 | idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25; | ||
| 3046 | var->red = rgb_bitfields[idx][0]; | ||
| 3047 | var->green = rgb_bitfields[idx][1]; | ||
| 3048 | var->blue = rgb_bitfields[idx][2]; | ||
| 3049 | var->transp = rgb_bitfields[idx][3]; | ||
| 3050 | break; | ||
| 3051 | } | ||
| 3052 | default: | ||
| 3053 | print_dbg("Unsupported depth %dbpp", var->bits_per_pixel); | ||
| 3054 | return -EINVAL; | ||
| 3055 | } | ||
| 3056 | |||
| 3057 | return 0; | ||
| 3058 | } | ||
| 3059 | |||
| 3060 | /* fb_set_par | ||
| 3061 | * Set hardware with var settings. This will enable the controller with a | ||
| 3062 | * specific mode, normally validated with the fb_check_var method | ||
| 3063 | */ | ||
| 3064 | static int au1200fb_fb_set_par(struct fb_info *fbi) | ||
| 3065 | { | ||
| 3066 | struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; | ||
| 3067 | |||
| 3068 | au1200fb_update_fbinfo(fbi); | ||
| 3069 | au1200_setmode(fbdev); | ||
| 3070 | |||
| 3071 | return 0; | ||
| 3072 | } | ||
| 3073 | |||
| 3074 | /* fb_setcolreg | ||
| 3075 | * Set color in LCD palette. | ||
| 3076 | */ | ||
| 3077 | static int au1200fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green, | ||
| 3078 | unsigned blue, unsigned transp, struct fb_info *fbi) | ||
| 3079 | { | ||
| 3080 | volatile u32 *palette = lcd->palette; | ||
| 3081 | u32 value; | ||
| 3082 | |||
| 3083 | if (regno > (AU1200_LCD_NBR_PALETTE_ENTRIES - 1)) | ||
| 3084 | return -EINVAL; | ||
| 3085 | |||
| 3086 | if (fbi->var.grayscale) { | ||
| 3087 | /* Convert color to grayscale */ | ||
| 3088 | red = green = blue = | ||
| 3089 | (19595 * red + 38470 * green + 7471 * blue) >> 16; | ||
| 3090 | } | ||
| 3091 | |||
| 3092 | if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) { | ||
| 3093 | /* Place color in the pseudopalette */ | ||
| 3094 | if (regno > 16) | ||
| 3095 | return -EINVAL; | ||
| 3096 | |||
| 3097 | palette = (u32*) fbi->pseudo_palette; | ||
| 3098 | |||
| 3099 | red >>= (16 - fbi->var.red.length); | ||
| 3100 | green >>= (16 - fbi->var.green.length); | ||
| 3101 | blue >>= (16 - fbi->var.blue.length); | ||
| 3102 | |||
| 3103 | value = (red << fbi->var.red.offset) | | ||
| 3104 | (green << fbi->var.green.offset)| | ||
| 3105 | (blue << fbi->var.blue.offset); | ||
| 3106 | value &= 0xFFFF; | ||
| 3107 | |||
| 3108 | } else if (1 /*FIX!!! panel_is_active(fbdev->panel)*/) { | ||
| 3109 | /* COLOR TFT PALLETTIZED (use RGB 565) */ | ||
| 3110 | value = (red & 0xF800)|((green >> 5) & | ||
| 3111 | 0x07E0)|((blue >> 11) & 0x001F); | ||
| 3112 | value &= 0xFFFF; | ||
| 3113 | |||
| 3114 | } else if (0 /*panel_is_color(fbdev->panel)*/) { | ||
| 3115 | /* COLOR STN MODE */ | ||
| 3116 | value = 0x1234; | ||
| 3117 | value &= 0xFFF; | ||
| 3118 | } else { | ||
| 3119 | /* MONOCHROME MODE */ | ||
| 3120 | value = (green >> 12) & 0x000F; | ||
| 3121 | value &= 0xF; | ||
| 3122 | } | ||
| 3123 | |||
| 3124 | palette[regno] = value; | ||
| 3125 | |||
| 3126 | return 0; | ||
| 3127 | } | ||
| 3128 | |||
| 3129 | /* fb_blank | ||
| 3130 | * Blank the screen. Depending on the mode, the screen will be | ||
| 3131 | * activated with the backlight color, or desactivated | ||
| 3132 | */ | ||
| 3133 | static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi) | ||
| 3134 | { | ||
| 3135 | /* Short-circuit screen blanking */ | ||
| 3136 | if (noblanking) | ||
| 3137 | return 0; | ||
| 3138 | |||
| 3139 | switch (blank_mode) { | ||
| 3140 | |||
| 3141 | case FB_BLANK_UNBLANK: | ||
| 3142 | case FB_BLANK_NORMAL: | ||
| 3143 | /* printk("turn on panel\n"); */ | ||
| 3144 | au1200_setpanel(panel); | ||
| 3145 | break; | ||
| 3146 | case FB_BLANK_VSYNC_SUSPEND: | ||
| 3147 | case FB_BLANK_HSYNC_SUSPEND: | ||
| 3148 | case FB_BLANK_POWERDOWN: | ||
| 3149 | /* printk("turn off panel\n"); */ | ||
| 3150 | au1200_setpanel(NULL); | ||
| 3151 | break; | ||
| 3152 | default: | ||
| 3153 | break; | ||
| 3154 | |||
| 3155 | } | ||
| 3156 | |||
| 3157 | /* FB_BLANK_NORMAL is a soft blank */ | ||
| 3158 | return (blank_mode == FB_BLANK_NORMAL) ? -EINVAL : 0; | ||
| 3159 | } | ||
| 3160 | |||
| 3161 | /* fb_mmap | ||
| 3162 | * Map video memory in user space. We don't use the generic fb_mmap | ||
| 3163 | * method mainly to allow the use of the TLB streaming flag (CCA=6) | ||
| 3164 | */ | ||
| 3165 | static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) | ||
| 3166 | |||
| 3167 | { | ||
| 3168 | unsigned int len; | ||
| 3169 | unsigned long start=0, off; | ||
| 3170 | struct au1200fb_device *fbdev = (struct au1200fb_device *) info; | ||
| 3171 | |||
| 3172 | #ifdef CONFIG_PM | ||
| 3173 | au1xxx_pm_access(LCD_pm_dev); | ||
| 3174 | #endif | ||
| 3175 | |||
| 3176 | if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { | ||
| 3177 | return -EINVAL; | ||
| 3178 | } | ||
| 3179 | |||
| 3180 | start = fbdev->fb_phys & PAGE_MASK; | ||
| 3181 | len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len); | ||
| 3182 | |||
| 3183 | off = vma->vm_pgoff << PAGE_SHIFT; | ||
| 3184 | |||
| 3185 | if ((vma->vm_end - vma->vm_start + off) > len) { | ||
| 3186 | return -EINVAL; | ||
| 3187 | } | ||
| 3188 | |||
| 3189 | off += start; | ||
| 3190 | vma->vm_pgoff = off >> PAGE_SHIFT; | ||
| 3191 | |||
| 3192 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||
| 3193 | pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; /* CCA=7 */ | ||
| 3194 | |||
| 3195 | vma->vm_flags |= VM_IO; | ||
| 3196 | |||
| 3197 | return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, | ||
| 3198 | vma->vm_end - vma->vm_start, | ||
| 3199 | vma->vm_page_prot); | ||
| 3200 | |||
| 3201 | return 0; | ||
| 3202 | } | ||
| 3203 | |||
| 3204 | static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) | ||
| 3205 | { | ||
| 3206 | |||
| 3207 | unsigned int hi1, divider; | ||
| 3208 | |||
| 3209 | /* SCREEN_SIZE: user cannot reset size, must switch panel choice */ | ||
| 3210 | |||
| 3211 | if (pdata->flags & SCREEN_BACKCOLOR) | ||
| 3212 | lcd->backcolor = pdata->backcolor; | ||
| 3213 | |||
| 3214 | if (pdata->flags & SCREEN_BRIGHTNESS) { | ||
| 3215 | |||
| 3216 | // limit brightness pwm duty to >= 30/1600 | ||
| 3217 | if (pdata->brightness < 30) { | ||
| 3218 | pdata->brightness = 30; | ||
| 3219 | } | ||
| 3220 | divider = (lcd->pwmdiv & 0x3FFFF) + 1; | ||
| 3221 | hi1 = (lcd->pwmhi >> 16) + 1; | ||
| 3222 | hi1 = (((pdata->brightness & 0xFF)+1) * divider >> 8); | ||
| 3223 | lcd->pwmhi &= 0xFFFF; | ||
| 3224 | lcd->pwmhi |= (hi1 << 16); | ||
| 3225 | } | ||
| 3226 | |||
| 3227 | if (pdata->flags & SCREEN_COLORKEY) | ||
| 3228 | lcd->colorkey = pdata->colorkey; | ||
| 3229 | |||
| 3230 | if (pdata->flags & SCREEN_MASK) | ||
| 3231 | lcd->colorkeymsk = pdata->mask; | ||
| 3232 | au_sync(); | ||
| 3233 | } | ||
| 3234 | |||
| 3235 | static void get_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) | ||
| 3236 | { | ||
| 3237 | unsigned int hi1, divider; | ||
| 3238 | |||
| 3239 | pdata->xsize = ((lcd->screen & LCD_SCREEN_SX) >> 19) + 1; | ||
| 3240 | pdata->ysize = ((lcd->screen & LCD_SCREEN_SY) >> 8) + 1; | ||
| 3241 | |||
| 3242 | pdata->backcolor = lcd->backcolor; | ||
| 3243 | pdata->colorkey = lcd->colorkey; | ||
| 3244 | pdata->mask = lcd->colorkeymsk; | ||
| 3245 | |||
| 3246 | // brightness | ||
| 3247 | hi1 = (lcd->pwmhi >> 16) + 1; | ||
| 3248 | divider = (lcd->pwmdiv & 0x3FFFF) + 1; | ||
| 3249 | pdata->brightness = ((hi1 << 8) / divider) - 1; | ||
| 3250 | au_sync(); | ||
| 3251 | } | ||
| 3252 | |||
| 3253 | static void set_window(unsigned int plane, | ||
| 3254 | struct au1200_lcd_window_regs_t *pdata) | ||
| 3255 | { | ||
| 3256 | unsigned int val, bpp; | ||
| 3257 | |||
| 3258 | /* Window control register 0 */ | ||
| 3259 | if (pdata->flags & WIN_POSITION) { | ||
| 3260 | val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_OX | | ||
| 3261 | LCD_WINCTRL0_OY); | ||
| 3262 | val |= ((pdata->xpos << 21) & LCD_WINCTRL0_OX); | ||
| 3263 | val |= ((pdata->ypos << 10) & LCD_WINCTRL0_OY); | ||
| 3264 | lcd->window[plane].winctrl0 = val; | ||
| 3265 | } | ||
| 3266 | if (pdata->flags & WIN_ALPHA_COLOR) { | ||
| 3267 | val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_A); | ||
| 3268 | val |= ((pdata->alpha_color << 2) & LCD_WINCTRL0_A); | ||
| 3269 | lcd->window[plane].winctrl0 = val; | ||
| 3270 | } | ||
| 3271 | if (pdata->flags & WIN_ALPHA_MODE) { | ||
| 3272 | val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_AEN); | ||
| 3273 | val |= ((pdata->alpha_mode << 1) & LCD_WINCTRL0_AEN); | ||
| 3274 | lcd->window[plane].winctrl0 = val; | ||
| 3275 | } | ||
| 3276 | |||
| 3277 | /* Window control register 1 */ | ||
| 3278 | if (pdata->flags & WIN_PRIORITY) { | ||
| 3279 | val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PRI); | ||
| 3280 | val |= ((pdata->priority << 30) & LCD_WINCTRL1_PRI); | ||
| 3281 | lcd->window[plane].winctrl1 = val; | ||
| 3282 | } | ||
| 3283 | if (pdata->flags & WIN_CHANNEL) { | ||
| 3284 | val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PIPE); | ||
| 3285 | val |= ((pdata->channel << 29) & LCD_WINCTRL1_PIPE); | ||
| 3286 | lcd->window[plane].winctrl1 = val; | ||
| 3287 | } | ||
| 3288 | if (pdata->flags & WIN_BUFFER_FORMAT) { | ||
| 3289 | val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_FRM); | ||
| 3290 | val |= ((pdata->buffer_format << 25) & LCD_WINCTRL1_FRM); | ||
| 3291 | lcd->window[plane].winctrl1 = val; | ||
| 3292 | } | ||
| 3293 | if (pdata->flags & WIN_COLOR_ORDER) { | ||
| 3294 | val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_CCO); | ||
| 3295 | val |= ((pdata->color_order << 24) & LCD_WINCTRL1_CCO); | ||
| 3296 | lcd->window[plane].winctrl1 = val; | ||
| 3297 | } | ||
| 3298 | if (pdata->flags & WIN_PIXEL_ORDER) { | ||
| 3299 | val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PO); | ||
| 3300 | val |= ((pdata->pixel_order << 22) & LCD_WINCTRL1_PO); | ||
| 3301 | lcd->window[plane].winctrl1 = val; | ||
| 3302 | } | ||
| 3303 | if (pdata->flags & WIN_SIZE) { | ||
| 3304 | val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_SZX | | ||
| 3305 | LCD_WINCTRL1_SZY); | ||
| 3306 | val |= (((pdata->xsize << 11) - 1) & LCD_WINCTRL1_SZX); | ||
| 3307 | val |= (((pdata->ysize) - 1) & LCD_WINCTRL1_SZY); | ||
| 3308 | lcd->window[plane].winctrl1 = val; | ||
| 3309 | /* program buffer line width */ | ||
| 3310 | bpp = winbpp(val) / 8; | ||
| 3311 | val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_BX); | ||
| 3312 | val |= (((pdata->xsize * bpp) << 8) & LCD_WINCTRL2_BX); | ||
| 3313 | lcd->window[plane].winctrl2 = val; | ||
| 3314 | } | ||
| 3315 | |||
| 3316 | /* Window control register 2 */ | ||
| 3317 | if (pdata->flags & WIN_COLORKEY_MODE) { | ||
| 3318 | val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_CKMODE); | ||
| 3319 | val |= ((pdata->colorkey_mode << 24) & LCD_WINCTRL2_CKMODE); | ||
| 3320 | lcd->window[plane].winctrl2 = val; | ||
| 3321 | } | ||
| 3322 | if (pdata->flags & WIN_DOUBLE_BUFFER_MODE) { | ||
| 3323 | val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_DBM); | ||
| 3324 | val |= ((pdata->double_buffer_mode << 23) & LCD_WINCTRL2_DBM); | ||
| 3325 | lcd->window[plane].winctrl2 = val; | ||
| 3326 | } | ||
| 3327 | if (pdata->flags & WIN_RAM_ARRAY_MODE) { | ||
| 3328 | val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_RAM); | ||
| 3329 | val |= ((pdata->ram_array_mode << 21) & LCD_WINCTRL2_RAM); | ||
| 3330 | lcd->window[plane].winctrl2 = val; | ||
| 3331 | } | ||
| 3332 | |||
| 3333 | /* Buffer line width programmed with WIN_SIZE */ | ||
| 3334 | |||
| 3335 | if (pdata->flags & WIN_BUFFER_SCALE) { | ||
| 3336 | val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_SCX | | ||
| 3337 | LCD_WINCTRL2_SCY); | ||
| 3338 | val |= ((pdata->xsize << 11) & LCD_WINCTRL2_SCX); | ||
| 3339 | val |= ((pdata->ysize) & LCD_WINCTRL2_SCY); | ||
| 3340 | lcd->window[plane].winctrl2 = val; | ||
| 3341 | } | ||
| 3342 | |||
| 3343 | if (pdata->flags & WIN_ENABLE) { | ||
| 3344 | val = lcd->winenable; | ||
| 3345 | val &= ~(1<<plane); | ||
| 3346 | val |= (pdata->enable & 1) << plane; | ||
| 3347 | lcd->winenable = val; | ||
| 3348 | } | ||
| 3349 | au_sync(); | ||
| 3350 | } | ||
| 3351 | |||
| 3352 | static void get_window(unsigned int plane, | ||
| 3353 | struct au1200_lcd_window_regs_t *pdata) | ||
| 3354 | { | ||
| 3355 | /* Window control register 0 */ | ||
| 3356 | pdata->xpos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OX) >> 21; | ||
| 3357 | pdata->ypos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OY) >> 10; | ||
| 3358 | pdata->alpha_color = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_A) >> 2; | ||
| 3359 | pdata->alpha_mode = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_AEN) >> 1; | ||
| 3360 | |||
| 3361 | /* Window control register 1 */ | ||
| 3362 | pdata->priority = (lcd->window[plane].winctrl1& LCD_WINCTRL1_PRI) >> 30; | ||
| 3363 | pdata->channel = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PIPE) >> 29; | ||
| 3364 | pdata->buffer_format = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_FRM) >> 25; | ||
| 3365 | pdata->color_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_CCO) >> 24; | ||
| 3366 | pdata->pixel_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PO) >> 22; | ||
| 3367 | pdata->xsize = ((lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZX) >> 11) + 1; | ||
| 3368 | pdata->ysize = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZY) + 1; | ||
| 3369 | |||
| 3370 | /* Window control register 2 */ | ||
| 3371 | pdata->colorkey_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_CKMODE) >> 24; | ||
| 3372 | pdata->double_buffer_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_DBM) >> 23; | ||
| 3373 | pdata->ram_array_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_RAM) >> 21; | ||
| 3374 | |||
| 3375 | pdata->enable = (lcd->winenable >> plane) & 1; | ||
| 3376 | au_sync(); | ||
| 3377 | } | ||
| 3378 | |||
| 3379 | static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd, | ||
| 3380 | unsigned long arg) | ||
| 3381 | { | ||
| 3382 | int plane; | ||
| 3383 | int val; | ||
| 3384 | |||
| 3385 | #ifdef CONFIG_PM | ||
| 3386 | au1xxx_pm_access(LCD_pm_dev); | ||
| 3387 | #endif | ||
| 3388 | |||
| 3389 | plane = fbinfo2index(info); | ||
| 3390 | print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane); | ||
| 3391 | |||
| 3392 | if (cmd == AU1200_LCD_FB_IOCTL) { | ||
| 3393 | struct au1200_lcd_iodata_t iodata; | ||
| 3394 | |||
| 3395 | if (copy_from_user(&iodata, (void __user *) arg, sizeof(iodata))) | ||
| 3396 | return -EFAULT; | ||
| 3397 | |||
| 3398 | print_dbg("FB IOCTL called\n"); | ||
| 3399 | |||
| 3400 | switch (iodata.subcmd) { | ||
| 3401 | case AU1200_LCD_SET_SCREEN: | ||
| 3402 | print_dbg("AU1200_LCD_SET_SCREEN\n"); | ||
| 3403 | set_global(cmd, &iodata.global); | ||
| 3404 | break; | ||
| 3405 | |||
| 3406 | case AU1200_LCD_GET_SCREEN: | ||
| 3407 | print_dbg("AU1200_LCD_GET_SCREEN\n"); | ||
| 3408 | get_global(cmd, &iodata.global); | ||
| 3409 | break; | ||
| 3410 | |||
| 3411 | case AU1200_LCD_SET_WINDOW: | ||
| 3412 | print_dbg("AU1200_LCD_SET_WINDOW\n"); | ||
| 3413 | set_window(plane, &iodata.window); | ||
| 3414 | break; | ||
| 3415 | |||
| 3416 | case AU1200_LCD_GET_WINDOW: | ||
| 3417 | print_dbg("AU1200_LCD_GET_WINDOW\n"); | ||
| 3418 | get_window(plane, &iodata.window); | ||
| 3419 | break; | ||
| 3420 | |||
| 3421 | case AU1200_LCD_SET_PANEL: | ||
| 3422 | print_dbg("AU1200_LCD_SET_PANEL\n"); | ||
| 3423 | if ((iodata.global.panel_choice >= 0) && | ||
| 3424 | (iodata.global.panel_choice < | ||
| 3425 | NUM_PANELS)) | ||
| 3426 | { | ||
| 3427 | struct panel_settings *newpanel; | ||
| 3428 | panel_index = iodata.global.panel_choice; | ||
| 3429 | newpanel = &known_lcd_panels[panel_index]; | ||
| 3430 | au1200_setpanel(newpanel); | ||
| 3431 | } | ||
| 3432 | break; | ||
| 3433 | |||
| 3434 | case AU1200_LCD_GET_PANEL: | ||
| 3435 | print_dbg("AU1200_LCD_GET_PANEL\n"); | ||
| 3436 | iodata.global.panel_choice = panel_index; | ||
| 3437 | break; | ||
| 3438 | |||
| 3439 | default: | ||
| 3440 | return -EINVAL; | ||
| 3441 | } | ||
| 3442 | |||
| 3443 | val = copy_to_user((void __user *) arg, &iodata, sizeof(iodata)); | ||
| 3444 | if (val) { | ||
| 3445 | print_dbg("error: could not copy %d bytes\n", val); | ||
| 3446 | return -EFAULT; | ||
| 3447 | } | ||
| 3448 | } | ||
| 3449 | |||
| 3450 | return 0; | ||
| 3451 | } | ||
| 3452 | |||
| 3453 | |||
| 3454 | static struct fb_ops au1200fb_fb_ops = { | ||
| 3455 | .owner = THIS_MODULE, | ||
| 3456 | .fb_check_var = au1200fb_fb_check_var, | ||
| 3457 | .fb_set_par = au1200fb_fb_set_par, | ||
| 3458 | .fb_setcolreg = au1200fb_fb_setcolreg, | ||
| 3459 | .fb_blank = au1200fb_fb_blank, | ||
| 3460 | .fb_fillrect = cfb_fillrect, | ||
| 3461 | .fb_copyarea = cfb_copyarea, | ||
| 3462 | .fb_imageblit = cfb_imageblit, | ||
| 3463 | .fb_sync = NULL, | ||
| 3464 | .fb_ioctl = au1200fb_ioctl, | ||
| 3465 | .fb_mmap = au1200fb_fb_mmap, | ||
| 3466 | }; | ||
| 3467 | |||
| 3468 | /*-------------------------------------------------------------------------*/ | ||
| 3469 | |||
| 3470 | static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id, struct pt_regs *regs) | ||
| 3471 | { | ||
| 3472 | /* Nothing to do for now, just clear any pending interrupt */ | ||
| 3473 | lcd->intstatus = lcd->intstatus; | ||
| 3474 | au_sync(); | ||
| 3475 | |||
| 3476 | return IRQ_HANDLED; | ||
| 3477 | } | ||
| 3478 | |||
| 3479 | /*-------------------------------------------------------------------------*/ | ||
| 3480 | |||
| 3481 | /* AU1200 LCD device probe helpers */ | ||
| 3482 | |||
| 3483 | static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) | ||
| 3484 | { | ||
| 3485 | struct fb_info *fbi = &fbdev->fb_info; | ||
| 3486 | int bpp; | ||
| 3487 | |||
| 3488 | memset(fbi, 0, sizeof(struct fb_info)); | ||
| 3489 | fbi->fbops = &au1200fb_fb_ops; | ||
| 3490 | |||
| 3491 | bpp = winbpp(win->w[fbdev->plane].mode_winctrl1); | ||
| 3492 | |||
| 3493 | /* Copy monitor specs from panel data */ | ||
| 3494 | /* fixme: we're setting up LCD controller windows, so these dont give a | ||
| 3495 | damn as to what the monitor specs are (the panel itself does, but that | ||
| 3496 | isnt done here...so maybe need a generic catchall monitor setting??? */ | ||
| 3497 | memcpy(&fbi->monspecs, &panel->monspecs, sizeof(struct fb_monspecs)); | ||
| 3498 | |||
| 3499 | /* We first try the user mode passed in argument. If that failed, | ||
| 3500 | * or if no one has been specified, we default to the first mode of the | ||
| 3501 | * panel list. Note that after this call, var data will be set */ | ||
| 3502 | if (!fb_find_mode(&fbi->var, | ||
| 3503 | fbi, | ||
| 3504 | NULL, /* drv_info.opt_mode, */ | ||
| 3505 | fbi->monspecs.modedb, | ||
| 3506 | fbi->monspecs.modedb_len, | ||
| 3507 | fbi->monspecs.modedb, | ||
| 3508 | bpp)) { | ||
| 3509 | |||
| 3510 | print_err("Cannot find valid mode for panel %s", panel->name); | ||
| 3511 | return -EFAULT; | ||
| 3512 | } | ||
| 3513 | |||
| 3514 | fbi->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL); | ||
| 3515 | if (!fbi->pseudo_palette) { | ||
| 3516 | return -ENOMEM; | ||
| 3517 | } | ||
| 3518 | memset(fbi->pseudo_palette, 0, sizeof(u32) * 16); | ||
| 3519 | |||
| 3520 | if (fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0) < 0) { | ||
| 3521 | print_err("Fail to allocate colormap (%d entries)", | ||
| 3522 | AU1200_LCD_NBR_PALETTE_ENTRIES); | ||
| 3523 | kfree(fbi->pseudo_palette); | ||
| 3524 | return -EFAULT; | ||
| 3525 | } | ||
| 3526 | |||
| 3527 | strncpy(fbi->fix.id, "AU1200", sizeof(fbi->fix.id)); | ||
| 3528 | fbi->fix.smem_start = fbdev->fb_phys; | ||
| 3529 | fbi->fix.smem_len = fbdev->fb_len; | ||
| 3530 | fbi->fix.type = FB_TYPE_PACKED_PIXELS; | ||
| 3531 | fbi->fix.xpanstep = 0; | ||
| 3532 | fbi->fix.ypanstep = 0; | ||
| 3533 | fbi->fix.mmio_start = 0; | ||
| 3534 | fbi->fix.mmio_len = 0; | ||
| 3535 | fbi->fix.accel = FB_ACCEL_NONE; | ||
| 3536 | |||
| 3537 | fbi->screen_base = (char __iomem *) fbdev->fb_mem; | ||
| 3538 | |||
| 3539 | au1200fb_update_fbinfo(fbi); | ||
| 3540 | |||
| 3541 | return 0; | ||
| 3542 | } | ||
| 3543 | |||
| 3544 | /*-------------------------------------------------------------------------*/ | ||
| 3545 | |||
| 3546 | /* AU1200 LCD controller device driver */ | ||
| 3547 | |||
| 3548 | static int au1200fb_drv_probe(struct device *dev) | ||
| 3549 | { | ||
| 3550 | struct au1200fb_device *fbdev; | ||
| 3551 | unsigned long page; | ||
| 3552 | int bpp, plane, ret; | ||
| 3553 | |||
| 3554 | if (!dev) | ||
| 3555 | return -EINVAL; | ||
| 3556 | |||
| 3557 | for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { | ||
| 3558 | bpp = winbpp(win->w[plane].mode_winctrl1); | ||
| 3559 | if (win->w[plane].xres == 0) | ||
| 3560 | win->w[plane].xres = panel->Xres; | ||
| 3561 | if (win->w[plane].yres == 0) | ||
| 3562 | win->w[plane].yres = panel->Yres; | ||
| 3563 | |||
| 3564 | fbdev = &_au1200fb_devices[plane]; | ||
| 3565 | memset(fbdev, 0, sizeof(struct au1200fb_device)); | ||
| 3566 | fbdev->plane = plane; | ||
| 3567 | |||
| 3568 | /* Allocate the framebuffer to the maximum screen size */ | ||
| 3569 | fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8; | ||
| 3570 | |||
| 3571 | fbdev->fb_mem = dma_alloc_noncoherent(dev, | ||
| 3572 | PAGE_ALIGN(fbdev->fb_len), | ||
| 3573 | &fbdev->fb_phys, GFP_KERNEL); | ||
| 3574 | if (!fbdev->fb_mem) { | ||
| 3575 | print_err("fail to allocate frambuffer (size: %dK))", | ||
| 3576 | fbdev->fb_len / 1024); | ||
| 3577 | return -ENOMEM; | ||
| 3578 | } | ||
| 3579 | |||
| 3580 | /* | ||
| 3581 | * Set page reserved so that mmap will work. This is necessary | ||
| 3582 | * since we'll be remapping normal memory. | ||
| 3583 | */ | ||
| 3584 | for (page = (unsigned long)fbdev->fb_phys; | ||
| 3585 | page < PAGE_ALIGN((unsigned long)fbdev->fb_phys + | ||
| 3586 | fbdev->fb_len); | ||
| 3587 | page += PAGE_SIZE) { | ||
| 3588 | SetPageReserved(pfn_to_page(page >> PAGE_SHIFT)); /* LCD DMA is NOT coherent on Au1200 */ | ||
| 3589 | } | ||
| 3590 | print_dbg("Framebuffer memory map at %p", fbdev->fb_mem); | ||
| 3591 | print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024); | ||
| 3592 | |||
| 3593 | /* Init FB data */ | ||
| 3594 | if ((ret = au1200fb_init_fbinfo(fbdev)) < 0) | ||
| 3595 | goto failed; | ||
| 3596 | |||
| 3597 | /* Register new framebuffer */ | ||
| 3598 | if ((ret = register_framebuffer(&fbdev->fb_info)) < 0) { | ||
| 3599 | print_err("cannot register new framebuffer"); | ||
| 3600 | goto failed; | ||
| 3601 | } | ||
| 3602 | |||
| 3603 | au1200fb_fb_set_par(&fbdev->fb_info); | ||
| 3604 | |||
| 3605 | #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) | ||
| 3606 | if (plane == 0) | ||
| 3607 | if (fb_prepare_logo(&fbdev->fb_info, FB_ROTATE_UR)) { | ||
| 3608 | /* Start display and show logo on boot */ | ||
| 3609 | fb_set_cmap(&fbdev->fb_info.cmap, | ||
| 3610 | &fbdev->fb_info); | ||
| 3611 | |||
| 3612 | fb_show_logo(&fbdev->fb_info, FB_ROTATE_UR); | ||
| 3613 | } | ||
| 3614 | #endif | ||
| 3615 | } | ||
| 3616 | |||
| 3617 | /* Now hook interrupt too */ | ||
| 3618 | if ((ret = request_irq(AU1200_LCD_INT, au1200fb_handle_irq, | ||
| 3619 | SA_INTERRUPT | SA_SHIRQ, "lcd", (void *)dev)) < 0) { | ||
| 3620 | print_err("fail to request interrupt line %d (err: %d)", | ||
| 3621 | AU1200_LCD_INT, ret); | ||
| 3622 | goto failed; | ||
| 3623 | } | ||
| 3624 | |||
| 3625 | return 0; | ||
| 3626 | |||
| 3627 | failed: | ||
| 3628 | /* NOTE: This only does the current plane/window that failed; others are still active */ | ||
| 3629 | if (fbdev->fb_mem) | ||
| 3630 | dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len), | ||
| 3631 | fbdev->fb_mem, fbdev->fb_phys); | ||
| 3632 | if (fbdev->fb_info.cmap.len != 0) | ||
| 3633 | fb_dealloc_cmap(&fbdev->fb_info.cmap); | ||
| 3634 | if (fbdev->fb_info.pseudo_palette) | ||
| 3635 | kfree(fbdev->fb_info.pseudo_palette); | ||
| 3636 | if (plane == 0) | ||
| 3637 | free_irq(AU1200_LCD_INT, (void*)dev); | ||
| 3638 | return ret; | ||
| 3639 | } | ||
| 3640 | |||
| 3641 | static int au1200fb_drv_remove(struct device *dev) | ||
| 3642 | { | ||
| 3643 | struct au1200fb_device *fbdev; | ||
| 3644 | int plane; | ||
| 3645 | |||
| 3646 | if (!dev) | ||
| 3647 | return -ENODEV; | ||
| 3648 | |||
| 3649 | /* Turn off the panel */ | ||
| 3650 | au1200_setpanel(NULL); | ||
| 3651 | |||
| 3652 | for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) | ||
| 3653 | { | ||
| 3654 | fbdev = &_au1200fb_devices[plane]; | ||
| 3655 | |||
| 3656 | /* Clean up all probe data */ | ||
| 3657 | unregister_framebuffer(&fbdev->fb_info); | ||
| 3658 | if (fbdev->fb_mem) | ||
| 3659 | dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len), | ||
| 3660 | fbdev->fb_mem, fbdev->fb_phys); | ||
| 3661 | if (fbdev->fb_info.cmap.len != 0) | ||
| 3662 | fb_dealloc_cmap(&fbdev->fb_info.cmap); | ||
| 3663 | if (fbdev->fb_info.pseudo_palette) | ||
| 3664 | kfree(fbdev->fb_info.pseudo_palette); | ||
| 3665 | } | ||
| 3666 | |||
| 3667 | free_irq(AU1200_LCD_INT, (void *)dev); | ||
| 3668 | |||
| 3669 | return 0; | ||
| 3670 | } | ||
| 3671 | |||
| 3672 | #ifdef CONFIG_PM | ||
| 3673 | static int au1200fb_drv_suspend(struct device *dev, u32 state, u32 level) | ||
| 3674 | { | ||
| 3675 | /* TODO */ | ||
| 3676 | return 0; | ||
| 3677 | } | ||
| 3678 | |||
| 3679 | static int au1200fb_drv_resume(struct device *dev, u32 level) | ||
| 3680 | { | ||
| 3681 | /* TODO */ | ||
| 3682 | return 0; | ||
| 3683 | } | ||
| 3684 | #endif /* CONFIG_PM */ | ||
| 3685 | |||
| 3686 | static struct device_driver au1200fb_driver = { | ||
| 3687 | .name = "au1200-lcd", | ||
| 3688 | .bus = &platform_bus_type, | ||
| 3689 | .probe = au1200fb_drv_probe, | ||
| 3690 | .remove = au1200fb_drv_remove, | ||
| 3691 | #ifdef CONFIG_PM | ||
| 3692 | .suspend = au1200fb_drv_suspend, | ||
| 3693 | .resume = au1200fb_drv_resume, | ||
| 3694 | #endif | ||
| 3695 | }; | ||
| 3696 | |||
| 3697 | /*-------------------------------------------------------------------------*/ | ||
| 3698 | |||
| 3699 | /* Kernel driver */ | ||
| 3700 | |||
| 3701 | static void au1200fb_setup(void) | ||
| 3702 | { | ||
| 3703 | char* options = NULL; | ||
| 3704 | char* this_opt; | ||
| 3705 | int num_panels = ARRAY_SIZE(known_lcd_panels); | ||
| 3706 | int panel_idx = -1; | ||
| 3707 | |||
| 3708 | fb_get_options(DRIVER_NAME, &options); | ||
| 3709 | |||
| 3710 | if (options) { | ||
| 3711 | while ((this_opt = strsep(&options,",")) != NULL) { | ||
| 3712 | /* Panel option - can be panel name, | ||
| 3713 | * "bs" for board-switch, or number/index */ | ||
| 3714 | if (!strncmp(this_opt, "panel:", 6)) { | ||
| 3715 | int i; | ||
| 3716 | long int li; | ||
| 3717 | char *endptr; | ||
| 3718 | this_opt += 6; | ||
| 3719 | /* First check for index, which allows | ||
| 3720 | * to short circuit this mess */ | ||
| 3721 | li = simple_strtol(this_opt, &endptr, 0); | ||
| 3722 | if (*endptr == '\0') { | ||
| 3723 | panel_idx = (int)li; | ||
| 3724 | } | ||
| 3725 | else if (strcmp(this_opt, "bs") == 0) { | ||
| 3726 | extern int board_au1200fb_panel(void); | ||
| 3727 | panel_idx = board_au1200fb_panel(); | ||
| 3728 | } | ||
| 3729 | |||
| 3730 | else | ||
| 3731 | for (i = 0; i < num_panels; i++) { | ||
| 3732 | if (!strcmp(this_opt, known_lcd_panels[i].name)) { | ||
| 3733 | panel_idx = i; | ||
| 3734 | break; | ||
| 3735 | } | ||
| 3736 | } | ||
| 3737 | |||
| 3738 | if ((panel_idx < 0) || (panel_idx >= num_panels)) { | ||
| 3739 | print_warn("Panel %s not supported!", this_opt); | ||
| 3740 | } | ||
| 3741 | else | ||
| 3742 | panel_index = panel_idx; | ||
| 3743 | } | ||
| 3744 | |||
| 3745 | else if (strncmp(this_opt, "nohwcursor", 10) == 0) { | ||
| 3746 | nohwcursor = 1; | ||
| 3747 | } | ||
| 3748 | |||
| 3749 | /* Unsupported option */ | ||
| 3750 | else { | ||
| 3751 | print_warn("Unsupported option \"%s\"", this_opt); | ||
| 3752 | } | ||
| 3753 | } | ||
| 3754 | } | ||
| 3755 | } | ||
| 3756 | |||
| 3757 | #ifdef CONFIG_PM | ||
| 3758 | static int au1200fb_pm_callback(au1xxx_power_dev_t *dev, | ||
| 3759 | au1xxx_request_t request, void *data) { | ||
| 3760 | int retval = -1; | ||
| 3761 | unsigned int d = 0; | ||
| 3762 | unsigned int brightness = 0; | ||
| 3763 | |||
| 3764 | if (request == AU1XXX_PM_SLEEP) { | ||
| 3765 | board_au1200fb_panel_shutdown(); | ||
| 3766 | } | ||
| 3767 | else if (request == AU1XXX_PM_WAKEUP) { | ||
| 3768 | if(dev->prev_state == SLEEP_STATE) | ||
| 3769 | { | ||
| 3770 | int plane; | ||
| 3771 | au1200_setpanel(panel); | ||
| 3772 | for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { | ||
| 3773 | struct au1200fb_device *fbdev; | ||
| 3774 | fbdev = &_au1200fb_devices[plane]; | ||
| 3775 | au1200fb_fb_set_par(&fbdev->fb_info); | ||
| 3776 | } | ||
| 3777 | } | ||
| 3778 | |||
| 3779 | d = *((unsigned int*)data); | ||
| 3780 | if(d <=10) brightness = 26; | ||
| 3781 | else if(d<=20) brightness = 51; | ||
| 3782 | else if(d<=30) brightness = 77; | ||
| 3783 | else if(d<=40) brightness = 102; | ||
| 3784 | else if(d<=50) brightness = 128; | ||
| 3785 | else if(d<=60) brightness = 153; | ||
| 3786 | else if(d<=70) brightness = 179; | ||
| 3787 | else if(d<=80) brightness = 204; | ||
| 3788 | else if(d<=90) brightness = 230; | ||
| 3789 | else brightness = 255; | ||
| 3790 | set_brightness(brightness); | ||
| 3791 | } else if (request == AU1XXX_PM_GETSTATUS) { | ||
| 3792 | return dev->cur_state; | ||
| 3793 | } else if (request == AU1XXX_PM_ACCESS) { | ||
| 3794 | if (dev->cur_state != SLEEP_STATE) | ||
| 3795 | return retval; | ||
| 3796 | else { | ||
| 3797 | au1200_setpanel(panel); | ||
| 3798 | } | ||
| 3799 | } else if (request == AU1XXX_PM_IDLE) { | ||
| 3800 | } else if (request == AU1XXX_PM_CLEANUP) { | ||
| 3801 | } | ||
| 3802 | |||
| 3803 | return retval; | ||
| 3804 | } | ||
| 3805 | #endif | ||
| 3806 | |||
| 3807 | static int __init au1200fb_init(void) | ||
| 3808 | { | ||
| 3809 | print_info("" DRIVER_DESC ""); | ||
| 3810 | |||
| 3811 | /* Setup driver with options */ | ||
| 3812 | au1200fb_setup(); | ||
| 3813 | |||
| 3814 | /* Point to the panel selected */ | ||
| 3815 | panel = &known_lcd_panels[panel_index]; | ||
| 3816 | win = &windows[window_index]; | ||
| 3817 | |||
| 3818 | printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name); | ||
| 3819 | printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name); | ||
| 3820 | |||
| 3821 | /* Kickstart the panel, the framebuffers/windows come soon enough */ | ||
| 3822 | au1200_setpanel(panel); | ||
| 3823 | |||
| 3824 | #ifdef CONFIG_PM | ||
| 3825 | LCD_pm_dev = new_au1xxx_power_device("LCD", &au1200fb_pm_callback, NULL); | ||
| 3826 | if ( LCD_pm_dev == NULL) | ||
| 3827 | printk(KERN_INFO "Unable to create a power management device entry for the au1200fb.\n"); | ||
| 3828 | else | ||
| 3829 | printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n"); | ||
| 3830 | #endif | ||
| 3831 | |||
| 3832 | return driver_register(&au1200fb_driver); | ||
| 3833 | } | ||
| 3834 | |||
| 3835 | static void __exit au1200fb_cleanup(void) | ||
| 3836 | { | ||
| 3837 | driver_unregister(&au1200fb_driver); | ||
| 3838 | } | ||
| 3839 | |||
| 3840 | module_init(au1200fb_init); | ||
| 3841 | module_exit(au1200fb_cleanup); | ||
| 3842 | |||
| 3843 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 3844 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index b72b05250a9d..34e07399756b 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c | |||
| @@ -305,94 +305,6 @@ static ssize_t show_stride(struct class_device *class_device, char *buf) | |||
| 305 | return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->fix.line_length); | 305 | return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->fix.line_length); |
| 306 | } | 306 | } |
| 307 | 307 | ||
| 308 | /* Format for cmap is "%02x%c%4x%4x%4x\n" */ | ||
| 309 | /* %02x entry %c transp %4x red %4x blue %4x green \n */ | ||
| 310 | /* 256 rows at 16 chars equals 4096, the normal page size */ | ||
| 311 | /* the code will automatically adjust for different page sizes */ | ||
| 312 | static ssize_t store_cmap(struct class_device *class_device, const char *buf, | ||
| 313 | size_t count) | ||
| 314 | { | ||
| 315 | struct fb_info *fb_info = class_get_devdata(class_device); | ||
| 316 | int rc, i, start, length, transp = 0; | ||
| 317 | |||
| 318 | if ((count > PAGE_SIZE) || ((count % 16) != 0)) | ||
| 319 | return -EINVAL; | ||
| 320 | |||
| 321 | if (!fb_info->fbops->fb_setcolreg && !fb_info->fbops->fb_setcmap) | ||
| 322 | return -EINVAL; | ||
| 323 | |||
| 324 | sscanf(buf, "%02x", &start); | ||
| 325 | length = count / 16; | ||
| 326 | |||
| 327 | for (i = 0; i < length; i++) | ||
| 328 | if (buf[i * 16 + 2] != ' ') | ||
| 329 | transp = 1; | ||
| 330 | |||
| 331 | /* If we can batch, do it */ | ||
| 332 | if (fb_info->fbops->fb_setcmap && length > 1) { | ||
| 333 | struct fb_cmap umap; | ||
| 334 | |||
| 335 | memset(&umap, 0, sizeof(umap)); | ||
| 336 | if ((rc = fb_alloc_cmap(&umap, length, transp))) | ||
| 337 | return rc; | ||
| 338 | |||
| 339 | umap.start = start; | ||
| 340 | for (i = 0; i < length; i++) { | ||
| 341 | sscanf(&buf[i * 16 + 3], "%4hx", &umap.red[i]); | ||
| 342 | sscanf(&buf[i * 16 + 7], "%4hx", &umap.blue[i]); | ||
| 343 | sscanf(&buf[i * 16 + 11], "%4hx", &umap.green[i]); | ||
| 344 | if (transp) | ||
| 345 | umap.transp[i] = (buf[i * 16 + 2] != ' '); | ||
| 346 | } | ||
| 347 | rc = fb_info->fbops->fb_setcmap(&umap, fb_info); | ||
| 348 | fb_copy_cmap(&umap, &fb_info->cmap); | ||
| 349 | fb_dealloc_cmap(&umap); | ||
| 350 | |||
| 351 | return rc ?: count; | ||
| 352 | } | ||
| 353 | for (i = 0; i < length; i++) { | ||
| 354 | u16 red, blue, green, tsp; | ||
| 355 | |||
| 356 | sscanf(&buf[i * 16 + 3], "%4hx", &red); | ||
| 357 | sscanf(&buf[i * 16 + 7], "%4hx", &blue); | ||
| 358 | sscanf(&buf[i * 16 + 11], "%4hx", &green); | ||
| 359 | tsp = (buf[i * 16 + 2] != ' '); | ||
| 360 | if ((rc = fb_info->fbops->fb_setcolreg(start++, | ||
| 361 | red, green, blue, tsp, fb_info))) | ||
| 362 | return rc; | ||
| 363 | |||
| 364 | fb_info->cmap.red[i] = red; | ||
| 365 | fb_info->cmap.blue[i] = blue; | ||
| 366 | fb_info->cmap.green[i] = green; | ||
| 367 | if (transp) | ||
| 368 | fb_info->cmap.transp[i] = tsp; | ||
| 369 | } | ||
| 370 | return count; | ||
| 371 | } | ||
| 372 | |||
| 373 | static ssize_t show_cmap(struct class_device *class_device, char *buf) | ||
| 374 | { | ||
| 375 | struct fb_info *fb_info = class_get_devdata(class_device); | ||
| 376 | unsigned int i; | ||
| 377 | |||
| 378 | if (!fb_info->cmap.red || !fb_info->cmap.blue || | ||
| 379 | !fb_info->cmap.green) | ||
| 380 | return -EINVAL; | ||
| 381 | |||
| 382 | if (fb_info->cmap.len > PAGE_SIZE / 16) | ||
| 383 | return -EINVAL; | ||
| 384 | |||
| 385 | /* don't mess with the format, the buffer is PAGE_SIZE */ | ||
| 386 | /* 256 entries at 16 chars per line equals 4096 = PAGE_SIZE */ | ||
| 387 | for (i = 0; i < fb_info->cmap.len; i++) { | ||
| 388 | snprintf(&buf[ i * 16], PAGE_SIZE - i * 16, "%02x%c%4x%4x%4x\n", i + fb_info->cmap.start, | ||
| 389 | ((fb_info->cmap.transp && fb_info->cmap.transp[i]) ? '*' : ' '), | ||
| 390 | fb_info->cmap.red[i], fb_info->cmap.blue[i], | ||
| 391 | fb_info->cmap.green[i]); | ||
| 392 | } | ||
| 393 | return 16 * fb_info->cmap.len; | ||
| 394 | } | ||
| 395 | |||
| 396 | static ssize_t store_blank(struct class_device *class_device, const char * buf, | 308 | static ssize_t store_blank(struct class_device *class_device, const char * buf, |
| 397 | size_t count) | 309 | size_t count) |
| 398 | { | 310 | { |
| @@ -502,10 +414,12 @@ static ssize_t show_fbstate(struct class_device *class_device, char *buf) | |||
| 502 | return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state); | 414 | return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state); |
| 503 | } | 415 | } |
| 504 | 416 | ||
| 417 | /* When cmap is added back in it should be a binary attribute | ||
| 418 | * not a text one. Consideration should also be given to converting | ||
| 419 | * fbdev to use configfs instead of sysfs */ | ||
| 505 | static struct class_device_attribute class_device_attrs[] = { | 420 | static struct class_device_attribute class_device_attrs[] = { |
| 506 | __ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp), | 421 | __ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp), |
| 507 | __ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank), | 422 | __ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank), |
| 508 | __ATTR(color_map, S_IRUGO|S_IWUSR, show_cmap, store_cmap), | ||
| 509 | __ATTR(console, S_IRUGO|S_IWUSR, show_console, store_console), | 423 | __ATTR(console, S_IRUGO|S_IWUSR, show_console, store_console), |
| 510 | __ATTR(cursor, S_IRUGO|S_IWUSR, show_cursor, store_cursor), | 424 | __ATTR(cursor, S_IRUGO|S_IWUSR, show_cursor, store_cursor), |
| 511 | __ATTR(mode, S_IRUGO|S_IWUSR, show_mode, store_mode), | 425 | __ATTR(mode, S_IRUGO|S_IWUSR, show_mode, store_mode), |
