diff options
Diffstat (limited to 'drivers')
99 files changed, 1909 insertions, 2773 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/base/topology.c b/drivers/base/topology.c index 915810f6237e..8c52421cbc54 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c | |||
@@ -107,7 +107,7 @@ static int __cpuinit topology_remove_dev(struct sys_device * sys_dev) | |||
107 | return 0; | 107 | return 0; |
108 | } | 108 | } |
109 | 109 | ||
110 | static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, | 110 | static int topology_cpu_callback(struct notifier_block *nfb, |
111 | unsigned long action, void *hcpu) | 111 | unsigned long action, void *hcpu) |
112 | { | 112 | { |
113 | unsigned int cpu = (unsigned long)hcpu; | 113 | unsigned int cpu = (unsigned long)hcpu; |
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/mem.c b/drivers/char/mem.c index 66719f9d294c..1fa9fa157c12 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/crash_dump.h> | 27 | #include <linux/crash_dump.h> |
28 | #include <linux/backing-dev.h> | 28 | #include <linux/backing-dev.h> |
29 | #include <linux/bootmem.h> | 29 | #include <linux/bootmem.h> |
30 | #include <linux/pipe_fs_i.h> | ||
30 | 31 | ||
31 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
32 | #include <asm/io.h> | 33 | #include <asm/io.h> |
@@ -578,6 +579,18 @@ static ssize_t write_null(struct file * file, const char __user * buf, | |||
578 | return count; | 579 | return count; |
579 | } | 580 | } |
580 | 581 | ||
582 | static int pipe_to_null(struct pipe_inode_info *info, struct pipe_buffer *buf, | ||
583 | struct splice_desc *sd) | ||
584 | { | ||
585 | return sd->len; | ||
586 | } | ||
587 | |||
588 | static ssize_t splice_write_null(struct pipe_inode_info *pipe,struct file *out, | ||
589 | loff_t *ppos, size_t len, unsigned int flags) | ||
590 | { | ||
591 | return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_null); | ||
592 | } | ||
593 | |||
581 | #ifdef CONFIG_MMU | 594 | #ifdef CONFIG_MMU |
582 | /* | 595 | /* |
583 | * For fun, we are using the MMU for this. | 596 | * For fun, we are using the MMU for this. |
@@ -785,6 +798,7 @@ static struct file_operations null_fops = { | |||
785 | .llseek = null_lseek, | 798 | .llseek = null_lseek, |
786 | .read = read_null, | 799 | .read = read_null, |
787 | .write = write_null, | 800 | .write = write_null, |
801 | .splice_write = splice_write_null, | ||
788 | }; | 802 | }; |
789 | 803 | ||
790 | #if defined(CONFIG_ISA) || !defined(__mc68000__) | 804 | #if defined(CONFIG_ISA) || !defined(__mc68000__) |
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c index 8666171e187b..d3ba2f860ef0 100644 --- a/drivers/char/mwave/mwavedd.c +++ b/drivers/char/mwave/mwavedd.c | |||
@@ -271,7 +271,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
271 | ipcnum, | 271 | ipcnum, |
272 | pDrvData->IPCs[ipcnum].usIntCount); | 272 | pDrvData->IPCs[ipcnum].usIntCount); |
273 | 273 | ||
274 | if (ipcnum > ARRAY_SIZE(pDrvData->IPCs)) { | 274 | if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) { |
275 | PRINTK_ERROR(KERN_ERR_MWAVE | 275 | PRINTK_ERROR(KERN_ERR_MWAVE |
276 | "mwavedd::mwave_ioctl:" | 276 | "mwavedd::mwave_ioctl:" |
277 | " IOCTL_MW_REGISTER_IPC:" | 277 | " IOCTL_MW_REGISTER_IPC:" |
diff --git a/drivers/char/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/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 9759d05b1972..29b2fa5534ae 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -1497,7 +1497,7 @@ int cpufreq_update_policy(unsigned int cpu) | |||
1497 | } | 1497 | } |
1498 | EXPORT_SYMBOL(cpufreq_update_policy); | 1498 | EXPORT_SYMBOL(cpufreq_update_policy); |
1499 | 1499 | ||
1500 | static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb, | 1500 | static int cpufreq_cpu_callback(struct notifier_block *nfb, |
1501 | unsigned long action, void *hcpu) | 1501 | unsigned long action, void *hcpu) |
1502 | { | 1502 | { |
1503 | unsigned int cpu = (unsigned long)hcpu; | 1503 | unsigned int cpu = (unsigned long)hcpu; |
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index 66572c5323ad..fce31936e6d7 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c | |||
@@ -25,6 +25,8 @@ | |||
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include "edac_mc.h" | 26 | #include "edac_mc.h" |
27 | 27 | ||
28 | static int force_function_unhide; | ||
29 | |||
28 | #define e752x_printk(level, fmt, arg...) \ | 30 | #define e752x_printk(level, fmt, arg...) \ |
29 | edac_printk(level, "e752x", fmt, ##arg) | 31 | edac_printk(level, "e752x", fmt, ##arg) |
30 | 32 | ||
@@ -782,8 +784,16 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) | |||
782 | debugf0("%s(): mci\n", __func__); | 784 | debugf0("%s(): mci\n", __func__); |
783 | debugf0("Starting Probe1\n"); | 785 | debugf0("Starting Probe1\n"); |
784 | 786 | ||
785 | /* enable device 0 function 1 */ | 787 | /* check to see if device 0 function 1 is enabled; if it isn't, we |
788 | * assume the BIOS has reserved it for a reason and is expecting | ||
789 | * exclusive access, we take care not to violate that assumption and | ||
790 | * fail the probe. */ | ||
786 | pci_read_config_byte(pdev, E752X_DEVPRES1, &stat8); | 791 | pci_read_config_byte(pdev, E752X_DEVPRES1, &stat8); |
792 | if (!force_function_unhide && !(stat8 & (1 << 5))) { | ||
793 | printk(KERN_INFO "Contact your BIOS vendor to see if the " | ||
794 | "E752x error registers can be safely un-hidden\n"); | ||
795 | goto fail; | ||
796 | } | ||
787 | stat8 |= (1 << 5); | 797 | stat8 |= (1 << 5); |
788 | pci_write_config_byte(pdev, E752X_DEVPRES1, stat8); | 798 | pci_write_config_byte(pdev, E752X_DEVPRES1, stat8); |
789 | 799 | ||
@@ -1063,3 +1073,8 @@ module_exit(e752x_exit); | |||
1063 | MODULE_LICENSE("GPL"); | 1073 | MODULE_LICENSE("GPL"); |
1064 | MODULE_AUTHOR("Linux Networx (http://lnxi.com) Tom Zimmerman\n"); | 1074 | MODULE_AUTHOR("Linux Networx (http://lnxi.com) Tom Zimmerman\n"); |
1065 | MODULE_DESCRIPTION("MC support for Intel e752x memory controllers"); | 1075 | MODULE_DESCRIPTION("MC support for Intel e752x memory controllers"); |
1076 | |||
1077 | module_param(force_function_unhide, int, 0444); | ||
1078 | MODULE_PARM_DESC(force_function_unhide, "if BIOS sets Dev0:Fun1 up as hidden:" | ||
1079 | " 1=force unhide and hope BIOS doesn't fight driver for Dev0:Fun1 access"); | ||
1080 | |||
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/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c index 1042987856f7..5013703db0e6 100644 --- a/drivers/input/touchscreen/corgi_ts.c +++ b/drivers/input/touchscreen/corgi_ts.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <asm/irq.h> | 20 | //#include <asm/irq.h> |
21 | 21 | ||
22 | #include <asm/arch/sharpsl.h> | 22 | #include <asm/arch/sharpsl.h> |
23 | #include <asm/arch/hardware.h> | 23 | #include <asm/arch/hardware.h> |
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/mmc/at91_mci.c b/drivers/mmc/at91_mci.c index 6061c2d101a0..88f0eef9cf33 100644 --- a/drivers/mmc/at91_mci.c +++ b/drivers/mmc/at91_mci.c | |||
@@ -621,9 +621,6 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
621 | struct at91mci_host *host = mmc_priv(mmc); | 621 | struct at91mci_host *host = mmc_priv(mmc); |
622 | unsigned long at91_master_clock = clk_get_rate(mci_clk); | 622 | unsigned long at91_master_clock = clk_get_rate(mci_clk); |
623 | 623 | ||
624 | DBG("Clock %uHz, busmode %u, powermode %u, Vdd %u\n", | ||
625 | ios->clock, ios->bus_mode, ios->power_mode, ios->vdd); | ||
626 | |||
627 | if (host) | 624 | if (host) |
628 | host->bus_mode = ios->bus_mode; | 625 | host->bus_mode = ios->bus_mode; |
629 | else | 626 | else |
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c index c0326bbc5f28..914d62b24064 100644 --- a/drivers/mmc/au1xmmc.c +++ b/drivers/mmc/au1xmmc.c | |||
@@ -720,10 +720,6 @@ static void au1xmmc_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) | |||
720 | { | 720 | { |
721 | struct au1xmmc_host *host = mmc_priv(mmc); | 721 | struct au1xmmc_host *host = mmc_priv(mmc); |
722 | 722 | ||
723 | DBG("set_ios (power=%u, clock=%uHz, vdd=%u, mode=%u)\n", | ||
724 | host->id, ios->power_mode, ios->clock, ios->vdd, | ||
725 | ios->bus_mode); | ||
726 | |||
727 | if (ios->power_mode == MMC_POWER_OFF) | 723 | if (ios->power_mode == MMC_POWER_OFF) |
728 | au1xmmc_set_power(host, 0); | 724 | au1xmmc_set_power(host, 0); |
729 | else if (ios->power_mode == MMC_POWER_ON) { | 725 | else if (ios->power_mode == MMC_POWER_ON) { |
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c index ffb7f55d3467..79358e223f57 100644 --- a/drivers/mmc/imxmmc.c +++ b/drivers/mmc/imxmmc.c | |||
@@ -102,6 +102,7 @@ struct imxmci_host { | |||
102 | #define IMXMCI_PEND_CPU_DATA_b 5 | 102 | #define IMXMCI_PEND_CPU_DATA_b 5 |
103 | #define IMXMCI_PEND_CARD_XCHG_b 6 | 103 | #define IMXMCI_PEND_CARD_XCHG_b 6 |
104 | #define IMXMCI_PEND_SET_INIT_b 7 | 104 | #define IMXMCI_PEND_SET_INIT_b 7 |
105 | #define IMXMCI_PEND_STARTED_b 8 | ||
105 | 106 | ||
106 | #define IMXMCI_PEND_IRQ_m (1 << IMXMCI_PEND_IRQ_b) | 107 | #define IMXMCI_PEND_IRQ_m (1 << IMXMCI_PEND_IRQ_b) |
107 | #define IMXMCI_PEND_DMA_END_m (1 << IMXMCI_PEND_DMA_END_b) | 108 | #define IMXMCI_PEND_DMA_END_m (1 << IMXMCI_PEND_DMA_END_b) |
@@ -111,6 +112,7 @@ struct imxmci_host { | |||
111 | #define IMXMCI_PEND_CPU_DATA_m (1 << IMXMCI_PEND_CPU_DATA_b) | 112 | #define IMXMCI_PEND_CPU_DATA_m (1 << IMXMCI_PEND_CPU_DATA_b) |
112 | #define IMXMCI_PEND_CARD_XCHG_m (1 << IMXMCI_PEND_CARD_XCHG_b) | 113 | #define IMXMCI_PEND_CARD_XCHG_m (1 << IMXMCI_PEND_CARD_XCHG_b) |
113 | #define IMXMCI_PEND_SET_INIT_m (1 << IMXMCI_PEND_SET_INIT_b) | 114 | #define IMXMCI_PEND_SET_INIT_m (1 << IMXMCI_PEND_SET_INIT_b) |
115 | #define IMXMCI_PEND_STARTED_m (1 << IMXMCI_PEND_STARTED_b) | ||
114 | 116 | ||
115 | static void imxmci_stop_clock(struct imxmci_host *host) | 117 | static void imxmci_stop_clock(struct imxmci_host *host) |
116 | { | 118 | { |
@@ -131,23 +133,52 @@ static void imxmci_stop_clock(struct imxmci_host *host) | |||
131 | dev_dbg(mmc_dev(host->mmc), "imxmci_stop_clock blocked, no luck\n"); | 133 | dev_dbg(mmc_dev(host->mmc), "imxmci_stop_clock blocked, no luck\n"); |
132 | } | 134 | } |
133 | 135 | ||
134 | static void imxmci_start_clock(struct imxmci_host *host) | 136 | static int imxmci_start_clock(struct imxmci_host *host) |
135 | { | 137 | { |
136 | int i = 0; | 138 | unsigned int trials = 0; |
139 | unsigned int delay_limit = 128; | ||
140 | unsigned long flags; | ||
141 | |||
137 | MMC_STR_STP_CLK &= ~STR_STP_CLK_STOP_CLK; | 142 | MMC_STR_STP_CLK &= ~STR_STP_CLK_STOP_CLK; |
138 | while(i < 0x1000) { | ||
139 | if(!(i & 0x7f)) | ||
140 | MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK; | ||
141 | 143 | ||
142 | if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN) { | 144 | clear_bit(IMXMCI_PEND_STARTED_b, &host->pending_events); |
143 | /* Check twice before cut */ | 145 | |
146 | /* | ||
147 | * Command start of the clock, this usually succeeds in less | ||
148 | * then 6 delay loops, but during card detection (low clockrate) | ||
149 | * it takes up to 5000 delay loops and sometimes fails for the first time | ||
150 | */ | ||
151 | MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK; | ||
152 | |||
153 | do { | ||
154 | unsigned int delay = delay_limit; | ||
155 | |||
156 | while(delay--){ | ||
144 | if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN) | 157 | if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN) |
145 | return; | 158 | /* Check twice before cut */ |
159 | if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN) | ||
160 | return 0; | ||
161 | |||
162 | if(test_bit(IMXMCI_PEND_STARTED_b, &host->pending_events)) | ||
163 | return 0; | ||
146 | } | 164 | } |
147 | 165 | ||
148 | i++; | 166 | local_irq_save(flags); |
149 | } | 167 | /* |
150 | dev_dbg(mmc_dev(host->mmc), "imxmci_start_clock blocked, no luck\n"); | 168 | * Ensure, that request is not doubled under all possible circumstances. |
169 | * It is possible, that cock running state is missed, because some other | ||
170 | * IRQ or schedule delays this function execution and the clocks has | ||
171 | * been already stopped by other means (response processing, SDHC HW) | ||
172 | */ | ||
173 | if(!test_bit(IMXMCI_PEND_STARTED_b, &host->pending_events)) | ||
174 | MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK; | ||
175 | local_irq_restore(flags); | ||
176 | |||
177 | } while(++trials<256); | ||
178 | |||
179 | dev_err(mmc_dev(host->mmc), "imxmci_start_clock blocked, no luck\n"); | ||
180 | |||
181 | return -1; | ||
151 | } | 182 | } |
152 | 183 | ||
153 | static void imxmci_softreset(void) | 184 | static void imxmci_softreset(void) |
@@ -498,7 +529,7 @@ static int imxmci_data_done(struct imxmci_host *host, unsigned int stat) | |||
498 | 529 | ||
499 | data_error = imxmci_finish_data(host, stat); | 530 | data_error = imxmci_finish_data(host, stat); |
500 | 531 | ||
501 | if (host->req->stop && (data_error == MMC_ERR_NONE)) { | 532 | if (host->req->stop) { |
502 | imxmci_stop_clock(host); | 533 | imxmci_stop_clock(host); |
503 | imxmci_start_cmd(host, host->req->stop, 0); | 534 | imxmci_start_cmd(host, host->req->stop, 0); |
504 | } else { | 535 | } else { |
@@ -622,6 +653,7 @@ static irqreturn_t imxmci_irq(int irq, void *devid, struct pt_regs *regs) | |||
622 | atomic_set(&host->stuck_timeout, 0); | 653 | atomic_set(&host->stuck_timeout, 0); |
623 | host->status_reg = stat; | 654 | host->status_reg = stat; |
624 | set_bit(IMXMCI_PEND_IRQ_b, &host->pending_events); | 655 | set_bit(IMXMCI_PEND_IRQ_b, &host->pending_events); |
656 | set_bit(IMXMCI_PEND_STARTED_b, &host->pending_events); | ||
625 | tasklet_schedule(&host->tasklet); | 657 | tasklet_schedule(&host->tasklet); |
626 | 658 | ||
627 | return IRQ_RETVAL(handled);; | 659 | return IRQ_RETVAL(handled);; |
@@ -775,10 +807,6 @@ static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
775 | struct imxmci_host *host = mmc_priv(mmc); | 807 | struct imxmci_host *host = mmc_priv(mmc); |
776 | int prescaler; | 808 | int prescaler; |
777 | 809 | ||
778 | dev_dbg(mmc_dev(host->mmc), "clock %u power %u vdd %u width %u\n", | ||
779 | ios->clock, ios->power_mode, ios->vdd, | ||
780 | (ios->bus_width==MMC_BUS_WIDTH_4)?4:1); | ||
781 | |||
782 | if( ios->bus_width==MMC_BUS_WIDTH_4 ) { | 810 | if( ios->bus_width==MMC_BUS_WIDTH_4 ) { |
783 | host->actual_bus_width = MMC_BUS_WIDTH_4; | 811 | host->actual_bus_width = MMC_BUS_WIDTH_4; |
784 | imx_gpio_mode(PB11_PF_SD_DAT3); | 812 | imx_gpio_mode(PB11_PF_SD_DAT3); |
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index da6ddd910fc5..1ca2c8b9c9b5 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c | |||
@@ -59,21 +59,23 @@ static const unsigned int tacc_mant[] = { | |||
59 | 59 | ||
60 | 60 | ||
61 | /** | 61 | /** |
62 | * mmc_request_done - finish processing an MMC command | 62 | * mmc_request_done - finish processing an MMC request |
63 | * @host: MMC host which completed command | 63 | * @host: MMC host which completed request |
64 | * @mrq: MMC request which completed | 64 | * @mrq: MMC request which request |
65 | * | 65 | * |
66 | * MMC drivers should call this function when they have completed | 66 | * MMC drivers should call this function when they have completed |
67 | * their processing of a command. This should be called before the | 67 | * their processing of a request. |
68 | * data part of the command has completed. | ||
69 | */ | 68 | */ |
70 | void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) | 69 | void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) |
71 | { | 70 | { |
72 | struct mmc_command *cmd = mrq->cmd; | 71 | struct mmc_command *cmd = mrq->cmd; |
73 | int err = mrq->cmd->error; | 72 | int err = cmd->error; |
74 | pr_debug("MMC: req done (%02x): %d: %08x %08x %08x %08x\n", | 73 | |
75 | cmd->opcode, err, cmd->resp[0], cmd->resp[1], | 74 | pr_debug("%s: req done (CMD%u): %d/%d/%d: %08x %08x %08x %08x\n", |
76 | cmd->resp[2], cmd->resp[3]); | 75 | mmc_hostname(host), cmd->opcode, err, |
76 | mrq->data ? mrq->data->error : 0, | ||
77 | mrq->stop ? mrq->stop->error : 0, | ||
78 | cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); | ||
77 | 79 | ||
78 | if (err && cmd->retries) { | 80 | if (err && cmd->retries) { |
79 | cmd->retries--; | 81 | cmd->retries--; |
@@ -97,8 +99,9 @@ EXPORT_SYMBOL(mmc_request_done); | |||
97 | void | 99 | void |
98 | mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) | 100 | mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) |
99 | { | 101 | { |
100 | pr_debug("MMC: starting cmd %02x arg %08x flags %08x\n", | 102 | pr_debug("%s: starting CMD%u arg %08x flags %08x\n", |
101 | mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags); | 103 | mmc_hostname(host), mrq->cmd->opcode, |
104 | mrq->cmd->arg, mrq->cmd->flags); | ||
102 | 105 | ||
103 | WARN_ON(host->card_busy == NULL); | 106 | WARN_ON(host->card_busy == NULL); |
104 | 107 | ||
@@ -312,6 +315,18 @@ void mmc_release_host(struct mmc_host *host) | |||
312 | 315 | ||
313 | EXPORT_SYMBOL(mmc_release_host); | 316 | EXPORT_SYMBOL(mmc_release_host); |
314 | 317 | ||
318 | static inline void mmc_set_ios(struct mmc_host *host) | ||
319 | { | ||
320 | struct mmc_ios *ios = &host->ios; | ||
321 | |||
322 | pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n", | ||
323 | mmc_hostname(host), ios->clock, ios->bus_mode, | ||
324 | ios->power_mode, ios->chip_select, ios->vdd, | ||
325 | ios->bus_width); | ||
326 | |||
327 | host->ops->set_ios(host, ios); | ||
328 | } | ||
329 | |||
315 | static int mmc_select_card(struct mmc_host *host, struct mmc_card *card) | 330 | static int mmc_select_card(struct mmc_host *host, struct mmc_card *card) |
316 | { | 331 | { |
317 | int err; | 332 | int err; |
@@ -364,7 +379,7 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card) | |||
364 | } | 379 | } |
365 | } | 380 | } |
366 | 381 | ||
367 | host->ops->set_ios(host, &host->ios); | 382 | mmc_set_ios(host); |
368 | 383 | ||
369 | return MMC_ERR_NONE; | 384 | return MMC_ERR_NONE; |
370 | } | 385 | } |
@@ -415,7 +430,7 @@ static u32 mmc_select_voltage(struct mmc_host *host, u32 ocr) | |||
415 | ocr = 3 << bit; | 430 | ocr = 3 << bit; |
416 | 431 | ||
417 | host->ios.vdd = bit; | 432 | host->ios.vdd = bit; |
418 | host->ops->set_ios(host, &host->ios); | 433 | mmc_set_ios(host); |
419 | } else { | 434 | } else { |
420 | ocr = 0; | 435 | ocr = 0; |
421 | } | 436 | } |
@@ -549,6 +564,7 @@ static void mmc_decode_csd(struct mmc_card *card) | |||
549 | csd->read_partial = UNSTUFF_BITS(resp, 79, 1); | 564 | csd->read_partial = UNSTUFF_BITS(resp, 79, 1); |
550 | csd->write_misalign = UNSTUFF_BITS(resp, 78, 1); | 565 | csd->write_misalign = UNSTUFF_BITS(resp, 78, 1); |
551 | csd->read_misalign = UNSTUFF_BITS(resp, 77, 1); | 566 | csd->read_misalign = UNSTUFF_BITS(resp, 77, 1); |
567 | csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3); | ||
552 | csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); | 568 | csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); |
553 | csd->write_partial = UNSTUFF_BITS(resp, 21, 1); | 569 | csd->write_partial = UNSTUFF_BITS(resp, 21, 1); |
554 | } else { | 570 | } else { |
@@ -583,6 +599,7 @@ static void mmc_decode_csd(struct mmc_card *card) | |||
583 | csd->read_partial = UNSTUFF_BITS(resp, 79, 1); | 599 | csd->read_partial = UNSTUFF_BITS(resp, 79, 1); |
584 | csd->write_misalign = UNSTUFF_BITS(resp, 78, 1); | 600 | csd->write_misalign = UNSTUFF_BITS(resp, 78, 1); |
585 | csd->read_misalign = UNSTUFF_BITS(resp, 77, 1); | 601 | csd->read_misalign = UNSTUFF_BITS(resp, 77, 1); |
602 | csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3); | ||
586 | csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); | 603 | csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); |
587 | csd->write_partial = UNSTUFF_BITS(resp, 21, 1); | 604 | csd->write_partial = UNSTUFF_BITS(resp, 21, 1); |
588 | } | 605 | } |
@@ -666,7 +683,7 @@ static void mmc_idle_cards(struct mmc_host *host) | |||
666 | struct mmc_command cmd; | 683 | struct mmc_command cmd; |
667 | 684 | ||
668 | host->ios.chip_select = MMC_CS_HIGH; | 685 | host->ios.chip_select = MMC_CS_HIGH; |
669 | host->ops->set_ios(host, &host->ios); | 686 | mmc_set_ios(host); |
670 | 687 | ||
671 | mmc_delay(1); | 688 | mmc_delay(1); |
672 | 689 | ||
@@ -679,7 +696,7 @@ static void mmc_idle_cards(struct mmc_host *host) | |||
679 | mmc_delay(1); | 696 | mmc_delay(1); |
680 | 697 | ||
681 | host->ios.chip_select = MMC_CS_DONTCARE; | 698 | host->ios.chip_select = MMC_CS_DONTCARE; |
682 | host->ops->set_ios(host, &host->ios); | 699 | mmc_set_ios(host); |
683 | 700 | ||
684 | mmc_delay(1); | 701 | mmc_delay(1); |
685 | } | 702 | } |
@@ -704,13 +721,13 @@ static void mmc_power_up(struct mmc_host *host) | |||
704 | host->ios.chip_select = MMC_CS_DONTCARE; | 721 | host->ios.chip_select = MMC_CS_DONTCARE; |
705 | host->ios.power_mode = MMC_POWER_UP; | 722 | host->ios.power_mode = MMC_POWER_UP; |
706 | host->ios.bus_width = MMC_BUS_WIDTH_1; | 723 | host->ios.bus_width = MMC_BUS_WIDTH_1; |
707 | host->ops->set_ios(host, &host->ios); | 724 | mmc_set_ios(host); |
708 | 725 | ||
709 | mmc_delay(1); | 726 | mmc_delay(1); |
710 | 727 | ||
711 | host->ios.clock = host->f_min; | 728 | host->ios.clock = host->f_min; |
712 | host->ios.power_mode = MMC_POWER_ON; | 729 | host->ios.power_mode = MMC_POWER_ON; |
713 | host->ops->set_ios(host, &host->ios); | 730 | mmc_set_ios(host); |
714 | 731 | ||
715 | mmc_delay(2); | 732 | mmc_delay(2); |
716 | } | 733 | } |
@@ -723,7 +740,7 @@ static void mmc_power_off(struct mmc_host *host) | |||
723 | host->ios.chip_select = MMC_CS_DONTCARE; | 740 | host->ios.chip_select = MMC_CS_DONTCARE; |
724 | host->ios.power_mode = MMC_POWER_OFF; | 741 | host->ios.power_mode = MMC_POWER_OFF; |
725 | host->ios.bus_width = MMC_BUS_WIDTH_1; | 742 | host->ios.bus_width = MMC_BUS_WIDTH_1; |
726 | host->ops->set_ios(host, &host->ios); | 743 | mmc_set_ios(host); |
727 | } | 744 | } |
728 | 745 | ||
729 | static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) | 746 | static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) |
@@ -971,7 +988,8 @@ static unsigned int mmc_calculate_clock(struct mmc_host *host) | |||
971 | if (!mmc_card_dead(card) && max_dtr > card->csd.max_dtr) | 988 | if (!mmc_card_dead(card) && max_dtr > card->csd.max_dtr) |
972 | max_dtr = card->csd.max_dtr; | 989 | max_dtr = card->csd.max_dtr; |
973 | 990 | ||
974 | pr_debug("MMC: selected %d.%03dMHz transfer rate\n", | 991 | pr_debug("%s: selected %d.%03dMHz transfer rate\n", |
992 | mmc_hostname(host), | ||
975 | max_dtr / 1000000, (max_dtr / 1000) % 1000); | 993 | max_dtr / 1000000, (max_dtr / 1000) % 1000); |
976 | 994 | ||
977 | return max_dtr; | 995 | return max_dtr; |
@@ -1046,7 +1064,7 @@ static void mmc_setup(struct mmc_host *host) | |||
1046 | } else { | 1064 | } else { |
1047 | host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; | 1065 | host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; |
1048 | host->ios.clock = host->f_min; | 1066 | host->ios.clock = host->f_min; |
1049 | host->ops->set_ios(host, &host->ios); | 1067 | mmc_set_ios(host); |
1050 | 1068 | ||
1051 | /* | 1069 | /* |
1052 | * We should remember the OCR mask from the existing | 1070 | * We should remember the OCR mask from the existing |
@@ -1082,7 +1100,7 @@ static void mmc_setup(struct mmc_host *host) | |||
1082 | * Ok, now switch to push-pull mode. | 1100 | * Ok, now switch to push-pull mode. |
1083 | */ | 1101 | */ |
1084 | host->ios.bus_mode = MMC_BUSMODE_PUSHPULL; | 1102 | host->ios.bus_mode = MMC_BUSMODE_PUSHPULL; |
1085 | host->ops->set_ios(host, &host->ios); | 1103 | mmc_set_ios(host); |
1086 | 1104 | ||
1087 | mmc_read_csds(host); | 1105 | mmc_read_csds(host); |
1088 | 1106 | ||
@@ -1128,7 +1146,7 @@ static void mmc_rescan(void *data) | |||
1128 | * attached cards and the host support. | 1146 | * attached cards and the host support. |
1129 | */ | 1147 | */ |
1130 | host->ios.clock = mmc_calculate_clock(host); | 1148 | host->ios.clock = mmc_calculate_clock(host); |
1131 | host->ops->set_ios(host, &host->ios); | 1149 | mmc_set_ios(host); |
1132 | } | 1150 | } |
1133 | 1151 | ||
1134 | mmc_release_host(host); | 1152 | mmc_release_host(host); |
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index 8eb2a2ede64b..06bd1f4cb9b1 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c | |||
@@ -187,6 +187,12 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
187 | brq.cmd.opcode = MMC_WRITE_BLOCK; | 187 | brq.cmd.opcode = MMC_WRITE_BLOCK; |
188 | brq.data.flags |= MMC_DATA_WRITE; | 188 | brq.data.flags |= MMC_DATA_WRITE; |
189 | brq.data.blocks = 1; | 189 | brq.data.blocks = 1; |
190 | |||
191 | /* | ||
192 | * Scale up the timeout by the r2w factor | ||
193 | */ | ||
194 | brq.data.timeout_ns <<= card->csd.r2w_factor; | ||
195 | brq.data.timeout_clks <<= card->csd.r2w_factor; | ||
190 | } | 196 | } |
191 | 197 | ||
192 | if (brq.data.blocks > 1) { | 198 | if (brq.data.blocks > 1) { |
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c index df7e861e2fc7..da8e4d7339cc 100644 --- a/drivers/mmc/mmci.c +++ b/drivers/mmc/mmci.c | |||
@@ -402,9 +402,6 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
402 | struct mmci_host *host = mmc_priv(mmc); | 402 | struct mmci_host *host = mmc_priv(mmc); |
403 | u32 clk = 0, pwr = 0; | 403 | u32 clk = 0, pwr = 0; |
404 | 404 | ||
405 | DBG(host, "clock %uHz busmode %u powermode %u Vdd %u\n", | ||
406 | ios->clock, ios->bus_mode, ios->power_mode, ios->vdd); | ||
407 | |||
408 | if (ios->clock) { | 405 | if (ios->clock) { |
409 | if (ios->clock >= host->mclk) { | 406 | if (ios->clock >= host->mclk) { |
410 | clk = MCI_CLK_BYPASS; | 407 | clk = MCI_CLK_BYPASS; |
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c index eb9a8826e9b5..f97b472085cb 100644 --- a/drivers/mmc/pxamci.c +++ b/drivers/mmc/pxamci.c | |||
@@ -65,11 +65,6 @@ struct pxamci_host { | |||
65 | unsigned int dma_dir; | 65 | unsigned int dma_dir; |
66 | }; | 66 | }; |
67 | 67 | ||
68 | static inline unsigned int ns_to_clocks(unsigned int ns) | ||
69 | { | ||
70 | return (ns * (CLOCKRATE / 1000000) + 999) / 1000; | ||
71 | } | ||
72 | |||
73 | static void pxamci_stop_clock(struct pxamci_host *host) | 68 | static void pxamci_stop_clock(struct pxamci_host *host) |
74 | { | 69 | { |
75 | if (readl(host->base + MMC_STAT) & STAT_CLK_EN) { | 70 | if (readl(host->base + MMC_STAT) & STAT_CLK_EN) { |
@@ -113,6 +108,7 @@ static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask) | |||
113 | static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) | 108 | static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) |
114 | { | 109 | { |
115 | unsigned int nob = data->blocks; | 110 | unsigned int nob = data->blocks; |
111 | unsigned long long clks; | ||
116 | unsigned int timeout; | 112 | unsigned int timeout; |
117 | u32 dcmd; | 113 | u32 dcmd; |
118 | int i; | 114 | int i; |
@@ -125,7 +121,9 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) | |||
125 | writel(nob, host->base + MMC_NOB); | 121 | writel(nob, host->base + MMC_NOB); |
126 | writel(1 << data->blksz_bits, host->base + MMC_BLKLEN); | 122 | writel(1 << data->blksz_bits, host->base + MMC_BLKLEN); |
127 | 123 | ||
128 | timeout = ns_to_clocks(data->timeout_ns) + data->timeout_clks; | 124 | clks = (unsigned long long)data->timeout_ns * CLOCKRATE; |
125 | do_div(clks, 1000000000UL); | ||
126 | timeout = (unsigned int)clks + (data->timeout_clks << host->clkrt); | ||
129 | writel((timeout + 255) / 256, host->base + MMC_RDTO); | 127 | writel((timeout + 255) / 256, host->base + MMC_RDTO); |
130 | 128 | ||
131 | if (data->flags & MMC_DATA_READ) { | 129 | if (data->flags & MMC_DATA_READ) { |
@@ -200,7 +198,6 @@ static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd, | |||
200 | 198 | ||
201 | static void pxamci_finish_request(struct pxamci_host *host, struct mmc_request *mrq) | 199 | static void pxamci_finish_request(struct pxamci_host *host, struct mmc_request *mrq) |
202 | { | 200 | { |
203 | pr_debug("PXAMCI: request done\n"); | ||
204 | host->mrq = NULL; | 201 | host->mrq = NULL; |
205 | host->cmd = NULL; | 202 | host->cmd = NULL; |
206 | host->data = NULL; | 203 | host->data = NULL; |
@@ -293,7 +290,7 @@ static int pxamci_data_done(struct pxamci_host *host, unsigned int stat) | |||
293 | pxamci_disable_irq(host, DATA_TRAN_DONE); | 290 | pxamci_disable_irq(host, DATA_TRAN_DONE); |
294 | 291 | ||
295 | host->data = NULL; | 292 | host->data = NULL; |
296 | if (host->mrq->stop && data->error == MMC_ERR_NONE) { | 293 | if (host->mrq->stop) { |
297 | pxamci_stop_clock(host); | 294 | pxamci_stop_clock(host); |
298 | pxamci_start_cmd(host, host->mrq->stop, 0); | 295 | pxamci_start_cmd(host, host->mrq->stop, 0); |
299 | } else { | 296 | } else { |
@@ -311,12 +308,10 @@ static irqreturn_t pxamci_irq(int irq, void *devid, struct pt_regs *regs) | |||
311 | 308 | ||
312 | ireg = readl(host->base + MMC_I_REG); | 309 | ireg = readl(host->base + MMC_I_REG); |
313 | 310 | ||
314 | pr_debug("PXAMCI: irq %08x\n", ireg); | ||
315 | |||
316 | if (ireg) { | 311 | if (ireg) { |
317 | unsigned stat = readl(host->base + MMC_STAT); | 312 | unsigned stat = readl(host->base + MMC_STAT); |
318 | 313 | ||
319 | pr_debug("PXAMCI: stat %08x\n", stat); | 314 | pr_debug("PXAMCI: irq %08x stat %08x\n", ireg, stat); |
320 | 315 | ||
321 | if (ireg & END_CMD_RES) | 316 | if (ireg & END_CMD_RES) |
322 | handled |= pxamci_cmd_done(host, stat); | 317 | handled |= pxamci_cmd_done(host, stat); |
@@ -370,10 +365,6 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
370 | { | 365 | { |
371 | struct pxamci_host *host = mmc_priv(mmc); | 366 | struct pxamci_host *host = mmc_priv(mmc); |
372 | 367 | ||
373 | pr_debug("pxamci_set_ios: clock %u power %u vdd %u.%02u\n", | ||
374 | ios->clock, ios->power_mode, ios->vdd / 100, | ||
375 | ios->vdd % 100); | ||
376 | |||
377 | if (ios->clock) { | 368 | if (ios->clock) { |
378 | unsigned int clk = CLOCKRATE / ios->clock; | 369 | unsigned int clk = CLOCKRATE / ios->clock; |
379 | if (CLOCKRATE / clk > ios->clock) | 370 | if (CLOCKRATE / clk > ios->clock) |
@@ -399,7 +390,7 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
399 | host->cmdat |= CMDAT_INIT; | 390 | host->cmdat |= CMDAT_INIT; |
400 | } | 391 | } |
401 | 392 | ||
402 | pr_debug("pxamci_set_ios: clkrt = %x cmdat = %x\n", | 393 | pr_debug("PXAMCI: clkrt = %x cmdat = %x\n", |
403 | host->clkrt, host->cmdat); | 394 | host->clkrt, host->cmdat); |
404 | } | 395 | } |
405 | 396 | ||
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index bdbfca050029..b0053280ff2d 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c | |||
@@ -570,10 +570,6 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
570 | 570 | ||
571 | spin_lock_irqsave(&host->lock, flags); | 571 | spin_lock_irqsave(&host->lock, flags); |
572 | 572 | ||
573 | DBG("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n", | ||
574 | ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select, | ||
575 | ios->vdd, ios->bus_width); | ||
576 | |||
577 | /* | 573 | /* |
578 | * Reset the chip on each power off. | 574 | * Reset the chip on each power off. |
579 | * Should clear out any weird states. | 575 | * Should clear out any weird states. |
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index 511f7b0b31d2..39b3d97f891e 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c | |||
@@ -931,10 +931,6 @@ static void wbsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
931 | struct wbsd_host *host = mmc_priv(mmc); | 931 | struct wbsd_host *host = mmc_priv(mmc); |
932 | u8 clk, setup, pwr; | 932 | u8 clk, setup, pwr; |
933 | 933 | ||
934 | DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n", | ||
935 | ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select, | ||
936 | ios->vdd, ios->bus_width); | ||
937 | |||
938 | spin_lock_bh(&host->lock); | 934 | spin_lock_bh(&host->lock); |
939 | 935 | ||
940 | /* | 936 | /* |
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index add8dc4aa7b0..c99e87838f92 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -3768,6 +3768,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, | |||
3768 | ps_page->ps_page[j] = NULL; | 3768 | ps_page->ps_page[j] = NULL; |
3769 | skb->len += length; | 3769 | skb->len += length; |
3770 | skb->data_len += length; | 3770 | skb->data_len += length; |
3771 | skb->truesize += length; | ||
3771 | } | 3772 | } |
3772 | 3773 | ||
3773 | copydone: | 3774 | copydone: |
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 7627a75f4f7c..f7235c9bc421 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
@@ -105,6 +105,8 @@ | |||
105 | * 0.50: 20 Jan 2006: Add 8021pq tagging support. | 105 | * 0.50: 20 Jan 2006: Add 8021pq tagging support. |
106 | * 0.51: 20 Jan 2006: Add 64bit consistent memory allocation for rings. | 106 | * 0.51: 20 Jan 2006: Add 64bit consistent memory allocation for rings. |
107 | * 0.52: 20 Jan 2006: Add MSI/MSIX support. | 107 | * 0.52: 20 Jan 2006: Add MSI/MSIX support. |
108 | * 0.53: 19 Mar 2006: Fix init from low power mode and add hw reset. | ||
109 | * 0.54: 21 Mar 2006: Fix spin locks for multi irqs and cleanup. | ||
108 | * | 110 | * |
109 | * Known bugs: | 111 | * Known bugs: |
110 | * We suspect that on some hardware no TX done interrupts are generated. | 112 | * We suspect that on some hardware no TX done interrupts are generated. |
@@ -116,7 +118,7 @@ | |||
116 | * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few | 118 | * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few |
117 | * superfluous timer interrupts from the nic. | 119 | * superfluous timer interrupts from the nic. |
118 | */ | 120 | */ |
119 | #define FORCEDETH_VERSION "0.52" | 121 | #define FORCEDETH_VERSION "0.54" |
120 | #define DRV_NAME "forcedeth" | 122 | #define DRV_NAME "forcedeth" |
121 | 123 | ||
122 | #include <linux/module.h> | 124 | #include <linux/module.h> |
@@ -160,6 +162,7 @@ | |||
160 | #define DEV_HAS_VLAN 0x0020 /* device supports vlan tagging and striping */ | 162 | #define DEV_HAS_VLAN 0x0020 /* device supports vlan tagging and striping */ |
161 | #define DEV_HAS_MSI 0x0040 /* device supports MSI */ | 163 | #define DEV_HAS_MSI 0x0040 /* device supports MSI */ |
162 | #define DEV_HAS_MSI_X 0x0080 /* device supports MSI-X */ | 164 | #define DEV_HAS_MSI_X 0x0080 /* device supports MSI-X */ |
165 | #define DEV_HAS_POWER_CNTRL 0x0100 /* device supports power savings */ | ||
163 | 166 | ||
164 | enum { | 167 | enum { |
165 | NvRegIrqStatus = 0x000, | 168 | NvRegIrqStatus = 0x000, |
@@ -203,6 +206,8 @@ enum { | |||
203 | #define NVREG_MISC1_HD 0x02 | 206 | #define NVREG_MISC1_HD 0x02 |
204 | #define NVREG_MISC1_FORCE 0x3b0f3c | 207 | #define NVREG_MISC1_FORCE 0x3b0f3c |
205 | 208 | ||
209 | NvRegMacReset = 0x3c, | ||
210 | #define NVREG_MAC_RESET_ASSERT 0x0F3 | ||
206 | NvRegTransmitterControl = 0x084, | 211 | NvRegTransmitterControl = 0x084, |
207 | #define NVREG_XMITCTL_START 0x01 | 212 | #define NVREG_XMITCTL_START 0x01 |
208 | NvRegTransmitterStatus = 0x088, | 213 | NvRegTransmitterStatus = 0x088, |
@@ -326,6 +331,10 @@ enum { | |||
326 | NvRegMSIXMap0 = 0x3e0, | 331 | NvRegMSIXMap0 = 0x3e0, |
327 | NvRegMSIXMap1 = 0x3e4, | 332 | NvRegMSIXMap1 = 0x3e4, |
328 | NvRegMSIXIrqStatus = 0x3f0, | 333 | NvRegMSIXIrqStatus = 0x3f0, |
334 | |||
335 | NvRegPowerState2 = 0x600, | ||
336 | #define NVREG_POWERSTATE2_POWERUP_MASK 0x0F11 | ||
337 | #define NVREG_POWERSTATE2_POWERUP_REV_A3 0x0001 | ||
329 | }; | 338 | }; |
330 | 339 | ||
331 | /* Big endian: should work, but is untested */ | 340 | /* Big endian: should work, but is untested */ |
@@ -414,7 +423,8 @@ typedef union _ring_type { | |||
414 | #define NV_RX3_VLAN_TAG_MASK (0x0000FFFF) | 423 | #define NV_RX3_VLAN_TAG_MASK (0x0000FFFF) |
415 | 424 | ||
416 | /* Miscelaneous hardware related defines: */ | 425 | /* Miscelaneous hardware related defines: */ |
417 | #define NV_PCI_REGSZ 0x270 | 426 | #define NV_PCI_REGSZ_VER1 0x270 |
427 | #define NV_PCI_REGSZ_VER2 0x604 | ||
418 | 428 | ||
419 | /* various timeout delays: all in usec */ | 429 | /* various timeout delays: all in usec */ |
420 | #define NV_TXRX_RESET_DELAY 4 | 430 | #define NV_TXRX_RESET_DELAY 4 |
@@ -431,6 +441,7 @@ typedef union _ring_type { | |||
431 | #define NV_MIIBUSY_DELAY 50 | 441 | #define NV_MIIBUSY_DELAY 50 |
432 | #define NV_MIIPHY_DELAY 10 | 442 | #define NV_MIIPHY_DELAY 10 |
433 | #define NV_MIIPHY_DELAYMAX 10000 | 443 | #define NV_MIIPHY_DELAYMAX 10000 |
444 | #define NV_MAC_RESET_DELAY 64 | ||
434 | 445 | ||
435 | #define NV_WAKEUPPATTERNS 5 | 446 | #define NV_WAKEUPPATTERNS 5 |
436 | #define NV_WAKEUPMASKENTRIES 4 | 447 | #define NV_WAKEUPMASKENTRIES 4 |
@@ -552,6 +563,8 @@ struct fe_priv { | |||
552 | u32 desc_ver; | 563 | u32 desc_ver; |
553 | u32 txrxctl_bits; | 564 | u32 txrxctl_bits; |
554 | u32 vlanctl_bits; | 565 | u32 vlanctl_bits; |
566 | u32 driver_data; | ||
567 | u32 register_size; | ||
555 | 568 | ||
556 | void __iomem *base; | 569 | void __iomem *base; |
557 | 570 | ||
@@ -698,6 +711,72 @@ static void setup_hw_rings(struct net_device *dev, int rxtx_flags) | |||
698 | } | 711 | } |
699 | } | 712 | } |
700 | 713 | ||
714 | static int using_multi_irqs(struct net_device *dev) | ||
715 | { | ||
716 | struct fe_priv *np = get_nvpriv(dev); | ||
717 | |||
718 | if (!(np->msi_flags & NV_MSI_X_ENABLED) || | ||
719 | ((np->msi_flags & NV_MSI_X_ENABLED) && | ||
720 | ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) | ||
721 | return 0; | ||
722 | else | ||
723 | return 1; | ||
724 | } | ||
725 | |||
726 | static void nv_enable_irq(struct net_device *dev) | ||
727 | { | ||
728 | struct fe_priv *np = get_nvpriv(dev); | ||
729 | |||
730 | if (!using_multi_irqs(dev)) { | ||
731 | if (np->msi_flags & NV_MSI_X_ENABLED) | ||
732 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); | ||
733 | else | ||
734 | enable_irq(dev->irq); | ||
735 | } else { | ||
736 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); | ||
737 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); | ||
738 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); | ||
739 | } | ||
740 | } | ||
741 | |||
742 | static void nv_disable_irq(struct net_device *dev) | ||
743 | { | ||
744 | struct fe_priv *np = get_nvpriv(dev); | ||
745 | |||
746 | if (!using_multi_irqs(dev)) { | ||
747 | if (np->msi_flags & NV_MSI_X_ENABLED) | ||
748 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); | ||
749 | else | ||
750 | disable_irq(dev->irq); | ||
751 | } else { | ||
752 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); | ||
753 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); | ||
754 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); | ||
755 | } | ||
756 | } | ||
757 | |||
758 | /* In MSIX mode, a write to irqmask behaves as XOR */ | ||
759 | static void nv_enable_hw_interrupts(struct net_device *dev, u32 mask) | ||
760 | { | ||
761 | u8 __iomem *base = get_hwbase(dev); | ||
762 | |||
763 | writel(mask, base + NvRegIrqMask); | ||
764 | } | ||
765 | |||
766 | static void nv_disable_hw_interrupts(struct net_device *dev, u32 mask) | ||
767 | { | ||
768 | struct fe_priv *np = get_nvpriv(dev); | ||
769 | u8 __iomem *base = get_hwbase(dev); | ||
770 | |||
771 | if (np->msi_flags & NV_MSI_X_ENABLED) { | ||
772 | writel(mask, base + NvRegIrqMask); | ||
773 | } else { | ||
774 | if (np->msi_flags & NV_MSI_ENABLED) | ||
775 | writel(0, base + NvRegMSIIrqMask); | ||
776 | writel(0, base + NvRegIrqMask); | ||
777 | } | ||
778 | } | ||
779 | |||
701 | #define MII_READ (-1) | 780 | #define MII_READ (-1) |
702 | /* mii_rw: read/write a register on the PHY. | 781 | /* mii_rw: read/write a register on the PHY. |
703 | * | 782 | * |
@@ -919,6 +998,24 @@ static void nv_txrx_reset(struct net_device *dev) | |||
919 | pci_push(base); | 998 | pci_push(base); |
920 | } | 999 | } |
921 | 1000 | ||
1001 | static void nv_mac_reset(struct net_device *dev) | ||
1002 | { | ||
1003 | struct fe_priv *np = netdev_priv(dev); | ||
1004 | u8 __iomem *base = get_hwbase(dev); | ||
1005 | |||
1006 | dprintk(KERN_DEBUG "%s: nv_mac_reset\n", dev->name); | ||
1007 | writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl); | ||
1008 | pci_push(base); | ||
1009 | writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset); | ||
1010 | pci_push(base); | ||
1011 | udelay(NV_MAC_RESET_DELAY); | ||
1012 | writel(0, base + NvRegMacReset); | ||
1013 | pci_push(base); | ||
1014 | udelay(NV_MAC_RESET_DELAY); | ||
1015 | writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl); | ||
1016 | pci_push(base); | ||
1017 | } | ||
1018 | |||
922 | /* | 1019 | /* |
923 | * nv_get_stats: dev->get_stats function | 1020 | * nv_get_stats: dev->get_stats function |
924 | * Get latest stats value from the nic. | 1021 | * Get latest stats value from the nic. |
@@ -989,24 +1086,25 @@ static void nv_do_rx_refill(unsigned long data) | |||
989 | struct net_device *dev = (struct net_device *) data; | 1086 | struct net_device *dev = (struct net_device *) data; |
990 | struct fe_priv *np = netdev_priv(dev); | 1087 | struct fe_priv *np = netdev_priv(dev); |
991 | 1088 | ||
992 | 1089 | if (!using_multi_irqs(dev)) { | |
993 | if (!(np->msi_flags & NV_MSI_X_ENABLED) || | 1090 | if (np->msi_flags & NV_MSI_X_ENABLED) |
994 | ((np->msi_flags & NV_MSI_X_ENABLED) && | 1091 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); |
995 | ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { | 1092 | else |
996 | disable_irq(dev->irq); | 1093 | disable_irq(dev->irq); |
997 | } else { | 1094 | } else { |
998 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); | 1095 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); |
999 | } | 1096 | } |
1000 | if (nv_alloc_rx(dev)) { | 1097 | if (nv_alloc_rx(dev)) { |
1001 | spin_lock(&np->lock); | 1098 | spin_lock_irq(&np->lock); |
1002 | if (!np->in_shutdown) | 1099 | if (!np->in_shutdown) |
1003 | mod_timer(&np->oom_kick, jiffies + OOM_REFILL); | 1100 | mod_timer(&np->oom_kick, jiffies + OOM_REFILL); |
1004 | spin_unlock(&np->lock); | 1101 | spin_unlock_irq(&np->lock); |
1005 | } | 1102 | } |
1006 | if (!(np->msi_flags & NV_MSI_X_ENABLED) || | 1103 | if (!using_multi_irqs(dev)) { |
1007 | ((np->msi_flags & NV_MSI_X_ENABLED) && | 1104 | if (np->msi_flags & NV_MSI_X_ENABLED) |
1008 | ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { | 1105 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); |
1009 | enable_irq(dev->irq); | 1106 | else |
1107 | enable_irq(dev->irq); | ||
1010 | } else { | 1108 | } else { |
1011 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); | 1109 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); |
1012 | } | 1110 | } |
@@ -1331,7 +1429,7 @@ static void nv_tx_timeout(struct net_device *dev) | |||
1331 | dev->name, (unsigned long)np->ring_addr, | 1429 | dev->name, (unsigned long)np->ring_addr, |
1332 | np->next_tx, np->nic_tx); | 1430 | np->next_tx, np->nic_tx); |
1333 | printk(KERN_INFO "%s: Dumping tx registers\n", dev->name); | 1431 | printk(KERN_INFO "%s: Dumping tx registers\n", dev->name); |
1334 | for (i=0;i<0x400;i+= 32) { | 1432 | for (i=0;i<=np->register_size;i+= 32) { |
1335 | printk(KERN_INFO "%3x: %08x %08x %08x %08x %08x %08x %08x %08x\n", | 1433 | printk(KERN_INFO "%3x: %08x %08x %08x %08x %08x %08x %08x %08x\n", |
1336 | i, | 1434 | i, |
1337 | readl(base + i + 0), readl(base + i + 4), | 1435 | readl(base + i + 0), readl(base + i + 4), |
@@ -1638,15 +1736,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) | |||
1638 | * guessed, there is probably a simpler approach. | 1736 | * guessed, there is probably a simpler approach. |
1639 | * Changing the MTU is a rare event, it shouldn't matter. | 1737 | * Changing the MTU is a rare event, it shouldn't matter. |
1640 | */ | 1738 | */ |
1641 | if (!(np->msi_flags & NV_MSI_X_ENABLED) || | 1739 | nv_disable_irq(dev); |
1642 | ((np->msi_flags & NV_MSI_X_ENABLED) && | ||
1643 | ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { | ||
1644 | disable_irq(dev->irq); | ||
1645 | } else { | ||
1646 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); | ||
1647 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); | ||
1648 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); | ||
1649 | } | ||
1650 | spin_lock_bh(&dev->xmit_lock); | 1740 | spin_lock_bh(&dev->xmit_lock); |
1651 | spin_lock(&np->lock); | 1741 | spin_lock(&np->lock); |
1652 | /* stop engines */ | 1742 | /* stop engines */ |
@@ -1679,15 +1769,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) | |||
1679 | nv_start_tx(dev); | 1769 | nv_start_tx(dev); |
1680 | spin_unlock(&np->lock); | 1770 | spin_unlock(&np->lock); |
1681 | spin_unlock_bh(&dev->xmit_lock); | 1771 | spin_unlock_bh(&dev->xmit_lock); |
1682 | if (!(np->msi_flags & NV_MSI_X_ENABLED) || | 1772 | nv_enable_irq(dev); |
1683 | ((np->msi_flags & NV_MSI_X_ENABLED) && | ||
1684 | ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { | ||
1685 | enable_irq(dev->irq); | ||
1686 | } else { | ||
1687 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); | ||
1688 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); | ||
1689 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); | ||
1690 | } | ||
1691 | } | 1773 | } |
1692 | return 0; | 1774 | return 0; |
1693 | } | 1775 | } |
@@ -2078,16 +2160,16 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs) | |||
2078 | if (!(events & np->irqmask)) | 2160 | if (!(events & np->irqmask)) |
2079 | break; | 2161 | break; |
2080 | 2162 | ||
2081 | spin_lock(&np->lock); | 2163 | spin_lock_irq(&np->lock); |
2082 | nv_tx_done(dev); | 2164 | nv_tx_done(dev); |
2083 | spin_unlock(&np->lock); | 2165 | spin_unlock_irq(&np->lock); |
2084 | 2166 | ||
2085 | if (events & (NVREG_IRQ_TX_ERR)) { | 2167 | if (events & (NVREG_IRQ_TX_ERR)) { |
2086 | dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", | 2168 | dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", |
2087 | dev->name, events); | 2169 | dev->name, events); |
2088 | } | 2170 | } |
2089 | if (i > max_interrupt_work) { | 2171 | if (i > max_interrupt_work) { |
2090 | spin_lock(&np->lock); | 2172 | spin_lock_irq(&np->lock); |
2091 | /* disable interrupts on the nic */ | 2173 | /* disable interrupts on the nic */ |
2092 | writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask); | 2174 | writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask); |
2093 | pci_push(base); | 2175 | pci_push(base); |
@@ -2097,7 +2179,7 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs) | |||
2097 | mod_timer(&np->nic_poll, jiffies + POLL_WAIT); | 2179 | mod_timer(&np->nic_poll, jiffies + POLL_WAIT); |
2098 | } | 2180 | } |
2099 | printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i); | 2181 | printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i); |
2100 | spin_unlock(&np->lock); | 2182 | spin_unlock_irq(&np->lock); |
2101 | break; | 2183 | break; |
2102 | } | 2184 | } |
2103 | 2185 | ||
@@ -2127,14 +2209,14 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs) | |||
2127 | 2209 | ||
2128 | nv_rx_process(dev); | 2210 | nv_rx_process(dev); |
2129 | if (nv_alloc_rx(dev)) { | 2211 | if (nv_alloc_rx(dev)) { |
2130 | spin_lock(&np->lock); | 2212 | spin_lock_irq(&np->lock); |
2131 | if (!np->in_shutdown) | 2213 | if (!np->in_shutdown) |
2132 | mod_timer(&np->oom_kick, jiffies + OOM_REFILL); | 2214 | mod_timer(&np->oom_kick, jiffies + OOM_REFILL); |
2133 | spin_unlock(&np->lock); | 2215 | spin_unlock_irq(&np->lock); |
2134 | } | 2216 | } |
2135 | 2217 | ||
2136 | if (i > max_interrupt_work) { | 2218 | if (i > max_interrupt_work) { |
2137 | spin_lock(&np->lock); | 2219 | spin_lock_irq(&np->lock); |
2138 | /* disable interrupts on the nic */ | 2220 | /* disable interrupts on the nic */ |
2139 | writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); | 2221 | writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); |
2140 | pci_push(base); | 2222 | pci_push(base); |
@@ -2144,7 +2226,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs) | |||
2144 | mod_timer(&np->nic_poll, jiffies + POLL_WAIT); | 2226 | mod_timer(&np->nic_poll, jiffies + POLL_WAIT); |
2145 | } | 2227 | } |
2146 | printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i); | 2228 | printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i); |
2147 | spin_unlock(&np->lock); | 2229 | spin_unlock_irq(&np->lock); |
2148 | break; | 2230 | break; |
2149 | } | 2231 | } |
2150 | 2232 | ||
@@ -2173,14 +2255,14 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs) | |||
2173 | break; | 2255 | break; |
2174 | 2256 | ||
2175 | if (events & NVREG_IRQ_LINK) { | 2257 | if (events & NVREG_IRQ_LINK) { |
2176 | spin_lock(&np->lock); | 2258 | spin_lock_irq(&np->lock); |
2177 | nv_link_irq(dev); | 2259 | nv_link_irq(dev); |
2178 | spin_unlock(&np->lock); | 2260 | spin_unlock_irq(&np->lock); |
2179 | } | 2261 | } |
2180 | if (np->need_linktimer && time_after(jiffies, np->link_timeout)) { | 2262 | if (np->need_linktimer && time_after(jiffies, np->link_timeout)) { |
2181 | spin_lock(&np->lock); | 2263 | spin_lock_irq(&np->lock); |
2182 | nv_linkchange(dev); | 2264 | nv_linkchange(dev); |
2183 | spin_unlock(&np->lock); | 2265 | spin_unlock_irq(&np->lock); |
2184 | np->link_timeout = jiffies + LINK_TIMEOUT; | 2266 | np->link_timeout = jiffies + LINK_TIMEOUT; |
2185 | } | 2267 | } |
2186 | if (events & (NVREG_IRQ_UNKNOWN)) { | 2268 | if (events & (NVREG_IRQ_UNKNOWN)) { |
@@ -2188,7 +2270,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs) | |||
2188 | dev->name, events); | 2270 | dev->name, events); |
2189 | } | 2271 | } |
2190 | if (i > max_interrupt_work) { | 2272 | if (i > max_interrupt_work) { |
2191 | spin_lock(&np->lock); | 2273 | spin_lock_irq(&np->lock); |
2192 | /* disable interrupts on the nic */ | 2274 | /* disable interrupts on the nic */ |
2193 | writel(NVREG_IRQ_OTHER, base + NvRegIrqMask); | 2275 | writel(NVREG_IRQ_OTHER, base + NvRegIrqMask); |
2194 | pci_push(base); | 2276 | pci_push(base); |
@@ -2198,7 +2280,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs) | |||
2198 | mod_timer(&np->nic_poll, jiffies + POLL_WAIT); | 2280 | mod_timer(&np->nic_poll, jiffies + POLL_WAIT); |
2199 | } | 2281 | } |
2200 | printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i); | 2282 | printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i); |
2201 | spin_unlock(&np->lock); | 2283 | spin_unlock_irq(&np->lock); |
2202 | break; | 2284 | break; |
2203 | } | 2285 | } |
2204 | 2286 | ||
@@ -2221,10 +2303,11 @@ static void nv_do_nic_poll(unsigned long data) | |||
2221 | * nv_nic_irq because that may decide to do otherwise | 2303 | * nv_nic_irq because that may decide to do otherwise |
2222 | */ | 2304 | */ |
2223 | 2305 | ||
2224 | if (!(np->msi_flags & NV_MSI_X_ENABLED) || | 2306 | if (!using_multi_irqs(dev)) { |
2225 | ((np->msi_flags & NV_MSI_X_ENABLED) && | 2307 | if (np->msi_flags & NV_MSI_X_ENABLED) |
2226 | ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { | 2308 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); |
2227 | disable_irq(dev->irq); | 2309 | else |
2310 | disable_irq(dev->irq); | ||
2228 | mask = np->irqmask; | 2311 | mask = np->irqmask; |
2229 | } else { | 2312 | } else { |
2230 | if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) { | 2313 | if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) { |
@@ -2247,11 +2330,12 @@ static void nv_do_nic_poll(unsigned long data) | |||
2247 | writel(mask, base + NvRegIrqMask); | 2330 | writel(mask, base + NvRegIrqMask); |
2248 | pci_push(base); | 2331 | pci_push(base); |
2249 | 2332 | ||
2250 | if (!(np->msi_flags & NV_MSI_X_ENABLED) || | 2333 | if (!using_multi_irqs(dev)) { |
2251 | ((np->msi_flags & NV_MSI_X_ENABLED) && | ||
2252 | ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { | ||
2253 | nv_nic_irq((int) 0, (void *) data, (struct pt_regs *) NULL); | 2334 | nv_nic_irq((int) 0, (void *) data, (struct pt_regs *) NULL); |
2254 | enable_irq(dev->irq); | 2335 | if (np->msi_flags & NV_MSI_X_ENABLED) |
2336 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); | ||
2337 | else | ||
2338 | enable_irq(dev->irq); | ||
2255 | } else { | 2339 | } else { |
2256 | if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) { | 2340 | if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) { |
2257 | nv_nic_irq_rx((int) 0, (void *) data, (struct pt_regs *) NULL); | 2341 | nv_nic_irq_rx((int) 0, (void *) data, (struct pt_regs *) NULL); |
@@ -2488,11 +2572,11 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
2488 | } | 2572 | } |
2489 | 2573 | ||
2490 | #define FORCEDETH_REGS_VER 1 | 2574 | #define FORCEDETH_REGS_VER 1 |
2491 | #define FORCEDETH_REGS_SIZE 0x400 /* 256 32-bit registers */ | ||
2492 | 2575 | ||
2493 | static int nv_get_regs_len(struct net_device *dev) | 2576 | static int nv_get_regs_len(struct net_device *dev) |
2494 | { | 2577 | { |
2495 | return FORCEDETH_REGS_SIZE; | 2578 | struct fe_priv *np = netdev_priv(dev); |
2579 | return np->register_size; | ||
2496 | } | 2580 | } |
2497 | 2581 | ||
2498 | static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf) | 2582 | static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf) |
@@ -2504,7 +2588,7 @@ static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void | |||
2504 | 2588 | ||
2505 | regs->version = FORCEDETH_REGS_VER; | 2589 | regs->version = FORCEDETH_REGS_VER; |
2506 | spin_lock_irq(&np->lock); | 2590 | spin_lock_irq(&np->lock); |
2507 | for (i=0;i<FORCEDETH_REGS_SIZE/sizeof(u32);i++) | 2591 | for (i = 0;i <= np->register_size/sizeof(u32); i++) |
2508 | rbuf[i] = readl(base + i*sizeof(u32)); | 2592 | rbuf[i] = readl(base + i*sizeof(u32)); |
2509 | spin_unlock_irq(&np->lock); | 2593 | spin_unlock_irq(&np->lock); |
2510 | } | 2594 | } |
@@ -2598,6 +2682,113 @@ static void set_msix_vector_map(struct net_device *dev, u32 vector, u32 irqmask) | |||
2598 | writel(readl(base + NvRegMSIXMap1) | msixmap, base + NvRegMSIXMap1); | 2682 | writel(readl(base + NvRegMSIXMap1) | msixmap, base + NvRegMSIXMap1); |
2599 | } | 2683 | } |
2600 | 2684 | ||
2685 | static int nv_request_irq(struct net_device *dev) | ||
2686 | { | ||
2687 | struct fe_priv *np = get_nvpriv(dev); | ||
2688 | u8 __iomem *base = get_hwbase(dev); | ||
2689 | int ret = 1; | ||
2690 | int i; | ||
2691 | |||
2692 | if (np->msi_flags & NV_MSI_X_CAPABLE) { | ||
2693 | for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { | ||
2694 | np->msi_x_entry[i].entry = i; | ||
2695 | } | ||
2696 | if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) { | ||
2697 | np->msi_flags |= NV_MSI_X_ENABLED; | ||
2698 | if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) { | ||
2699 | /* Request irq for rx handling */ | ||
2700 | if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, SA_SHIRQ, dev->name, dev) != 0) { | ||
2701 | printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret); | ||
2702 | pci_disable_msix(np->pci_dev); | ||
2703 | np->msi_flags &= ~NV_MSI_X_ENABLED; | ||
2704 | goto out_err; | ||
2705 | } | ||
2706 | /* Request irq for tx handling */ | ||
2707 | if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, SA_SHIRQ, dev->name, dev) != 0) { | ||
2708 | printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret); | ||
2709 | pci_disable_msix(np->pci_dev); | ||
2710 | np->msi_flags &= ~NV_MSI_X_ENABLED; | ||
2711 | goto out_free_rx; | ||
2712 | } | ||
2713 | /* Request irq for link and timer handling */ | ||
2714 | if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, SA_SHIRQ, dev->name, dev) != 0) { | ||
2715 | printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret); | ||
2716 | pci_disable_msix(np->pci_dev); | ||
2717 | np->msi_flags &= ~NV_MSI_X_ENABLED; | ||
2718 | goto out_free_tx; | ||
2719 | } | ||
2720 | /* map interrupts to their respective vector */ | ||
2721 | writel(0, base + NvRegMSIXMap0); | ||
2722 | writel(0, base + NvRegMSIXMap1); | ||
2723 | set_msix_vector_map(dev, NV_MSI_X_VECTOR_RX, NVREG_IRQ_RX_ALL); | ||
2724 | set_msix_vector_map(dev, NV_MSI_X_VECTOR_TX, NVREG_IRQ_TX_ALL); | ||
2725 | set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER); | ||
2726 | } else { | ||
2727 | /* Request irq for all interrupts */ | ||
2728 | if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) { | ||
2729 | printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); | ||
2730 | pci_disable_msix(np->pci_dev); | ||
2731 | np->msi_flags &= ~NV_MSI_X_ENABLED; | ||
2732 | goto out_err; | ||
2733 | } | ||
2734 | |||
2735 | /* map interrupts to vector 0 */ | ||
2736 | writel(0, base + NvRegMSIXMap0); | ||
2737 | writel(0, base + NvRegMSIXMap1); | ||
2738 | } | ||
2739 | } | ||
2740 | } | ||
2741 | if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) { | ||
2742 | if ((ret = pci_enable_msi(np->pci_dev)) == 0) { | ||
2743 | np->msi_flags |= NV_MSI_ENABLED; | ||
2744 | if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) { | ||
2745 | printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); | ||
2746 | pci_disable_msi(np->pci_dev); | ||
2747 | np->msi_flags &= ~NV_MSI_ENABLED; | ||
2748 | goto out_err; | ||
2749 | } | ||
2750 | |||
2751 | /* map interrupts to vector 0 */ | ||
2752 | writel(0, base + NvRegMSIMap0); | ||
2753 | writel(0, base + NvRegMSIMap1); | ||
2754 | /* enable msi vector 0 */ | ||
2755 | writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask); | ||
2756 | } | ||
2757 | } | ||
2758 | if (ret != 0) { | ||
2759 | if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) | ||
2760 | goto out_err; | ||
2761 | } | ||
2762 | |||
2763 | return 0; | ||
2764 | out_free_tx: | ||
2765 | free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, dev); | ||
2766 | out_free_rx: | ||
2767 | free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, dev); | ||
2768 | out_err: | ||
2769 | return 1; | ||
2770 | } | ||
2771 | |||
2772 | static void nv_free_irq(struct net_device *dev) | ||
2773 | { | ||
2774 | struct fe_priv *np = get_nvpriv(dev); | ||
2775 | int i; | ||
2776 | |||
2777 | if (np->msi_flags & NV_MSI_X_ENABLED) { | ||
2778 | for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { | ||
2779 | free_irq(np->msi_x_entry[i].vector, dev); | ||
2780 | } | ||
2781 | pci_disable_msix(np->pci_dev); | ||
2782 | np->msi_flags &= ~NV_MSI_X_ENABLED; | ||
2783 | } else { | ||
2784 | free_irq(np->pci_dev->irq, dev); | ||
2785 | if (np->msi_flags & NV_MSI_ENABLED) { | ||
2786 | pci_disable_msi(np->pci_dev); | ||
2787 | np->msi_flags &= ~NV_MSI_ENABLED; | ||
2788 | } | ||
2789 | } | ||
2790 | } | ||
2791 | |||
2601 | static int nv_open(struct net_device *dev) | 2792 | static int nv_open(struct net_device *dev) |
2602 | { | 2793 | { |
2603 | struct fe_priv *np = netdev_priv(dev); | 2794 | struct fe_priv *np = netdev_priv(dev); |
@@ -2608,6 +2799,8 @@ static int nv_open(struct net_device *dev) | |||
2608 | dprintk(KERN_DEBUG "nv_open: begin\n"); | 2799 | dprintk(KERN_DEBUG "nv_open: begin\n"); |
2609 | 2800 | ||
2610 | /* 1) erase previous misconfiguration */ | 2801 | /* 1) erase previous misconfiguration */ |
2802 | if (np->driver_data & DEV_HAS_POWER_CNTRL) | ||
2803 | nv_mac_reset(dev); | ||
2611 | /* 4.1-1: stop adapter: ignored, 4.3 seems to be overkill */ | 2804 | /* 4.1-1: stop adapter: ignored, 4.3 seems to be overkill */ |
2612 | writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA); | 2805 | writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA); |
2613 | writel(0, base + NvRegMulticastAddrB); | 2806 | writel(0, base + NvRegMulticastAddrB); |
@@ -2688,12 +2881,16 @@ static int nv_open(struct net_device *dev) | |||
2688 | udelay(10); | 2881 | udelay(10); |
2689 | writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState); | 2882 | writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState); |
2690 | 2883 | ||
2691 | writel(0, base + NvRegIrqMask); | 2884 | nv_disable_hw_interrupts(dev, np->irqmask); |
2692 | pci_push(base); | 2885 | pci_push(base); |
2693 | writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus); | 2886 | writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus); |
2694 | writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); | 2887 | writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); |
2695 | pci_push(base); | 2888 | pci_push(base); |
2696 | 2889 | ||
2890 | if (nv_request_irq(dev)) { | ||
2891 | goto out_drain; | ||
2892 | } | ||
2893 | |||
2697 | if (np->msi_flags & NV_MSI_X_CAPABLE) { | 2894 | if (np->msi_flags & NV_MSI_X_CAPABLE) { |
2698 | for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { | 2895 | for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { |
2699 | np->msi_x_entry[i].entry = i; | 2896 | np->msi_x_entry[i].entry = i; |
@@ -2767,7 +2964,7 @@ static int nv_open(struct net_device *dev) | |||
2767 | } | 2964 | } |
2768 | 2965 | ||
2769 | /* ask for interrupts */ | 2966 | /* ask for interrupts */ |
2770 | writel(np->irqmask, base + NvRegIrqMask); | 2967 | nv_enable_hw_interrupts(dev, np->irqmask); |
2771 | 2968 | ||
2772 | spin_lock_irq(&np->lock); | 2969 | spin_lock_irq(&np->lock); |
2773 | writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA); | 2970 | writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA); |
@@ -2811,7 +3008,6 @@ static int nv_close(struct net_device *dev) | |||
2811 | { | 3008 | { |
2812 | struct fe_priv *np = netdev_priv(dev); | 3009 | struct fe_priv *np = netdev_priv(dev); |
2813 | u8 __iomem *base; | 3010 | u8 __iomem *base; |
2814 | int i; | ||
2815 | 3011 | ||
2816 | spin_lock_irq(&np->lock); | 3012 | spin_lock_irq(&np->lock); |
2817 | np->in_shutdown = 1; | 3013 | np->in_shutdown = 1; |
@@ -2829,31 +3025,13 @@ static int nv_close(struct net_device *dev) | |||
2829 | 3025 | ||
2830 | /* disable interrupts on the nic or we will lock up */ | 3026 | /* disable interrupts on the nic or we will lock up */ |
2831 | base = get_hwbase(dev); | 3027 | base = get_hwbase(dev); |
2832 | if (np->msi_flags & NV_MSI_X_ENABLED) { | 3028 | nv_disable_hw_interrupts(dev, np->irqmask); |
2833 | writel(np->irqmask, base + NvRegIrqMask); | ||
2834 | } else { | ||
2835 | if (np->msi_flags & NV_MSI_ENABLED) | ||
2836 | writel(0, base + NvRegMSIIrqMask); | ||
2837 | writel(0, base + NvRegIrqMask); | ||
2838 | } | ||
2839 | pci_push(base); | 3029 | pci_push(base); |
2840 | dprintk(KERN_INFO "%s: Irqmask is zero again\n", dev->name); | 3030 | dprintk(KERN_INFO "%s: Irqmask is zero again\n", dev->name); |
2841 | 3031 | ||
2842 | spin_unlock_irq(&np->lock); | 3032 | spin_unlock_irq(&np->lock); |
2843 | 3033 | ||
2844 | if (np->msi_flags & NV_MSI_X_ENABLED) { | 3034 | nv_free_irq(dev); |
2845 | for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { | ||
2846 | free_irq(np->msi_x_entry[i].vector, dev); | ||
2847 | } | ||
2848 | pci_disable_msix(np->pci_dev); | ||
2849 | np->msi_flags &= ~NV_MSI_X_ENABLED; | ||
2850 | } else { | ||
2851 | free_irq(np->pci_dev->irq, dev); | ||
2852 | if (np->msi_flags & NV_MSI_ENABLED) { | ||
2853 | pci_disable_msi(np->pci_dev); | ||
2854 | np->msi_flags &= ~NV_MSI_ENABLED; | ||
2855 | } | ||
2856 | } | ||
2857 | 3035 | ||
2858 | drain_ring(dev); | 3036 | drain_ring(dev); |
2859 | 3037 | ||
@@ -2878,6 +3056,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
2878 | unsigned long addr; | 3056 | unsigned long addr; |
2879 | u8 __iomem *base; | 3057 | u8 __iomem *base; |
2880 | int err, i; | 3058 | int err, i; |
3059 | u32 powerstate; | ||
2881 | 3060 | ||
2882 | dev = alloc_etherdev(sizeof(struct fe_priv)); | 3061 | dev = alloc_etherdev(sizeof(struct fe_priv)); |
2883 | err = -ENOMEM; | 3062 | err = -ENOMEM; |
@@ -2910,6 +3089,11 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
2910 | if (err < 0) | 3089 | if (err < 0) |
2911 | goto out_disable; | 3090 | goto out_disable; |
2912 | 3091 | ||
3092 | if (id->driver_data & (DEV_HAS_VLAN|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL)) | ||
3093 | np->register_size = NV_PCI_REGSZ_VER2; | ||
3094 | else | ||
3095 | np->register_size = NV_PCI_REGSZ_VER1; | ||
3096 | |||
2913 | err = -EINVAL; | 3097 | err = -EINVAL; |
2914 | addr = 0; | 3098 | addr = 0; |
2915 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { | 3099 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { |
@@ -2918,7 +3102,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
2918 | pci_resource_len(pci_dev, i), | 3102 | pci_resource_len(pci_dev, i), |
2919 | pci_resource_flags(pci_dev, i)); | 3103 | pci_resource_flags(pci_dev, i)); |
2920 | if (pci_resource_flags(pci_dev, i) & IORESOURCE_MEM && | 3104 | if (pci_resource_flags(pci_dev, i) & IORESOURCE_MEM && |
2921 | pci_resource_len(pci_dev, i) >= NV_PCI_REGSZ) { | 3105 | pci_resource_len(pci_dev, i) >= np->register_size) { |
2922 | addr = pci_resource_start(pci_dev, i); | 3106 | addr = pci_resource_start(pci_dev, i); |
2923 | break; | 3107 | break; |
2924 | } | 3108 | } |
@@ -2929,24 +3113,25 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
2929 | goto out_relreg; | 3113 | goto out_relreg; |
2930 | } | 3114 | } |
2931 | 3115 | ||
3116 | /* copy of driver data */ | ||
3117 | np->driver_data = id->driver_data; | ||
3118 | |||
2932 | /* handle different descriptor versions */ | 3119 | /* handle different descriptor versions */ |
2933 | if (id->driver_data & DEV_HAS_HIGH_DMA) { | 3120 | if (id->driver_data & DEV_HAS_HIGH_DMA) { |
2934 | /* packet format 3: supports 40-bit addressing */ | 3121 | /* packet format 3: supports 40-bit addressing */ |
2935 | np->desc_ver = DESC_VER_3; | 3122 | np->desc_ver = DESC_VER_3; |
3123 | np->txrxctl_bits = NVREG_TXRXCTL_DESC_3; | ||
2936 | if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) { | 3124 | if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) { |
2937 | printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n", | 3125 | printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n", |
2938 | pci_name(pci_dev)); | 3126 | pci_name(pci_dev)); |
2939 | } else { | 3127 | } else { |
2940 | if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) { | 3128 | dev->features |= NETIF_F_HIGHDMA; |
2941 | printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n", | 3129 | printk(KERN_INFO "forcedeth: using HIGHDMA\n"); |
2942 | pci_name(pci_dev)); | 3130 | } |
2943 | goto out_relreg; | 3131 | if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) { |
2944 | } else { | 3132 | printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n", |
2945 | dev->features |= NETIF_F_HIGHDMA; | 3133 | pci_name(pci_dev)); |
2946 | printk(KERN_INFO "forcedeth: using HIGHDMA\n"); | ||
2947 | } | ||
2948 | } | 3134 | } |
2949 | np->txrxctl_bits = NVREG_TXRXCTL_DESC_3; | ||
2950 | } else if (id->driver_data & DEV_HAS_LARGEDESC) { | 3135 | } else if (id->driver_data & DEV_HAS_LARGEDESC) { |
2951 | /* packet format 2: supports jumbo frames */ | 3136 | /* packet format 2: supports jumbo frames */ |
2952 | np->desc_ver = DESC_VER_2; | 3137 | np->desc_ver = DESC_VER_2; |
@@ -2986,7 +3171,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
2986 | } | 3171 | } |
2987 | 3172 | ||
2988 | err = -ENOMEM; | 3173 | err = -ENOMEM; |
2989 | np->base = ioremap(addr, NV_PCI_REGSZ); | 3174 | np->base = ioremap(addr, np->register_size); |
2990 | if (!np->base) | 3175 | if (!np->base) |
2991 | goto out_relreg; | 3176 | goto out_relreg; |
2992 | dev->base_addr = (unsigned long)np->base; | 3177 | dev->base_addr = (unsigned long)np->base; |
@@ -3062,6 +3247,20 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
3062 | writel(0, base + NvRegWakeUpFlags); | 3247 | writel(0, base + NvRegWakeUpFlags); |
3063 | np->wolenabled = 0; | 3248 | np->wolenabled = 0; |
3064 | 3249 | ||
3250 | if (id->driver_data & DEV_HAS_POWER_CNTRL) { | ||
3251 | u8 revision_id; | ||
3252 | pci_read_config_byte(pci_dev, PCI_REVISION_ID, &revision_id); | ||
3253 | |||
3254 | /* take phy and nic out of low power mode */ | ||
3255 | powerstate = readl(base + NvRegPowerState2); | ||
3256 | powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK; | ||
3257 | if ((id->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 || | ||
3258 | id->device == PCI_DEVICE_ID_NVIDIA_NVENET_13) && | ||
3259 | revision_id >= 0xA3) | ||
3260 | powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3; | ||
3261 | writel(powerstate, base + NvRegPowerState2); | ||
3262 | } | ||
3263 | |||
3065 | if (np->desc_ver == DESC_VER_1) { | 3264 | if (np->desc_ver == DESC_VER_1) { |
3066 | np->tx_flags = NV_TX_VALID; | 3265 | np->tx_flags = NV_TX_VALID; |
3067 | } else { | 3266 | } else { |
@@ -3223,19 +3422,19 @@ static struct pci_device_id pci_tbl[] = { | |||
3223 | }, | 3422 | }, |
3224 | { /* MCP51 Ethernet Controller */ | 3423 | { /* MCP51 Ethernet Controller */ |
3225 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12), | 3424 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12), |
3226 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA, | 3425 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL, |
3227 | }, | 3426 | }, |
3228 | { /* MCP51 Ethernet Controller */ | 3427 | { /* MCP51 Ethernet Controller */ |
3229 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_13), | 3428 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_13), |
3230 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA, | 3429 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL, |
3231 | }, | 3430 | }, |
3232 | { /* MCP55 Ethernet Controller */ | 3431 | { /* MCP55 Ethernet Controller */ |
3233 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14), | 3432 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14), |
3234 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X, | 3433 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL, |
3235 | }, | 3434 | }, |
3236 | { /* MCP55 Ethernet Controller */ | 3435 | { /* MCP55 Ethernet Controller */ |
3237 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15), | 3436 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15), |
3238 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X, | 3437 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL, |
3239 | }, | 3438 | }, |
3240 | {0,}, | 3439 | {0,}, |
3241 | }; | 3440 | }; |
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 771e25d8c417..218d31764c52 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
@@ -210,7 +210,8 @@ static int gfar_probe(struct platform_device *pdev) | |||
210 | goto regs_fail; | 210 | goto regs_fail; |
211 | } | 211 | } |
212 | 212 | ||
213 | spin_lock_init(&priv->lock); | 213 | spin_lock_init(&priv->txlock); |
214 | spin_lock_init(&priv->rxlock); | ||
214 | 215 | ||
215 | platform_set_drvdata(pdev, dev); | 216 | platform_set_drvdata(pdev, dev); |
216 | 217 | ||
@@ -515,11 +516,13 @@ void stop_gfar(struct net_device *dev) | |||
515 | phy_stop(priv->phydev); | 516 | phy_stop(priv->phydev); |
516 | 517 | ||
517 | /* Lock it down */ | 518 | /* Lock it down */ |
518 | spin_lock_irqsave(&priv->lock, flags); | 519 | spin_lock_irqsave(&priv->txlock, flags); |
520 | spin_lock(&priv->rxlock); | ||
519 | 521 | ||
520 | gfar_halt(dev); | 522 | gfar_halt(dev); |
521 | 523 | ||
522 | spin_unlock_irqrestore(&priv->lock, flags); | 524 | spin_unlock(&priv->rxlock); |
525 | spin_unlock_irqrestore(&priv->txlock, flags); | ||
523 | 526 | ||
524 | /* Free the IRQs */ | 527 | /* Free the IRQs */ |
525 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { | 528 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { |
@@ -605,14 +608,15 @@ void gfar_start(struct net_device *dev) | |||
605 | tempval |= DMACTRL_INIT_SETTINGS; | 608 | tempval |= DMACTRL_INIT_SETTINGS; |
606 | gfar_write(&priv->regs->dmactrl, tempval); | 609 | gfar_write(&priv->regs->dmactrl, tempval); |
607 | 610 | ||
608 | /* Clear THLT, so that the DMA starts polling now */ | ||
609 | gfar_write(®s->tstat, TSTAT_CLEAR_THALT); | ||
610 | |||
611 | /* Make sure we aren't stopped */ | 611 | /* Make sure we aren't stopped */ |
612 | tempval = gfar_read(&priv->regs->dmactrl); | 612 | tempval = gfar_read(&priv->regs->dmactrl); |
613 | tempval &= ~(DMACTRL_GRS | DMACTRL_GTS); | 613 | tempval &= ~(DMACTRL_GRS | DMACTRL_GTS); |
614 | gfar_write(&priv->regs->dmactrl, tempval); | 614 | gfar_write(&priv->regs->dmactrl, tempval); |
615 | 615 | ||
616 | /* Clear THLT/RHLT, so that the DMA starts polling now */ | ||
617 | gfar_write(®s->tstat, TSTAT_CLEAR_THALT); | ||
618 | gfar_write(®s->rstat, RSTAT_CLEAR_RHALT); | ||
619 | |||
616 | /* Unmask the interrupts we look for */ | 620 | /* Unmask the interrupts we look for */ |
617 | gfar_write(®s->imask, IMASK_DEFAULT); | 621 | gfar_write(®s->imask, IMASK_DEFAULT); |
618 | } | 622 | } |
@@ -928,12 +932,13 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
928 | struct txfcb *fcb = NULL; | 932 | struct txfcb *fcb = NULL; |
929 | struct txbd8 *txbdp; | 933 | struct txbd8 *txbdp; |
930 | u16 status; | 934 | u16 status; |
935 | unsigned long flags; | ||
931 | 936 | ||
932 | /* Update transmit stats */ | 937 | /* Update transmit stats */ |
933 | priv->stats.tx_bytes += skb->len; | 938 | priv->stats.tx_bytes += skb->len; |
934 | 939 | ||
935 | /* Lock priv now */ | 940 | /* Lock priv now */ |
936 | spin_lock_irq(&priv->lock); | 941 | spin_lock_irqsave(&priv->txlock, flags); |
937 | 942 | ||
938 | /* Point at the first free tx descriptor */ | 943 | /* Point at the first free tx descriptor */ |
939 | txbdp = priv->cur_tx; | 944 | txbdp = priv->cur_tx; |
@@ -1004,7 +1009,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1004 | gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT); | 1009 | gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT); |
1005 | 1010 | ||
1006 | /* Unlock priv */ | 1011 | /* Unlock priv */ |
1007 | spin_unlock_irq(&priv->lock); | 1012 | spin_unlock_irqrestore(&priv->txlock, flags); |
1008 | 1013 | ||
1009 | return 0; | 1014 | return 0; |
1010 | } | 1015 | } |
@@ -1049,7 +1054,7 @@ static void gfar_vlan_rx_register(struct net_device *dev, | |||
1049 | unsigned long flags; | 1054 | unsigned long flags; |
1050 | u32 tempval; | 1055 | u32 tempval; |
1051 | 1056 | ||
1052 | spin_lock_irqsave(&priv->lock, flags); | 1057 | spin_lock_irqsave(&priv->rxlock, flags); |
1053 | 1058 | ||
1054 | priv->vlgrp = grp; | 1059 | priv->vlgrp = grp; |
1055 | 1060 | ||
@@ -1076,7 +1081,7 @@ static void gfar_vlan_rx_register(struct net_device *dev, | |||
1076 | gfar_write(&priv->regs->rctrl, tempval); | 1081 | gfar_write(&priv->regs->rctrl, tempval); |
1077 | } | 1082 | } |
1078 | 1083 | ||
1079 | spin_unlock_irqrestore(&priv->lock, flags); | 1084 | spin_unlock_irqrestore(&priv->rxlock, flags); |
1080 | } | 1085 | } |
1081 | 1086 | ||
1082 | 1087 | ||
@@ -1085,12 +1090,12 @@ static void gfar_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) | |||
1085 | struct gfar_private *priv = netdev_priv(dev); | 1090 | struct gfar_private *priv = netdev_priv(dev); |
1086 | unsigned long flags; | 1091 | unsigned long flags; |
1087 | 1092 | ||
1088 | spin_lock_irqsave(&priv->lock, flags); | 1093 | spin_lock_irqsave(&priv->rxlock, flags); |
1089 | 1094 | ||
1090 | if (priv->vlgrp) | 1095 | if (priv->vlgrp) |
1091 | priv->vlgrp->vlan_devices[vid] = NULL; | 1096 | priv->vlgrp->vlan_devices[vid] = NULL; |
1092 | 1097 | ||
1093 | spin_unlock_irqrestore(&priv->lock, flags); | 1098 | spin_unlock_irqrestore(&priv->rxlock, flags); |
1094 | } | 1099 | } |
1095 | 1100 | ||
1096 | 1101 | ||
@@ -1179,7 +1184,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs) | |||
1179 | gfar_write(&priv->regs->ievent, IEVENT_TX_MASK); | 1184 | gfar_write(&priv->regs->ievent, IEVENT_TX_MASK); |
1180 | 1185 | ||
1181 | /* Lock priv */ | 1186 | /* Lock priv */ |
1182 | spin_lock(&priv->lock); | 1187 | spin_lock(&priv->txlock); |
1183 | bdp = priv->dirty_tx; | 1188 | bdp = priv->dirty_tx; |
1184 | while ((bdp->status & TXBD_READY) == 0) { | 1189 | while ((bdp->status & TXBD_READY) == 0) { |
1185 | /* If dirty_tx and cur_tx are the same, then either the */ | 1190 | /* If dirty_tx and cur_tx are the same, then either the */ |
@@ -1224,7 +1229,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs) | |||
1224 | else | 1229 | else |
1225 | gfar_write(&priv->regs->txic, 0); | 1230 | gfar_write(&priv->regs->txic, 0); |
1226 | 1231 | ||
1227 | spin_unlock(&priv->lock); | 1232 | spin_unlock(&priv->txlock); |
1228 | 1233 | ||
1229 | return IRQ_HANDLED; | 1234 | return IRQ_HANDLED; |
1230 | } | 1235 | } |
@@ -1305,9 +1310,10 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) | |||
1305 | { | 1310 | { |
1306 | struct net_device *dev = (struct net_device *) dev_id; | 1311 | struct net_device *dev = (struct net_device *) dev_id; |
1307 | struct gfar_private *priv = netdev_priv(dev); | 1312 | struct gfar_private *priv = netdev_priv(dev); |
1308 | |||
1309 | #ifdef CONFIG_GFAR_NAPI | 1313 | #ifdef CONFIG_GFAR_NAPI |
1310 | u32 tempval; | 1314 | u32 tempval; |
1315 | #else | ||
1316 | unsigned long flags; | ||
1311 | #endif | 1317 | #endif |
1312 | 1318 | ||
1313 | /* Clear IEVENT, so rx interrupt isn't called again | 1319 | /* Clear IEVENT, so rx interrupt isn't called again |
@@ -1330,7 +1336,7 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) | |||
1330 | } | 1336 | } |
1331 | #else | 1337 | #else |
1332 | 1338 | ||
1333 | spin_lock(&priv->lock); | 1339 | spin_lock_irqsave(&priv->rxlock, flags); |
1334 | gfar_clean_rx_ring(dev, priv->rx_ring_size); | 1340 | gfar_clean_rx_ring(dev, priv->rx_ring_size); |
1335 | 1341 | ||
1336 | /* If we are coalescing interrupts, update the timer */ | 1342 | /* If we are coalescing interrupts, update the timer */ |
@@ -1341,7 +1347,7 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) | |||
1341 | else | 1347 | else |
1342 | gfar_write(&priv->regs->rxic, 0); | 1348 | gfar_write(&priv->regs->rxic, 0); |
1343 | 1349 | ||
1344 | spin_unlock(&priv->lock); | 1350 | spin_unlock_irqrestore(&priv->rxlock, flags); |
1345 | #endif | 1351 | #endif |
1346 | 1352 | ||
1347 | return IRQ_HANDLED; | 1353 | return IRQ_HANDLED; |
@@ -1490,13 +1496,6 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) | |||
1490 | /* Update the current rxbd pointer to be the next one */ | 1496 | /* Update the current rxbd pointer to be the next one */ |
1491 | priv->cur_rx = bdp; | 1497 | priv->cur_rx = bdp; |
1492 | 1498 | ||
1493 | /* If no packets have arrived since the | ||
1494 | * last one we processed, clear the IEVENT RX and | ||
1495 | * BSY bits so that another interrupt won't be | ||
1496 | * generated when we set IMASK */ | ||
1497 | if (bdp->status & RXBD_EMPTY) | ||
1498 | gfar_write(&priv->regs->ievent, IEVENT_RX_MASK); | ||
1499 | |||
1500 | return howmany; | 1499 | return howmany; |
1501 | } | 1500 | } |
1502 | 1501 | ||
@@ -1516,7 +1515,7 @@ static int gfar_poll(struct net_device *dev, int *budget) | |||
1516 | rx_work_limit -= howmany; | 1515 | rx_work_limit -= howmany; |
1517 | *budget -= howmany; | 1516 | *budget -= howmany; |
1518 | 1517 | ||
1519 | if (rx_work_limit >= 0) { | 1518 | if (rx_work_limit > 0) { |
1520 | netif_rx_complete(dev); | 1519 | netif_rx_complete(dev); |
1521 | 1520 | ||
1522 | /* Clear the halt bit in RSTAT */ | 1521 | /* Clear the halt bit in RSTAT */ |
@@ -1533,7 +1532,8 @@ static int gfar_poll(struct net_device *dev, int *budget) | |||
1533 | gfar_write(&priv->regs->rxic, 0); | 1532 | gfar_write(&priv->regs->rxic, 0); |
1534 | } | 1533 | } |
1535 | 1534 | ||
1536 | return (rx_work_limit < 0) ? 1 : 0; | 1535 | /* Return 1 if there's more work to do */ |
1536 | return (rx_work_limit > 0) ? 0 : 1; | ||
1537 | } | 1537 | } |
1538 | #endif | 1538 | #endif |
1539 | 1539 | ||
@@ -1629,7 +1629,7 @@ static void adjust_link(struct net_device *dev) | |||
1629 | struct phy_device *phydev = priv->phydev; | 1629 | struct phy_device *phydev = priv->phydev; |
1630 | int new_state = 0; | 1630 | int new_state = 0; |
1631 | 1631 | ||
1632 | spin_lock_irqsave(&priv->lock, flags); | 1632 | spin_lock_irqsave(&priv->txlock, flags); |
1633 | if (phydev->link) { | 1633 | if (phydev->link) { |
1634 | u32 tempval = gfar_read(®s->maccfg2); | 1634 | u32 tempval = gfar_read(®s->maccfg2); |
1635 | u32 ecntrl = gfar_read(®s->ecntrl); | 1635 | u32 ecntrl = gfar_read(®s->ecntrl); |
@@ -1694,7 +1694,7 @@ static void adjust_link(struct net_device *dev) | |||
1694 | if (new_state && netif_msg_link(priv)) | 1694 | if (new_state && netif_msg_link(priv)) |
1695 | phy_print_status(phydev); | 1695 | phy_print_status(phydev); |
1696 | 1696 | ||
1697 | spin_unlock_irqrestore(&priv->lock, flags); | 1697 | spin_unlock_irqrestore(&priv->txlock, flags); |
1698 | } | 1698 | } |
1699 | 1699 | ||
1700 | /* Update the hash table based on the current list of multicast | 1700 | /* Update the hash table based on the current list of multicast |
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index d37d5401be6e..127c98cf3336 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h | |||
@@ -656,43 +656,62 @@ struct gfar { | |||
656 | * the buffer descriptor determines the actual condition. | 656 | * the buffer descriptor determines the actual condition. |
657 | */ | 657 | */ |
658 | struct gfar_private { | 658 | struct gfar_private { |
659 | /* pointers to arrays of skbuffs for tx and rx */ | 659 | /* Fields controlled by TX lock */ |
660 | spinlock_t txlock; | ||
661 | |||
662 | /* Pointer to the array of skbuffs */ | ||
660 | struct sk_buff ** tx_skbuff; | 663 | struct sk_buff ** tx_skbuff; |
661 | struct sk_buff ** rx_skbuff; | ||
662 | 664 | ||
663 | /* indices pointing to the next free sbk in skb arrays */ | 665 | /* next free skb in the array */ |
664 | u16 skb_curtx; | 666 | u16 skb_curtx; |
665 | u16 skb_currx; | ||
666 | 667 | ||
667 | /* index of the first skb which hasn't been transmitted | 668 | /* First skb in line to be transmitted */ |
668 | * yet. */ | ||
669 | u16 skb_dirtytx; | 669 | u16 skb_dirtytx; |
670 | 670 | ||
671 | /* Configuration info for the coalescing features */ | 671 | /* Configuration info for the coalescing features */ |
672 | unsigned char txcoalescing; | 672 | unsigned char txcoalescing; |
673 | unsigned short txcount; | 673 | unsigned short txcount; |
674 | unsigned short txtime; | 674 | unsigned short txtime; |
675 | |||
676 | /* Buffer descriptor pointers */ | ||
677 | struct txbd8 *tx_bd_base; /* First tx buffer descriptor */ | ||
678 | struct txbd8 *cur_tx; /* Next free ring entry */ | ||
679 | struct txbd8 *dirty_tx; /* First buffer in line | ||
680 | to be transmitted */ | ||
681 | unsigned int tx_ring_size; | ||
682 | |||
683 | /* RX Locked fields */ | ||
684 | spinlock_t rxlock; | ||
685 | |||
686 | /* skb array and index */ | ||
687 | struct sk_buff ** rx_skbuff; | ||
688 | u16 skb_currx; | ||
689 | |||
690 | /* RX Coalescing values */ | ||
675 | unsigned char rxcoalescing; | 691 | unsigned char rxcoalescing; |
676 | unsigned short rxcount; | 692 | unsigned short rxcount; |
677 | unsigned short rxtime; | 693 | unsigned short rxtime; |
678 | 694 | ||
679 | /* GFAR addresses */ | 695 | struct rxbd8 *rx_bd_base; /* First Rx buffers */ |
680 | struct rxbd8 *rx_bd_base; /* Base addresses of Rx and Tx Buffers */ | ||
681 | struct txbd8 *tx_bd_base; | ||
682 | struct rxbd8 *cur_rx; /* Next free rx ring entry */ | 696 | struct rxbd8 *cur_rx; /* Next free rx ring entry */ |
683 | struct txbd8 *cur_tx; /* Next free ring entry */ | 697 | |
684 | struct txbd8 *dirty_tx; /* The Ring entry to be freed. */ | 698 | /* RX parameters */ |
685 | struct gfar __iomem *regs; /* Pointer to the GFAR memory mapped Registers */ | 699 | unsigned int rx_ring_size; |
686 | u32 __iomem *hash_regs[16]; | ||
687 | int hash_width; | ||
688 | struct net_device_stats stats; /* linux network statistics */ | ||
689 | struct gfar_extra_stats extra_stats; | ||
690 | spinlock_t lock; | ||
691 | unsigned int rx_buffer_size; | 700 | unsigned int rx_buffer_size; |
692 | unsigned int rx_stash_size; | 701 | unsigned int rx_stash_size; |
693 | unsigned int rx_stash_index; | 702 | unsigned int rx_stash_index; |
694 | unsigned int tx_ring_size; | 703 | |
695 | unsigned int rx_ring_size; | 704 | struct vlan_group *vlgrp; |
705 | |||
706 | /* Unprotected fields */ | ||
707 | /* Pointer to the GFAR memory mapped Registers */ | ||
708 | struct gfar __iomem *regs; | ||
709 | |||
710 | /* Hash registers and their width */ | ||
711 | u32 __iomem *hash_regs[16]; | ||
712 | int hash_width; | ||
713 | |||
714 | /* global parameters */ | ||
696 | unsigned int fifo_threshold; | 715 | unsigned int fifo_threshold; |
697 | unsigned int fifo_starve; | 716 | unsigned int fifo_starve; |
698 | unsigned int fifo_starve_off; | 717 | unsigned int fifo_starve_off; |
@@ -702,13 +721,15 @@ struct gfar_private { | |||
702 | extended_hash:1, | 721 | extended_hash:1, |
703 | bd_stash_en:1; | 722 | bd_stash_en:1; |
704 | unsigned short padding; | 723 | unsigned short padding; |
705 | struct vlan_group *vlgrp; | 724 | |
706 | /* Info structure initialized by board setup code */ | ||
707 | unsigned int interruptTransmit; | 725 | unsigned int interruptTransmit; |
708 | unsigned int interruptReceive; | 726 | unsigned int interruptReceive; |
709 | unsigned int interruptError; | 727 | unsigned int interruptError; |
728 | |||
729 | /* info structure initialized by platform code */ | ||
710 | struct gianfar_platform_data *einfo; | 730 | struct gianfar_platform_data *einfo; |
711 | 731 | ||
732 | /* PHY stuff */ | ||
712 | struct phy_device *phydev; | 733 | struct phy_device *phydev; |
713 | struct mii_bus *mii_bus; | 734 | struct mii_bus *mii_bus; |
714 | int oldspeed; | 735 | int oldspeed; |
@@ -716,6 +737,10 @@ struct gfar_private { | |||
716 | int oldlink; | 737 | int oldlink; |
717 | 738 | ||
718 | uint32_t msg_enable; | 739 | uint32_t msg_enable; |
740 | |||
741 | /* Network Statistics */ | ||
742 | struct net_device_stats stats; | ||
743 | struct gfar_extra_stats extra_stats; | ||
719 | }; | 744 | }; |
720 | 745 | ||
721 | static inline u32 gfar_read(volatile unsigned __iomem *addr) | 746 | static inline u32 gfar_read(volatile unsigned __iomem *addr) |
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 5de7b2e259dc..d69698c695ef 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c | |||
@@ -455,10 +455,14 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva | |||
455 | 455 | ||
456 | /* Halt TX and RX, and process the frames which | 456 | /* Halt TX and RX, and process the frames which |
457 | * have already been received */ | 457 | * have already been received */ |
458 | spin_lock_irqsave(&priv->lock, flags); | 458 | spin_lock_irqsave(&priv->txlock, flags); |
459 | spin_lock(&priv->rxlock); | ||
460 | |||
459 | gfar_halt(dev); | 461 | gfar_halt(dev); |
460 | gfar_clean_rx_ring(dev, priv->rx_ring_size); | 462 | gfar_clean_rx_ring(dev, priv->rx_ring_size); |
461 | spin_unlock_irqrestore(&priv->lock, flags); | 463 | |
464 | spin_unlock(&priv->rxlock); | ||
465 | spin_unlock_irqrestore(&priv->txlock, flags); | ||
462 | 466 | ||
463 | /* Now we take down the rings to rebuild them */ | 467 | /* Now we take down the rings to rebuild them */ |
464 | stop_gfar(dev); | 468 | stop_gfar(dev); |
@@ -488,10 +492,14 @@ static int gfar_set_rx_csum(struct net_device *dev, uint32_t data) | |||
488 | 492 | ||
489 | /* Halt TX and RX, and process the frames which | 493 | /* Halt TX and RX, and process the frames which |
490 | * have already been received */ | 494 | * have already been received */ |
491 | spin_lock_irqsave(&priv->lock, flags); | 495 | spin_lock_irqsave(&priv->txlock, flags); |
496 | spin_lock(&priv->rxlock); | ||
497 | |||
492 | gfar_halt(dev); | 498 | gfar_halt(dev); |
493 | gfar_clean_rx_ring(dev, priv->rx_ring_size); | 499 | gfar_clean_rx_ring(dev, priv->rx_ring_size); |
494 | spin_unlock_irqrestore(&priv->lock, flags); | 500 | |
501 | spin_unlock(&priv->rxlock); | ||
502 | spin_unlock_irqrestore(&priv->txlock, flags); | ||
495 | 503 | ||
496 | /* Now we take down the rings to rebuild them */ | 504 | /* Now we take down the rings to rebuild them */ |
497 | stop_gfar(dev); | 505 | stop_gfar(dev); |
@@ -523,7 +531,7 @@ static int gfar_set_tx_csum(struct net_device *dev, uint32_t data) | |||
523 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) | 531 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) |
524 | return -EOPNOTSUPP; | 532 | return -EOPNOTSUPP; |
525 | 533 | ||
526 | spin_lock_irqsave(&priv->lock, flags); | 534 | spin_lock_irqsave(&priv->txlock, flags); |
527 | gfar_halt(dev); | 535 | gfar_halt(dev); |
528 | 536 | ||
529 | if (data) | 537 | if (data) |
@@ -532,7 +540,7 @@ static int gfar_set_tx_csum(struct net_device *dev, uint32_t data) | |||
532 | dev->features &= ~NETIF_F_IP_CSUM; | 540 | dev->features &= ~NETIF_F_IP_CSUM; |
533 | 541 | ||
534 | gfar_start(dev); | 542 | gfar_start(dev); |
535 | spin_unlock_irqrestore(&priv->lock, flags); | 543 | spin_unlock_irqrestore(&priv->txlock, flags); |
536 | 544 | ||
537 | return 0; | 545 | return 0; |
538 | } | 546 | } |
diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c index 51ef181b1368..a6d5c43199cb 100644 --- a/drivers/net/gianfar_sysfs.c +++ b/drivers/net/gianfar_sysfs.c | |||
@@ -82,7 +82,7 @@ static ssize_t gfar_set_bd_stash(struct class_device *cdev, | |||
82 | else | 82 | else |
83 | return count; | 83 | return count; |
84 | 84 | ||
85 | spin_lock_irqsave(&priv->lock, flags); | 85 | spin_lock_irqsave(&priv->rxlock, flags); |
86 | 86 | ||
87 | /* Set the new stashing value */ | 87 | /* Set the new stashing value */ |
88 | priv->bd_stash_en = new_setting; | 88 | priv->bd_stash_en = new_setting; |
@@ -96,7 +96,7 @@ static ssize_t gfar_set_bd_stash(struct class_device *cdev, | |||
96 | 96 | ||
97 | gfar_write(&priv->regs->attr, temp); | 97 | gfar_write(&priv->regs->attr, temp); |
98 | 98 | ||
99 | spin_unlock_irqrestore(&priv->lock, flags); | 99 | spin_unlock_irqrestore(&priv->rxlock, flags); |
100 | 100 | ||
101 | return count; | 101 | return count; |
102 | } | 102 | } |
@@ -118,7 +118,7 @@ static ssize_t gfar_set_rx_stash_size(struct class_device *cdev, | |||
118 | u32 temp; | 118 | u32 temp; |
119 | unsigned long flags; | 119 | unsigned long flags; |
120 | 120 | ||
121 | spin_lock_irqsave(&priv->lock, flags); | 121 | spin_lock_irqsave(&priv->rxlock, flags); |
122 | if (length > priv->rx_buffer_size) | 122 | if (length > priv->rx_buffer_size) |
123 | return count; | 123 | return count; |
124 | 124 | ||
@@ -142,7 +142,7 @@ static ssize_t gfar_set_rx_stash_size(struct class_device *cdev, | |||
142 | 142 | ||
143 | gfar_write(&priv->regs->attr, temp); | 143 | gfar_write(&priv->regs->attr, temp); |
144 | 144 | ||
145 | spin_unlock_irqrestore(&priv->lock, flags); | 145 | spin_unlock_irqrestore(&priv->rxlock, flags); |
146 | 146 | ||
147 | return count; | 147 | return count; |
148 | } | 148 | } |
@@ -166,7 +166,7 @@ static ssize_t gfar_set_rx_stash_index(struct class_device *cdev, | |||
166 | u32 temp; | 166 | u32 temp; |
167 | unsigned long flags; | 167 | unsigned long flags; |
168 | 168 | ||
169 | spin_lock_irqsave(&priv->lock, flags); | 169 | spin_lock_irqsave(&priv->rxlock, flags); |
170 | if (index > priv->rx_stash_size) | 170 | if (index > priv->rx_stash_size) |
171 | return count; | 171 | return count; |
172 | 172 | ||
@@ -180,7 +180,7 @@ static ssize_t gfar_set_rx_stash_index(struct class_device *cdev, | |||
180 | temp |= ATTRELI_EI(index); | 180 | temp |= ATTRELI_EI(index); |
181 | gfar_write(&priv->regs->attreli, flags); | 181 | gfar_write(&priv->regs->attreli, flags); |
182 | 182 | ||
183 | spin_unlock_irqrestore(&priv->lock, flags); | 183 | spin_unlock_irqrestore(&priv->rxlock, flags); |
184 | 184 | ||
185 | return count; | 185 | return count; |
186 | } | 186 | } |
@@ -205,7 +205,7 @@ static ssize_t gfar_set_fifo_threshold(struct class_device *cdev, | |||
205 | if (length > GFAR_MAX_FIFO_THRESHOLD) | 205 | if (length > GFAR_MAX_FIFO_THRESHOLD) |
206 | return count; | 206 | return count; |
207 | 207 | ||
208 | spin_lock_irqsave(&priv->lock, flags); | 208 | spin_lock_irqsave(&priv->txlock, flags); |
209 | 209 | ||
210 | priv->fifo_threshold = length; | 210 | priv->fifo_threshold = length; |
211 | 211 | ||
@@ -214,7 +214,7 @@ static ssize_t gfar_set_fifo_threshold(struct class_device *cdev, | |||
214 | temp |= length; | 214 | temp |= length; |
215 | gfar_write(&priv->regs->fifo_tx_thr, temp); | 215 | gfar_write(&priv->regs->fifo_tx_thr, temp); |
216 | 216 | ||
217 | spin_unlock_irqrestore(&priv->lock, flags); | 217 | spin_unlock_irqrestore(&priv->txlock, flags); |
218 | 218 | ||
219 | return count; | 219 | return count; |
220 | } | 220 | } |
@@ -240,7 +240,7 @@ static ssize_t gfar_set_fifo_starve(struct class_device *cdev, | |||
240 | if (num > GFAR_MAX_FIFO_STARVE) | 240 | if (num > GFAR_MAX_FIFO_STARVE) |
241 | return count; | 241 | return count; |
242 | 242 | ||
243 | spin_lock_irqsave(&priv->lock, flags); | 243 | spin_lock_irqsave(&priv->txlock, flags); |
244 | 244 | ||
245 | priv->fifo_starve = num; | 245 | priv->fifo_starve = num; |
246 | 246 | ||
@@ -249,7 +249,7 @@ static ssize_t gfar_set_fifo_starve(struct class_device *cdev, | |||
249 | temp |= num; | 249 | temp |= num; |
250 | gfar_write(&priv->regs->fifo_tx_starve, temp); | 250 | gfar_write(&priv->regs->fifo_tx_starve, temp); |
251 | 251 | ||
252 | spin_unlock_irqrestore(&priv->lock, flags); | 252 | spin_unlock_irqrestore(&priv->txlock, flags); |
253 | 253 | ||
254 | return count; | 254 | return count; |
255 | } | 255 | } |
@@ -274,7 +274,7 @@ static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev, | |||
274 | if (num > GFAR_MAX_FIFO_STARVE_OFF) | 274 | if (num > GFAR_MAX_FIFO_STARVE_OFF) |
275 | return count; | 275 | return count; |
276 | 276 | ||
277 | spin_lock_irqsave(&priv->lock, flags); | 277 | spin_lock_irqsave(&priv->txlock, flags); |
278 | 278 | ||
279 | priv->fifo_starve_off = num; | 279 | priv->fifo_starve_off = num; |
280 | 280 | ||
@@ -283,7 +283,7 @@ static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev, | |||
283 | temp |= num; | 283 | temp |= num; |
284 | gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp); | 284 | gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp); |
285 | 285 | ||
286 | spin_unlock_irqrestore(&priv->lock, flags); | 286 | spin_unlock_irqrestore(&priv->txlock, flags); |
287 | 287 | ||
288 | return count; | 288 | return count; |
289 | } | 289 | } |
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c index 79a8fbcf5f93..0d5fccc984bb 100644 --- a/drivers/net/hamradio/dmascc.c +++ b/drivers/net/hamradio/dmascc.c | |||
@@ -582,7 +582,6 @@ static int __init setup_adapter(int card_base, int type, int n) | |||
582 | INIT_WORK(&priv->rx_work, rx_bh, priv); | 582 | INIT_WORK(&priv->rx_work, rx_bh, priv); |
583 | dev->priv = priv; | 583 | dev->priv = priv; |
584 | sprintf(dev->name, "dmascc%i", 2 * n + i); | 584 | sprintf(dev->name, "dmascc%i", 2 * n + i); |
585 | SET_MODULE_OWNER(dev); | ||
586 | dev->base_addr = card_base; | 585 | dev->base_addr = card_base; |
587 | dev->irq = irq; | 586 | dev->irq = irq; |
588 | dev->open = scc_open; | 587 | dev->open = scc_open; |
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c index 6ace0e914fd1..5927784df3f9 100644 --- a/drivers/net/hamradio/scc.c +++ b/drivers/net/hamradio/scc.c | |||
@@ -1550,7 +1550,6 @@ static unsigned char ax25_nocall[AX25_ADDR_LEN] = | |||
1550 | 1550 | ||
1551 | static void scc_net_setup(struct net_device *dev) | 1551 | static void scc_net_setup(struct net_device *dev) |
1552 | { | 1552 | { |
1553 | SET_MODULE_OWNER(dev); | ||
1554 | dev->tx_queue_len = 16; /* should be enough... */ | 1553 | dev->tx_queue_len = 16; /* should be enough... */ |
1555 | 1554 | ||
1556 | dev->open = scc_net_open; | 1555 | dev->open = scc_net_open; |
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c index fe22479eb202..b49884048caa 100644 --- a/drivers/net/hamradio/yam.c +++ b/drivers/net/hamradio/yam.c | |||
@@ -1098,7 +1098,6 @@ static void yam_setup(struct net_device *dev) | |||
1098 | 1098 | ||
1099 | dev->base_addr = yp->iobase; | 1099 | dev->base_addr = yp->iobase; |
1100 | dev->irq = yp->irq; | 1100 | dev->irq = yp->irq; |
1101 | SET_MODULE_OWNER(dev); | ||
1102 | 1101 | ||
1103 | dev->open = yam_open; | 1102 | dev->open = yam_open; |
1104 | dev->stop = yam_close; | 1103 | dev->stop = yam_close; |
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index ea62a3e7d586..411f4d809c47 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
@@ -1419,6 +1419,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev) | |||
1419 | mv643xx_eth_update_pscr(dev, &cmd); | 1419 | mv643xx_eth_update_pscr(dev, &cmd); |
1420 | mv643xx_set_settings(dev, &cmd); | 1420 | mv643xx_set_settings(dev, &cmd); |
1421 | 1421 | ||
1422 | SET_MODULE_OWNER(dev); | ||
1423 | SET_NETDEV_DEV(dev, &pdev->dev); | ||
1422 | err = register_netdev(dev); | 1424 | err = register_netdev(dev); |
1423 | if (err) | 1425 | if (err) |
1424 | goto out; | 1426 | goto out; |
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 67b0eab16589..227df9876a2c 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -51,7 +51,7 @@ | |||
51 | #include "sky2.h" | 51 | #include "sky2.h" |
52 | 52 | ||
53 | #define DRV_NAME "sky2" | 53 | #define DRV_NAME "sky2" |
54 | #define DRV_VERSION "1.1" | 54 | #define DRV_VERSION "1.2" |
55 | #define PFX DRV_NAME " " | 55 | #define PFX DRV_NAME " " |
56 | 56 | ||
57 | /* | 57 | /* |
@@ -925,8 +925,7 @@ static inline struct sk_buff *sky2_alloc_skb(unsigned int size, gfp_t gfp_mask) | |||
925 | skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask); | 925 | skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask); |
926 | if (likely(skb)) { | 926 | if (likely(skb)) { |
927 | unsigned long p = (unsigned long) skb->data; | 927 | unsigned long p = (unsigned long) skb->data; |
928 | skb_reserve(skb, | 928 | skb_reserve(skb, ALIGN(p, RX_SKB_ALIGN) - p); |
929 | ((p + RX_SKB_ALIGN - 1) & ~(RX_SKB_ALIGN - 1)) - p); | ||
930 | } | 929 | } |
931 | 930 | ||
932 | return skb; | 931 | return skb; |
@@ -1686,13 +1685,12 @@ static void sky2_tx_timeout(struct net_device *dev) | |||
1686 | } | 1685 | } |
1687 | 1686 | ||
1688 | 1687 | ||
1689 | #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) | ||
1690 | /* Want receive buffer size to be multiple of 64 bits | 1688 | /* Want receive buffer size to be multiple of 64 bits |
1691 | * and incl room for vlan and truncation | 1689 | * and incl room for vlan and truncation |
1692 | */ | 1690 | */ |
1693 | static inline unsigned sky2_buf_size(int mtu) | 1691 | static inline unsigned sky2_buf_size(int mtu) |
1694 | { | 1692 | { |
1695 | return roundup(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8; | 1693 | return ALIGN(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8; |
1696 | } | 1694 | } |
1697 | 1695 | ||
1698 | static int sky2_change_mtu(struct net_device *dev, int new_mtu) | 1696 | static int sky2_change_mtu(struct net_device *dev, int new_mtu) |
@@ -2086,6 +2084,20 @@ static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port, | |||
2086 | } | 2084 | } |
2087 | } | 2085 | } |
2088 | 2086 | ||
2087 | /* If idle then force a fake soft NAPI poll once a second | ||
2088 | * to work around cases where sharing an edge triggered interrupt. | ||
2089 | */ | ||
2090 | static void sky2_idle(unsigned long arg) | ||
2091 | { | ||
2092 | struct net_device *dev = (struct net_device *) arg; | ||
2093 | |||
2094 | local_irq_disable(); | ||
2095 | if (__netif_rx_schedule_prep(dev)) | ||
2096 | __netif_rx_schedule(dev); | ||
2097 | local_irq_enable(); | ||
2098 | } | ||
2099 | |||
2100 | |||
2089 | static int sky2_poll(struct net_device *dev0, int *budget) | 2101 | static int sky2_poll(struct net_device *dev0, int *budget) |
2090 | { | 2102 | { |
2091 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; | 2103 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; |
@@ -2093,6 +2105,7 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2093 | int work_done = 0; | 2105 | int work_done = 0; |
2094 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); | 2106 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); |
2095 | 2107 | ||
2108 | restart_poll: | ||
2096 | if (unlikely(status & ~Y2_IS_STAT_BMU)) { | 2109 | if (unlikely(status & ~Y2_IS_STAT_BMU)) { |
2097 | if (status & Y2_IS_HW_ERR) | 2110 | if (status & Y2_IS_HW_ERR) |
2098 | sky2_hw_intr(hw); | 2111 | sky2_hw_intr(hw); |
@@ -2123,7 +2136,7 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2123 | } | 2136 | } |
2124 | 2137 | ||
2125 | if (status & Y2_IS_STAT_BMU) { | 2138 | if (status & Y2_IS_STAT_BMU) { |
2126 | work_done = sky2_status_intr(hw, work_limit); | 2139 | work_done += sky2_status_intr(hw, work_limit - work_done); |
2127 | *budget -= work_done; | 2140 | *budget -= work_done; |
2128 | dev0->quota -= work_done; | 2141 | dev0->quota -= work_done; |
2129 | 2142 | ||
@@ -2133,9 +2146,24 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2133 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | 2146 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); |
2134 | } | 2147 | } |
2135 | 2148 | ||
2136 | netif_rx_complete(dev0); | 2149 | mod_timer(&hw->idle_timer, jiffies + HZ); |
2150 | |||
2151 | local_irq_disable(); | ||
2152 | __netif_rx_complete(dev0); | ||
2137 | 2153 | ||
2138 | status = sky2_read32(hw, B0_Y2_SP_LISR); | 2154 | status = sky2_read32(hw, B0_Y2_SP_LISR); |
2155 | |||
2156 | if (unlikely(status)) { | ||
2157 | /* More work pending, try and keep going */ | ||
2158 | if (__netif_rx_schedule_prep(dev0)) { | ||
2159 | __netif_rx_reschedule(dev0, work_done); | ||
2160 | status = sky2_read32(hw, B0_Y2_SP_EISR); | ||
2161 | local_irq_enable(); | ||
2162 | goto restart_poll; | ||
2163 | } | ||
2164 | } | ||
2165 | |||
2166 | local_irq_enable(); | ||
2139 | return 0; | 2167 | return 0; |
2140 | } | 2168 | } |
2141 | 2169 | ||
@@ -2153,8 +2181,6 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
2153 | prefetch(&hw->st_le[hw->st_idx]); | 2181 | prefetch(&hw->st_le[hw->st_idx]); |
2154 | if (likely(__netif_rx_schedule_prep(dev0))) | 2182 | if (likely(__netif_rx_schedule_prep(dev0))) |
2155 | __netif_rx_schedule(dev0); | 2183 | __netif_rx_schedule(dev0); |
2156 | else | ||
2157 | printk(KERN_DEBUG PFX "irq race detected\n"); | ||
2158 | 2184 | ||
2159 | return IRQ_HANDLED; | 2185 | return IRQ_HANDLED; |
2160 | } | 2186 | } |
@@ -2193,7 +2219,7 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk) | |||
2193 | } | 2219 | } |
2194 | 2220 | ||
2195 | 2221 | ||
2196 | static int sky2_reset(struct sky2_hw *hw) | 2222 | static int __devinit sky2_reset(struct sky2_hw *hw) |
2197 | { | 2223 | { |
2198 | u16 status; | 2224 | u16 status; |
2199 | u8 t8, pmd_type; | 2225 | u8 t8, pmd_type; |
@@ -3276,6 +3302,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3276 | 3302 | ||
3277 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); | 3303 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); |
3278 | 3304 | ||
3305 | setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) dev); | ||
3306 | |||
3279 | pci_set_drvdata(pdev, hw); | 3307 | pci_set_drvdata(pdev, hw); |
3280 | 3308 | ||
3281 | return 0; | 3309 | return 0; |
@@ -3311,13 +3339,15 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
3311 | if (!hw) | 3339 | if (!hw) |
3312 | return; | 3340 | return; |
3313 | 3341 | ||
3342 | del_timer_sync(&hw->idle_timer); | ||
3343 | |||
3344 | sky2_write32(hw, B0_IMSK, 0); | ||
3314 | dev0 = hw->dev[0]; | 3345 | dev0 = hw->dev[0]; |
3315 | dev1 = hw->dev[1]; | 3346 | dev1 = hw->dev[1]; |
3316 | if (dev1) | 3347 | if (dev1) |
3317 | unregister_netdev(dev1); | 3348 | unregister_netdev(dev1); |
3318 | unregister_netdev(dev0); | 3349 | unregister_netdev(dev0); |
3319 | 3350 | ||
3320 | sky2_write32(hw, B0_IMSK, 0); | ||
3321 | sky2_set_power_state(hw, PCI_D3hot); | 3351 | sky2_set_power_state(hw, PCI_D3hot); |
3322 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); | 3352 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); |
3323 | sky2_write8(hw, B0_CTST, CS_RST_SET); | 3353 | sky2_write8(hw, B0_CTST, CS_RST_SET); |
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 89dd18cd12f0..b026f5653f04 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h | |||
@@ -1880,6 +1880,8 @@ struct sky2_hw { | |||
1880 | struct sky2_status_le *st_le; | 1880 | struct sky2_status_le *st_le; |
1881 | u32 st_idx; | 1881 | u32 st_idx; |
1882 | dma_addr_t st_dma; | 1882 | dma_addr_t st_dma; |
1883 | |||
1884 | struct timer_list idle_timer; | ||
1883 | int msi_detected; | 1885 | int msi_detected; |
1884 | wait_queue_head_t msi_wait; | 1886 | wait_queue_head_t msi_wait; |
1885 | }; | 1887 | }; |
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/net/via-rhine.c b/drivers/net/via-rhine.c index 6a23964c1317..a6dc53b4250d 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c | |||
@@ -129,6 +129,7 @@ | |||
129 | - Massive clean-up | 129 | - Massive clean-up |
130 | - Rewrite PHY, media handling (remove options, full_duplex, backoff) | 130 | - Rewrite PHY, media handling (remove options, full_duplex, backoff) |
131 | - Fix Tx engine race for good | 131 | - Fix Tx engine race for good |
132 | - Craig Brind: Zero padded aligned buffers for short packets. | ||
132 | 133 | ||
133 | */ | 134 | */ |
134 | 135 | ||
@@ -1326,7 +1327,12 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev) | |||
1326 | rp->stats.tx_dropped++; | 1327 | rp->stats.tx_dropped++; |
1327 | return 0; | 1328 | return 0; |
1328 | } | 1329 | } |
1330 | |||
1331 | /* Padding is not copied and so must be redone. */ | ||
1329 | skb_copy_and_csum_dev(skb, rp->tx_buf[entry]); | 1332 | skb_copy_and_csum_dev(skb, rp->tx_buf[entry]); |
1333 | if (skb->len < ETH_ZLEN) | ||
1334 | memset(rp->tx_buf[entry] + skb->len, 0, | ||
1335 | ETH_ZLEN - skb->len); | ||
1330 | rp->tx_skbuff_dma[entry] = 0; | 1336 | rp->tx_skbuff_dma[entry] = 0; |
1331 | rp->tx_ring[entry].addr = cpu_to_le32(rp->tx_bufs_dma + | 1337 | rp->tx_ring[entry].addr = cpu_to_le32(rp->tx_bufs_dma + |
1332 | (rp->tx_buf[entry] - | 1338 | (rp->tx_buf[entry] - |
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..3b35cb779539 100644 --- a/drivers/serial/cpm_uart/cpm_uart.h +++ b/drivers/serial/cpm_uart/cpm_uart.h | |||
@@ -5,11 +5,20 @@ | |||
5 | * | 5 | * |
6 | * Copyright (C) 2004 Freescale Semiconductor, Inc. | 6 | * Copyright (C) 2004 Freescale Semiconductor, Inc. |
7 | * | 7 | * |
8 | * 2006 (c) MontaVista Software, Inc. | ||
9 | * Vitaly Bordug <vbordug@ru.mvista.com> | ||
10 | * | ||
11 | * This file is licensed under the terms of the GNU General Public License | ||
12 | * version 2. This program is licensed "as is" without any warranty of any | ||
13 | * kind, whether express or implied. | ||
14 | * | ||
8 | */ | 15 | */ |
9 | #ifndef CPM_UART_H | 16 | #ifndef CPM_UART_H |
10 | #define CPM_UART_H | 17 | #define CPM_UART_H |
11 | 18 | ||
12 | #include <linux/config.h> | 19 | #include <linux/config.h> |
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/fs_uart_pd.h> | ||
13 | 22 | ||
14 | #if defined(CONFIG_CPM2) | 23 | #if defined(CONFIG_CPM2) |
15 | #include "cpm_uart_cpm2.h" | 24 | #include "cpm_uart_cpm2.h" |
@@ -26,14 +35,14 @@ | |||
26 | #define FLAG_SMC 0x00000002 | 35 | #define FLAG_SMC 0x00000002 |
27 | #define FLAG_CONSOLE 0x00000001 | 36 | #define FLAG_CONSOLE 0x00000001 |
28 | 37 | ||
29 | #define UART_SMC1 0 | 38 | #define UART_SMC1 fsid_smc1_uart |
30 | #define UART_SMC2 1 | 39 | #define UART_SMC2 fsid_smc2_uart |
31 | #define UART_SCC1 2 | 40 | #define UART_SCC1 fsid_scc1_uart |
32 | #define UART_SCC2 3 | 41 | #define UART_SCC2 fsid_scc2_uart |
33 | #define UART_SCC3 4 | 42 | #define UART_SCC3 fsid_scc3_uart |
34 | #define UART_SCC4 5 | 43 | #define UART_SCC4 fsid_scc4_uart |
35 | 44 | ||
36 | #define UART_NR 6 | 45 | #define UART_NR fs_uart_nr |
37 | 46 | ||
38 | #define RX_NUM_FIFO 4 | 47 | #define RX_NUM_FIFO 4 |
39 | #define RX_BUF_SIZE 32 | 48 | #define RX_BUF_SIZE 32 |
@@ -64,6 +73,7 @@ struct uart_cpm_port { | |||
64 | uint dp_addr; | 73 | uint dp_addr; |
65 | void *mem_addr; | 74 | void *mem_addr; |
66 | dma_addr_t dma_addr; | 75 | dma_addr_t dma_addr; |
76 | u32 mem_size; | ||
67 | /* helpers */ | 77 | /* helpers */ |
68 | int baud; | 78 | int baud; |
69 | int bits; | 79 | int bits; |
@@ -90,4 +100,38 @@ void scc2_lineif(struct uart_cpm_port *pinfo); | |||
90 | void scc3_lineif(struct uart_cpm_port *pinfo); | 100 | void scc3_lineif(struct uart_cpm_port *pinfo); |
91 | void scc4_lineif(struct uart_cpm_port *pinfo); | 101 | void scc4_lineif(struct uart_cpm_port *pinfo); |
92 | 102 | ||
103 | /* | ||
104 | virtual to phys transtalion | ||
105 | */ | ||
106 | static inline unsigned long cpu2cpm_addr(void* addr, struct uart_cpm_port *pinfo) | ||
107 | { | ||
108 | int offset; | ||
109 | u32 val = (u32)addr; | ||
110 | /* sane check */ | ||
111 | if (likely((val >= (u32)pinfo->mem_addr)) && | ||
112 | (val<((u32)pinfo->mem_addr + pinfo->mem_size))) { | ||
113 | offset = val - (u32)pinfo->mem_addr; | ||
114 | return pinfo->dma_addr+offset; | ||
115 | } | ||
116 | /* something nasty happened */ | ||
117 | BUG(); | ||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | static inline void *cpm2cpu_addr(unsigned long addr, struct uart_cpm_port *pinfo) | ||
122 | { | ||
123 | int offset; | ||
124 | u32 val = addr; | ||
125 | /* sane check */ | ||
126 | if (likely((val >= pinfo->dma_addr) && | ||
127 | (val<(pinfo->dma_addr + pinfo->mem_size)))) { | ||
128 | offset = val - (u32)pinfo->dma_addr; | ||
129 | return (void*)(pinfo->mem_addr+offset); | ||
130 | } | ||
131 | /* something nasty happened */ | ||
132 | BUG(); | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | |||
93 | #endif /* CPM_UART_H */ | 137 | #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..969f94900431 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
@@ -12,7 +12,8 @@ | |||
12 | * | 12 | * |
13 | * Copyright (C) 2004 Freescale Semiconductor, Inc. | 13 | * Copyright (C) 2004 Freescale Semiconductor, Inc. |
14 | * (C) 2004 Intracom, S.A. | 14 | * (C) 2004 Intracom, S.A. |
15 | * (C) 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com> | 15 | * (C) 2005-2006 MontaVista Software, Inc. |
16 | * Vitaly Bordug <vbordug@ru.mvista.com> | ||
16 | * | 17 | * |
17 | * This program is free software; you can redistribute it and/or modify | 18 | * This program is free software; you can redistribute it and/or modify |
18 | * it under the terms of the GNU General Public License as published by | 19 | * it under the terms of the GNU General Public License as published by |
@@ -41,6 +42,7 @@ | |||
41 | #include <linux/device.h> | 42 | #include <linux/device.h> |
42 | #include <linux/bootmem.h> | 43 | #include <linux/bootmem.h> |
43 | #include <linux/dma-mapping.h> | 44 | #include <linux/dma-mapping.h> |
45 | #include <linux/fs_uart_pd.h> | ||
44 | 46 | ||
45 | #include <asm/io.h> | 47 | #include <asm/io.h> |
46 | #include <asm/irq.h> | 48 | #include <asm/irq.h> |
@@ -60,7 +62,7 @@ | |||
60 | /* Track which ports are configured as uarts */ | 62 | /* Track which ports are configured as uarts */ |
61 | int cpm_uart_port_map[UART_NR]; | 63 | int cpm_uart_port_map[UART_NR]; |
62 | /* How many ports did we config as uarts */ | 64 | /* How many ports did we config as uarts */ |
63 | int cpm_uart_nr; | 65 | int cpm_uart_nr = 0; |
64 | 66 | ||
65 | /**************************************************************/ | 67 | /**************************************************************/ |
66 | 68 | ||
@@ -71,18 +73,51 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo); | |||
71 | 73 | ||
72 | /**************************************************************/ | 74 | /**************************************************************/ |
73 | 75 | ||
74 | static inline unsigned long cpu2cpm_addr(void *addr) | 76 | |
77 | /* Place-holder for board-specific stuff */ | ||
78 | struct platform_device* __attribute__ ((weak)) __init | ||
79 | early_uart_get_pdev(int index) | ||
80 | { | ||
81 | return NULL; | ||
82 | } | ||
83 | |||
84 | |||
85 | static void cpm_uart_count(void) | ||
75 | { | 86 | { |
76 | if ((unsigned long)addr >= CPM_ADDR) | 87 | cpm_uart_nr = 0; |
77 | return (unsigned long)addr; | 88 | #ifdef CONFIG_SERIAL_CPM_SMC1 |
78 | return virt_to_bus(addr); | 89 | cpm_uart_port_map[cpm_uart_nr++] = UART_SMC1; |
90 | #endif | ||
91 | #ifdef CONFIG_SERIAL_CPM_SMC2 | ||
92 | cpm_uart_port_map[cpm_uart_nr++] = UART_SMC2; | ||
93 | #endif | ||
94 | #ifdef CONFIG_SERIAL_CPM_SCC1 | ||
95 | cpm_uart_port_map[cpm_uart_nr++] = UART_SCC1; | ||
96 | #endif | ||
97 | #ifdef CONFIG_SERIAL_CPM_SCC2 | ||
98 | cpm_uart_port_map[cpm_uart_nr++] = UART_SCC2; | ||
99 | #endif | ||
100 | #ifdef CONFIG_SERIAL_CPM_SCC3 | ||
101 | cpm_uart_port_map[cpm_uart_nr++] = UART_SCC3; | ||
102 | #endif | ||
103 | #ifdef CONFIG_SERIAL_CPM_SCC4 | ||
104 | cpm_uart_port_map[cpm_uart_nr++] = UART_SCC4; | ||
105 | #endif | ||
79 | } | 106 | } |
80 | 107 | ||
81 | static inline void *cpm2cpu_addr(unsigned long addr) | 108 | /* Get UART number by its id */ |
109 | static int cpm_uart_id2nr(int id) | ||
82 | { | 110 | { |
83 | if (addr >= CPM_ADDR) | 111 | int i; |
84 | return (void *)addr; | 112 | if (id < UART_NR) { |
85 | return bus_to_virt(addr); | 113 | for (i=0; i<UART_NR; i++) { |
114 | if (cpm_uart_port_map[i] == id) | ||
115 | return i; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | /* not found or invalid argument */ | ||
120 | return -1; | ||
86 | } | 121 | } |
87 | 122 | ||
88 | /* | 123 | /* |
@@ -258,7 +293,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) | |||
258 | } | 293 | } |
259 | 294 | ||
260 | /* get pointer */ | 295 | /* get pointer */ |
261 | cp = cpm2cpu_addr(bdp->cbd_bufaddr); | 296 | cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); |
262 | 297 | ||
263 | /* loop through the buffer */ | 298 | /* loop through the buffer */ |
264 | while (i-- > 0) { | 299 | while (i-- > 0) { |
@@ -438,7 +473,11 @@ static void cpm_uart_shutdown(struct uart_port *port) | |||
438 | } | 473 | } |
439 | 474 | ||
440 | /* Shut them really down and reinit buffer descriptors */ | 475 | /* Shut them really down and reinit buffer descriptors */ |
441 | cpm_line_cr_cmd(line, CPM_CR_STOP_TX); | 476 | if (IS_SMC(pinfo)) |
477 | cpm_line_cr_cmd(line, CPM_CR_STOP_TX); | ||
478 | else | ||
479 | cpm_line_cr_cmd(line, CPM_CR_GRA_STOP_TX); | ||
480 | |||
442 | cpm_uart_initbd(pinfo); | 481 | cpm_uart_initbd(pinfo); |
443 | } | 482 | } |
444 | } | 483 | } |
@@ -601,7 +640,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) | |||
601 | /* Pick next descriptor and fill from buffer */ | 640 | /* Pick next descriptor and fill from buffer */ |
602 | bdp = pinfo->tx_cur; | 641 | bdp = pinfo->tx_cur; |
603 | 642 | ||
604 | p = cpm2cpu_addr(bdp->cbd_bufaddr); | 643 | p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); |
605 | 644 | ||
606 | *p++ = port->x_char; | 645 | *p++ = port->x_char; |
607 | bdp->cbd_datlen = 1; | 646 | bdp->cbd_datlen = 1; |
@@ -628,7 +667,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) | |||
628 | 667 | ||
629 | while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) { | 668 | while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) { |
630 | count = 0; | 669 | count = 0; |
631 | p = cpm2cpu_addr(bdp->cbd_bufaddr); | 670 | p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); |
632 | while (count < pinfo->tx_fifosize) { | 671 | while (count < pinfo->tx_fifosize) { |
633 | *p++ = xmit->buf[xmit->tail]; | 672 | *p++ = xmit->buf[xmit->tail]; |
634 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 673 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
@@ -677,12 +716,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo) | |||
677 | mem_addr = pinfo->mem_addr; | 716 | mem_addr = pinfo->mem_addr; |
678 | bdp = pinfo->rx_cur = pinfo->rx_bd_base; | 717 | bdp = pinfo->rx_cur = pinfo->rx_bd_base; |
679 | for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) { | 718 | for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) { |
680 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); | 719 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo); |
681 | bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT; | 720 | bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT; |
682 | mem_addr += pinfo->rx_fifosize; | 721 | mem_addr += pinfo->rx_fifosize; |
683 | } | 722 | } |
684 | 723 | ||
685 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); | 724 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo); |
686 | bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; | 725 | bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; |
687 | 726 | ||
688 | /* Set the physical address of the host memory | 727 | /* Set the physical address of the host memory |
@@ -692,12 +731,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); | 731 | mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize); |
693 | bdp = pinfo->tx_cur = pinfo->tx_bd_base; | 732 | bdp = pinfo->tx_cur = pinfo->tx_bd_base; |
694 | for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) { | 733 | for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) { |
695 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); | 734 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo); |
696 | bdp->cbd_sc = BD_SC_INTRPT; | 735 | bdp->cbd_sc = BD_SC_INTRPT; |
697 | mem_addr += pinfo->tx_fifosize; | 736 | mem_addr += pinfo->tx_fifosize; |
698 | } | 737 | } |
699 | 738 | ||
700 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); | 739 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo); |
701 | bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT; | 740 | bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT; |
702 | } | 741 | } |
703 | 742 | ||
@@ -829,14 +868,6 @@ static int cpm_uart_request_port(struct uart_port *port) | |||
829 | if (pinfo->flags & FLAG_CONSOLE) | 868 | if (pinfo->flags & FLAG_CONSOLE) |
830 | return 0; | 869 | return 0; |
831 | 870 | ||
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)) { | 871 | if (IS_SMC(pinfo)) { |
841 | pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX); | 872 | pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX); |
842 | pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); | 873 | pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); |
@@ -988,6 +1019,58 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { | |||
988 | }, | 1019 | }, |
989 | }; | 1020 | }; |
990 | 1021 | ||
1022 | int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con) | ||
1023 | { | ||
1024 | struct resource *r; | ||
1025 | struct fs_uart_platform_info *pdata = pdev->dev.platform_data; | ||
1026 | int idx = pdata->fs_no; /* It is UART_SMCx or UART_SCCx index */ | ||
1027 | struct uart_cpm_port *pinfo; | ||
1028 | int line; | ||
1029 | u32 mem, pram; | ||
1030 | |||
1031 | line = cpm_uart_id2nr(idx); | ||
1032 | if(line < 0) { | ||
1033 | printk(KERN_ERR"%s(): port %d is not registered", __FUNCTION__, idx); | ||
1034 | return -1; | ||
1035 | } | ||
1036 | |||
1037 | pinfo = (struct uart_cpm_port *) &cpm_uart_ports[idx]; | ||
1038 | |||
1039 | pinfo->brg = pdata->brg; | ||
1040 | |||
1041 | if (!is_con) { | ||
1042 | pinfo->port.line = line; | ||
1043 | pinfo->port.flags = UPF_BOOT_AUTOCONF; | ||
1044 | } | ||
1045 | |||
1046 | if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"))) | ||
1047 | return -EINVAL; | ||
1048 | mem = r->start; | ||
1049 | |||
1050 | if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram"))) | ||
1051 | return -EINVAL; | ||
1052 | pram = r->start; | ||
1053 | |||
1054 | if(idx > fsid_smc2_uart) { | ||
1055 | pinfo->sccp = (scc_t *)mem; | ||
1056 | pinfo->sccup = (scc_uart_t *)pram; | ||
1057 | } else { | ||
1058 | pinfo->smcp = (smc_t *)mem; | ||
1059 | pinfo->smcup = (smc_uart_t *)pram; | ||
1060 | } | ||
1061 | pinfo->tx_nrfifos = pdata->tx_num_fifo; | ||
1062 | pinfo->tx_fifosize = pdata->tx_buf_size; | ||
1063 | |||
1064 | pinfo->rx_nrfifos = pdata->rx_num_fifo; | ||
1065 | pinfo->rx_fifosize = pdata->rx_buf_size; | ||
1066 | |||
1067 | pinfo->port.uartclk = pdata->uart_clk; | ||
1068 | pinfo->port.mapbase = (unsigned long)mem; | ||
1069 | pinfo->port.irq = platform_get_irq(pdev, 0); | ||
1070 | |||
1071 | return 0; | ||
1072 | } | ||
1073 | |||
991 | #ifdef CONFIG_SERIAL_CPM_CONSOLE | 1074 | #ifdef CONFIG_SERIAL_CPM_CONSOLE |
992 | /* | 1075 | /* |
993 | * Print a string to the serial port trying not to disturb | 1076 | * Print a string to the serial port trying not to disturb |
@@ -1027,7 +1110,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 | 1110 | * If the buffer address is in the CPM DPRAM, don't |
1028 | * convert it. | 1111 | * convert it. |
1029 | */ | 1112 | */ |
1030 | cp = cpm2cpu_addr(bdp->cbd_bufaddr); | 1113 | cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); |
1031 | 1114 | ||
1032 | *cp = *s; | 1115 | *cp = *s; |
1033 | 1116 | ||
@@ -1044,7 +1127,7 @@ static void cpm_uart_console_write(struct console *co, const char *s, | |||
1044 | while ((bdp->cbd_sc & BD_SC_READY) != 0) | 1127 | while ((bdp->cbd_sc & BD_SC_READY) != 0) |
1045 | ; | 1128 | ; |
1046 | 1129 | ||
1047 | cp = cpm2cpu_addr(bdp->cbd_bufaddr); | 1130 | cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); |
1048 | 1131 | ||
1049 | *cp = 13; | 1132 | *cp = 13; |
1050 | bdp->cbd_datlen = 1; | 1133 | bdp->cbd_datlen = 1; |
@@ -1067,9 +1150,7 @@ static void cpm_uart_console_write(struct console *co, const char *s, | |||
1067 | pinfo->tx_cur = (volatile cbd_t *) bdp; | 1150 | pinfo->tx_cur = (volatile cbd_t *) bdp; |
1068 | } | 1151 | } |
1069 | 1152 | ||
1070 | /* | 1153 | |
1071 | * Setup console. Be careful is called early ! | ||
1072 | */ | ||
1073 | static int __init cpm_uart_console_setup(struct console *co, char *options) | 1154 | static int __init cpm_uart_console_setup(struct console *co, char *options) |
1074 | { | 1155 | { |
1075 | struct uart_port *port; | 1156 | struct uart_port *port; |
@@ -1080,9 +1161,27 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) | |||
1080 | int flow = 'n'; | 1161 | int flow = 'n'; |
1081 | int ret; | 1162 | int ret; |
1082 | 1163 | ||
1164 | struct fs_uart_platform_info *pdata; | ||
1165 | struct platform_device* pdev = early_uart_get_pdev(co->index); | ||
1166 | |||
1083 | port = | 1167 | port = |
1084 | (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]]; | 1168 | (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]]; |
1085 | pinfo = (struct uart_cpm_port *)port; | 1169 | pinfo = (struct uart_cpm_port *)port; |
1170 | if (!pdev) { | ||
1171 | pr_info("cpm_uart: console: compat mode\n"); | ||
1172 | /* compatibility - will be cleaned up */ | ||
1173 | cpm_uart_init_portdesc(); | ||
1174 | |||
1175 | if (pinfo->set_lineif) | ||
1176 | pinfo->set_lineif(pinfo); | ||
1177 | } else { | ||
1178 | pdata = pdev->dev.platform_data; | ||
1179 | if (pdata) | ||
1180 | if (pdata->init_ioports) | ||
1181 | pdata->init_ioports(); | ||
1182 | |||
1183 | cpm_uart_drv_get_platform_data(pdev, 1); | ||
1184 | } | ||
1086 | 1185 | ||
1087 | pinfo->flags |= FLAG_CONSOLE; | 1186 | pinfo->flags |= FLAG_CONSOLE; |
1088 | 1187 | ||
@@ -1097,14 +1196,6 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) | |||
1097 | baud = 9600; | 1196 | baud = 9600; |
1098 | } | 1197 | } |
1099 | 1198 | ||
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)) { | 1199 | if (IS_SMC(pinfo)) { |
1109 | pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX); | 1200 | pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX); |
1110 | pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); | 1201 | pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); |
@@ -1143,11 +1234,8 @@ static struct console cpm_scc_uart_console = { | |||
1143 | 1234 | ||
1144 | int __init cpm_uart_console_init(void) | 1235 | int __init cpm_uart_console_init(void) |
1145 | { | 1236 | { |
1146 | int ret = cpm_uart_init_portdesc(); | 1237 | register_console(&cpm_scc_uart_console); |
1147 | 1238 | return 0; | |
1148 | if (!ret) | ||
1149 | register_console(&cpm_scc_uart_console); | ||
1150 | return ret; | ||
1151 | } | 1239 | } |
1152 | 1240 | ||
1153 | console_initcall(cpm_uart_console_init); | 1241 | console_initcall(cpm_uart_console_init); |
@@ -1165,44 +1253,129 @@ static struct uart_driver cpm_reg = { | |||
1165 | .minor = SERIAL_CPM_MINOR, | 1253 | .minor = SERIAL_CPM_MINOR, |
1166 | .cons = CPM_UART_CONSOLE, | 1254 | .cons = CPM_UART_CONSOLE, |
1167 | }; | 1255 | }; |
1168 | 1256 | static int cpm_uart_drv_probe(struct device *dev) | |
1169 | static int __init cpm_uart_init(void) | ||
1170 | { | 1257 | { |
1171 | int ret, i; | 1258 | struct platform_device *pdev = to_platform_device(dev); |
1172 | 1259 | struct fs_uart_platform_info *pdata; | |
1173 | printk(KERN_INFO "Serial: CPM driver $Revision: 0.01 $\n"); | 1260 | int ret = -ENODEV; |
1174 | 1261 | ||
1175 | #ifndef CONFIG_SERIAL_CPM_CONSOLE | 1262 | if(!pdev) { |
1176 | ret = cpm_uart_init_portdesc(); | 1263 | printk(KERN_ERR"CPM UART: platform data missing!\n"); |
1177 | if (ret) | ||
1178 | return ret; | 1264 | return ret; |
1179 | #endif | 1265 | } |
1180 | 1266 | ||
1181 | cpm_reg.nr = cpm_uart_nr; | 1267 | pdata = pdev->dev.platform_data; |
1182 | ret = uart_register_driver(&cpm_reg); | 1268 | pr_debug("cpm_uart_drv_probe: Adding CPM UART %d\n", cpm_uart_id2nr(pdata->fs_no)); |
1183 | 1269 | ||
1184 | if (ret) | 1270 | if ((ret = cpm_uart_drv_get_platform_data(pdev, 0))) |
1185 | return ret; | 1271 | return ret; |
1186 | 1272 | ||
1187 | for (i = 0; i < cpm_uart_nr; i++) { | 1273 | if (pdata->init_ioports) |
1188 | int con = cpm_uart_port_map[i]; | 1274 | 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 | 1275 | ||
1194 | return ret; | 1276 | ret = uart_add_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port); |
1277 | |||
1278 | return ret; | ||
1195 | } | 1279 | } |
1196 | 1280 | ||
1197 | static void __exit cpm_uart_exit(void) | 1281 | static int cpm_uart_drv_remove(struct device *dev) |
1198 | { | 1282 | { |
1283 | struct platform_device *pdev = to_platform_device(dev); | ||
1284 | struct fs_uart_platform_info *pdata = pdev->dev.platform_data; | ||
1285 | |||
1286 | pr_debug("cpm_uart_drv_remove: Removing CPM UART %d\n", | ||
1287 | cpm_uart_id2nr(pdata->fs_no)); | ||
1288 | |||
1289 | uart_remove_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port); | ||
1290 | return 0; | ||
1291 | } | ||
1292 | |||
1293 | static struct device_driver cpm_smc_uart_driver = { | ||
1294 | .name = "fsl-cpm-smc:uart", | ||
1295 | .bus = &platform_bus_type, | ||
1296 | .probe = cpm_uart_drv_probe, | ||
1297 | .remove = cpm_uart_drv_remove, | ||
1298 | }; | ||
1299 | |||
1300 | static struct device_driver cpm_scc_uart_driver = { | ||
1301 | .name = "fsl-cpm-scc:uart", | ||
1302 | .bus = &platform_bus_type, | ||
1303 | .probe = cpm_uart_drv_probe, | ||
1304 | .remove = cpm_uart_drv_remove, | ||
1305 | }; | ||
1306 | |||
1307 | /* | ||
1308 | This is supposed to match uart devices on platform bus, | ||
1309 | */ | ||
1310 | static int match_is_uart (struct device* dev, void* data) | ||
1311 | { | ||
1312 | struct platform_device* pdev = container_of(dev, struct platform_device, dev); | ||
1313 | int ret = 0; | ||
1314 | /* this was setfunc as uart */ | ||
1315 | if(strstr(pdev->name,":uart")) { | ||
1316 | ret = 1; | ||
1317 | } | ||
1318 | return ret; | ||
1319 | } | ||
1320 | |||
1321 | |||
1322 | static int cpm_uart_init(void) { | ||
1323 | |||
1324 | int ret; | ||
1199 | int i; | 1325 | int i; |
1326 | struct device *dev; | ||
1327 | printk(KERN_INFO "Serial: CPM driver $Revision: 0.02 $\n"); | ||
1328 | |||
1329 | /* lookup the bus for uart devices */ | ||
1330 | dev = bus_find_device(&platform_bus_type, NULL, 0, match_is_uart); | ||
1331 | |||
1332 | /* There are devices on the bus - all should be OK */ | ||
1333 | if (dev) { | ||
1334 | cpm_uart_count(); | ||
1335 | cpm_reg.nr = cpm_uart_nr; | ||
1336 | |||
1337 | if (!(ret = uart_register_driver(&cpm_reg))) { | ||
1338 | if ((ret = driver_register(&cpm_smc_uart_driver))) { | ||
1339 | uart_unregister_driver(&cpm_reg); | ||
1340 | return ret; | ||
1341 | } | ||
1342 | if ((ret = driver_register(&cpm_scc_uart_driver))) { | ||
1343 | driver_unregister(&cpm_scc_uart_driver); | ||
1344 | uart_unregister_driver(&cpm_reg); | ||
1345 | } | ||
1346 | } | ||
1347 | } else { | ||
1348 | /* No capable platform devices found - falling back to legacy mode */ | ||
1349 | pr_info("cpm_uart: WARNING: no UART devices found on platform bus!\n"); | ||
1350 | pr_info( | ||
1351 | "cpm_uart: the driver will guess configuration, but this mode is no longer supported.\n"); | ||
1352 | #ifndef CONFIG_SERIAL_CPM_CONSOLE | ||
1353 | ret = cpm_uart_init_portdesc(); | ||
1354 | if (ret) | ||
1355 | return ret; | ||
1356 | #endif | ||
1357 | |||
1358 | cpm_reg.nr = cpm_uart_nr; | ||
1359 | ret = uart_register_driver(&cpm_reg); | ||
1360 | |||
1361 | if (ret) | ||
1362 | return ret; | ||
1363 | |||
1364 | for (i = 0; i < cpm_uart_nr; i++) { | ||
1365 | int con = cpm_uart_port_map[i]; | ||
1366 | cpm_uart_ports[con].port.line = i; | ||
1367 | cpm_uart_ports[con].port.flags = UPF_BOOT_AUTOCONF; | ||
1368 | uart_add_one_port(&cpm_reg, &cpm_uart_ports[con].port); | ||
1369 | } | ||
1200 | 1370 | ||
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 | } | 1371 | } |
1372 | return ret; | ||
1373 | } | ||
1205 | 1374 | ||
1375 | static void __exit cpm_uart_exit(void) | ||
1376 | { | ||
1377 | driver_unregister(&cpm_scc_uart_driver); | ||
1378 | driver_unregister(&cpm_smc_uart_driver); | ||
1206 | uart_unregister_driver(&cpm_reg); | 1379 | uart_unregister_driver(&cpm_reg); |
1207 | } | 1380 | } |
1208 | 1381 | ||
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c index d789ee55cbb7..17406a05ce1f 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c | |||
@@ -8,6 +8,8 @@ | |||
8 | * | 8 | * |
9 | * Copyright (C) 2004 Freescale Semiconductor, Inc. | 9 | * Copyright (C) 2004 Freescale Semiconductor, Inc. |
10 | * (C) 2004 Intracom, S.A. | 10 | * (C) 2004 Intracom, S.A. |
11 | * (C) 2006 MontaVista Software, Inc. | ||
12 | * Vitaly Bordug <vbordug@ru.mvista.com> | ||
11 | * | 13 | * |
12 | * This program is free software; you can redistribute it and/or modify | 14 | * This program is free software; you can redistribute it and/or modify |
13 | * it under the terms of the GNU General Public License as published by | 15 | * it under the terms of the GNU General Public License as published by |
@@ -81,58 +83,11 @@ void cpm_line_cr_cmd(int line, int cmd) | |||
81 | 83 | ||
82 | void smc1_lineif(struct uart_cpm_port *pinfo) | 84 | void smc1_lineif(struct uart_cpm_port *pinfo) |
83 | { | 85 | { |
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; | 86 | pinfo->brg = 1; |
109 | } | 87 | } |
110 | 88 | ||
111 | void smc2_lineif(struct uart_cpm_port *pinfo) | 89 | void smc2_lineif(struct uart_cpm_port *pinfo) |
112 | { | 90 | { |
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; | 91 | pinfo->brg = 2; |
137 | } | 92 | } |
138 | 93 | ||
@@ -191,7 +146,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) | |||
191 | /* was hostalloc but changed cause it blows away the */ | 146 | /* was hostalloc but changed cause it blows away the */ |
192 | /* large tlb mapping when pinning the kernel area */ | 147 | /* large tlb mapping when pinning the kernel area */ |
193 | mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8)); | 148 | mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8)); |
194 | dma_addr = 0; | 149 | dma_addr = (u32)mem_addr; |
195 | } else | 150 | } else |
196 | mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr, | 151 | mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr, |
197 | GFP_KERNEL); | 152 | GFP_KERNEL); |
@@ -204,8 +159,9 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) | |||
204 | } | 159 | } |
205 | 160 | ||
206 | pinfo->dp_addr = dp_offset; | 161 | pinfo->dp_addr = dp_offset; |
207 | pinfo->mem_addr = mem_addr; | 162 | pinfo->mem_addr = mem_addr; /* virtual address*/ |
208 | pinfo->dma_addr = dma_addr; | 163 | pinfo->dma_addr = dma_addr; /* physical address*/ |
164 | pinfo->mem_size = memsz; | ||
209 | 165 | ||
210 | pinfo->rx_buf = mem_addr; | 166 | pinfo->rx_buf = mem_addr; |
211 | pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos | 167 | 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..4b2de08f46d0 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c | |||
@@ -8,6 +8,8 @@ | |||
8 | * | 8 | * |
9 | * Copyright (C) 2004 Freescale Semiconductor, Inc. | 9 | * Copyright (C) 2004 Freescale Semiconductor, Inc. |
10 | * (C) 2004 Intracom, S.A. | 10 | * (C) 2004 Intracom, S.A. |
11 | * (C) 2006 MontaVista Software, Inc. | ||
12 | * Vitaly Bordug <vbordug@ru.mvista.com> | ||
11 | * | 13 | * |
12 | * This program is free software; you can redistribute it and/or modify | 14 | * This program is free software; you can redistribute it and/or modify |
13 | * it under the terms of the GNU General Public License as published by | 15 | * it under the terms of the GNU General Public License as published by |
@@ -142,14 +144,6 @@ void scc2_lineif(struct uart_cpm_port *pinfo) | |||
142 | * be supported in a sane fashion. | 144 | * be supported in a sane fashion. |
143 | */ | 145 | */ |
144 | #ifndef CONFIG_STX_GP3 | 146 | #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; | 147 | volatile iop_cpm2_t *io = &cpm2_immr->im_ioport; |
154 | io->iop_pparb |= 0x008b0000; | 148 | io->iop_pparb |= 0x008b0000; |
155 | io->iop_pdirb |= 0x00880000; | 149 | io->iop_pdirb |= 0x00880000; |
@@ -157,7 +151,6 @@ void scc2_lineif(struct uart_cpm_port *pinfo) | |||
157 | io->iop_pdirb &= ~0x00030000; | 151 | io->iop_pdirb &= ~0x00030000; |
158 | io->iop_psorb &= ~0x00030000; | 152 | io->iop_psorb &= ~0x00030000; |
159 | #endif | 153 | #endif |
160 | #endif | ||
161 | cpm2_immr->im_cpmux.cmx_scr &= 0xff00ffff; | 154 | cpm2_immr->im_cpmux.cmx_scr &= 0xff00ffff; |
162 | cpm2_immr->im_cpmux.cmx_scr |= 0x00090000; | 155 | cpm2_immr->im_cpmux.cmx_scr |= 0x00090000; |
163 | pinfo->brg = 2; | 156 | pinfo->brg = 2; |
@@ -218,8 +211,10 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) | |||
218 | 211 | ||
219 | memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) + | 212 | memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) + |
220 | L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize); | 213 | L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize); |
221 | if (is_con) | 214 | if (is_con) { |
222 | mem_addr = alloc_bootmem(memsz); | 215 | mem_addr = alloc_bootmem(memsz); |
216 | dma_addr = mem_addr; | ||
217 | } | ||
223 | else | 218 | else |
224 | mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr, | 219 | mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr, |
225 | GFP_KERNEL); | 220 | GFP_KERNEL); |
@@ -234,6 +229,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) | |||
234 | pinfo->dp_addr = dp_offset; | 229 | pinfo->dp_addr = dp_offset; |
235 | pinfo->mem_addr = mem_addr; | 230 | pinfo->mem_addr = mem_addr; |
236 | pinfo->dma_addr = dma_addr; | 231 | pinfo->dma_addr = dma_addr; |
232 | pinfo->mem_size = memsz; | ||
237 | 233 | ||
238 | pinfo->rx_buf = mem_addr; | 234 | pinfo->rx_buf = mem_addr; |
239 | pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos | 235 | pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos |
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index c3b7a6673e9c..d202eb4f3848 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <asm/io.h> | 45 | #include <asm/io.h> |
46 | #include <asm/irq.h> | 46 | #include <asm/irq.h> |
47 | #include <asm/hardware.h> | 47 | #include <asm/hardware.h> |
48 | #include <asm/arch/imx-uart.h> | ||
48 | 49 | ||
49 | /* We've been assigned a range on the "Low-density serial ports" major */ | 50 | /* We've been assigned a range on the "Low-density serial ports" major */ |
50 | #define SERIAL_IMX_MAJOR 204 | 51 | #define SERIAL_IMX_MAJOR 204 |
@@ -73,7 +74,8 @@ struct imx_port { | |||
73 | struct uart_port port; | 74 | struct uart_port port; |
74 | struct timer_list timer; | 75 | struct timer_list timer; |
75 | unsigned int old_status; | 76 | unsigned int old_status; |
76 | int txirq,rxirq,rtsirq; | 77 | int txirq,rxirq,rtsirq; |
78 | int have_rtscts:1; | ||
77 | }; | 79 | }; |
78 | 80 | ||
79 | /* | 81 | /* |
@@ -491,8 +493,12 @@ imx_set_termios(struct uart_port *port, struct termios *termios, | |||
491 | ucr2 = UCR2_SRST | UCR2_IRTS; | 493 | ucr2 = UCR2_SRST | UCR2_IRTS; |
492 | 494 | ||
493 | if (termios->c_cflag & CRTSCTS) { | 495 | if (termios->c_cflag & CRTSCTS) { |
494 | ucr2 &= ~UCR2_IRTS; | 496 | if( sport->have_rtscts ) { |
495 | ucr2 |= UCR2_CTSC; | 497 | ucr2 &= ~UCR2_IRTS; |
498 | ucr2 |= UCR2_CTSC; | ||
499 | } else { | ||
500 | termios->c_cflag &= ~CRTSCTS; | ||
501 | } | ||
496 | } | 502 | } |
497 | 503 | ||
498 | if (termios->c_cflag & CSTOPB) | 504 | if (termios->c_cflag & CSTOPB) |
@@ -719,27 +725,6 @@ static void __init imx_init_ports(void) | |||
719 | imx_ports[i].timer.function = imx_timeout; | 725 | imx_ports[i].timer.function = imx_timeout; |
720 | imx_ports[i].timer.data = (unsigned long)&imx_ports[i]; | 726 | imx_ports[i].timer.data = (unsigned long)&imx_ports[i]; |
721 | } | 727 | } |
722 | |||
723 | imx_gpio_mode(PC9_PF_UART1_CTS); | ||
724 | imx_gpio_mode(PC10_PF_UART1_RTS); | ||
725 | imx_gpio_mode(PC11_PF_UART1_TXD); | ||
726 | imx_gpio_mode(PC12_PF_UART1_RXD); | ||
727 | imx_gpio_mode(PB28_PF_UART2_CTS); | ||
728 | imx_gpio_mode(PB29_PF_UART2_RTS); | ||
729 | |||
730 | imx_gpio_mode(PB30_PF_UART2_TXD); | ||
731 | imx_gpio_mode(PB31_PF_UART2_RXD); | ||
732 | |||
733 | #if 0 /* We don't need these, on the mx1 the _modem_ side of the uart | ||
734 | * is implemented. | ||
735 | */ | ||
736 | imx_gpio_mode(PD7_AF_UART2_DTR); | ||
737 | imx_gpio_mode(PD8_AF_UART2_DCD); | ||
738 | imx_gpio_mode(PD9_AF_UART2_RI); | ||
739 | imx_gpio_mode(PD10_AF_UART2_DSR); | ||
740 | #endif | ||
741 | |||
742 | |||
743 | } | 728 | } |
744 | 729 | ||
745 | #ifdef CONFIG_SERIAL_IMX_CONSOLE | 730 | #ifdef CONFIG_SERIAL_IMX_CONSOLE |
@@ -932,7 +917,14 @@ static int serial_imx_resume(struct platform_device *dev) | |||
932 | 917 | ||
933 | static int serial_imx_probe(struct platform_device *dev) | 918 | static int serial_imx_probe(struct platform_device *dev) |
934 | { | 919 | { |
920 | struct imxuart_platform_data *pdata; | ||
921 | |||
935 | imx_ports[dev->id].port.dev = &dev->dev; | 922 | imx_ports[dev->id].port.dev = &dev->dev; |
923 | |||
924 | pdata = (struct imxuart_platform_data *)dev->dev.platform_data; | ||
925 | if(pdata && (pdata->flags & IMXUART_HAVE_RTSCTS)) | ||
926 | imx_ports[dev->id].have_rtscts = 1; | ||
927 | |||
936 | uart_add_one_port(&imx_reg, &imx_ports[dev->id].port); | 928 | uart_add_one_port(&imx_reg, &imx_ports[dev->id].port); |
937 | platform_set_drvdata(dev, &imx_ports[dev->id]); | 929 | platform_set_drvdata(dev, &imx_ports[dev->id]); |
938 | return 0; | 930 | return 0; |
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/sn/ioc4.c b/drivers/sn/ioc4.c index 67140a5804f5..cdeff909403e 100644 --- a/drivers/sn/ioc4.c +++ b/drivers/sn/ioc4.c | |||
@@ -310,7 +310,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) | |||
310 | pci_set_drvdata(idd->idd_pdev, idd); | 310 | pci_set_drvdata(idd->idd_pdev, idd); |
311 | 311 | ||
312 | mutex_lock(&ioc4_mutex); | 312 | mutex_lock(&ioc4_mutex); |
313 | list_add(&idd->idd_list, &ioc4_devices); | 313 | list_add_tail(&idd->idd_list, &ioc4_devices); |
314 | 314 | ||
315 | /* Add this IOC4 to all submodules */ | 315 | /* Add this IOC4 to all submodules */ |
316 | list_for_each_entry(is, &ioc4_submodules, is_list) { | 316 | list_for_each_entry(is, &ioc4_submodules, is_list) { |
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 42b457030b03..0eb010a3f5bc 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c | |||
@@ -1614,6 +1614,7 @@ static int activate_ep_files (struct dev_data *dev) | |||
1614 | data, &ep_config_operations, | 1614 | data, &ep_config_operations, |
1615 | &data->dentry); | 1615 | &data->dentry); |
1616 | if (!data->inode) { | 1616 | if (!data->inode) { |
1617 | usb_ep_free_request(ep, data->req); | ||
1617 | kfree (data); | 1618 | kfree (data); |
1618 | goto enomem; | 1619 | goto enomem; |
1619 | } | 1620 | } |
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), |