diff options
Diffstat (limited to 'drivers')
45 files changed, 643 insertions, 311 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/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/mmc/pxamci.c b/drivers/mmc/pxamci.c index eb9a8826e9b5..eb42cb349420 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) { |
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..9788b1ef2e7d 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
@@ -105,6 +105,7 @@ | |||
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. | ||
108 | * | 109 | * |
109 | * Known bugs: | 110 | * Known bugs: |
110 | * We suspect that on some hardware no TX done interrupts are generated. | 111 | * We suspect that on some hardware no TX done interrupts are generated. |
@@ -116,7 +117,7 @@ | |||
116 | * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few | 117 | * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few |
117 | * superfluous timer interrupts from the nic. | 118 | * superfluous timer interrupts from the nic. |
118 | */ | 119 | */ |
119 | #define FORCEDETH_VERSION "0.52" | 120 | #define FORCEDETH_VERSION "0.53" |
120 | #define DRV_NAME "forcedeth" | 121 | #define DRV_NAME "forcedeth" |
121 | 122 | ||
122 | #include <linux/module.h> | 123 | #include <linux/module.h> |
@@ -160,6 +161,7 @@ | |||
160 | #define DEV_HAS_VLAN 0x0020 /* device supports vlan tagging and striping */ | 161 | #define DEV_HAS_VLAN 0x0020 /* device supports vlan tagging and striping */ |
161 | #define DEV_HAS_MSI 0x0040 /* device supports MSI */ | 162 | #define DEV_HAS_MSI 0x0040 /* device supports MSI */ |
162 | #define DEV_HAS_MSI_X 0x0080 /* device supports MSI-X */ | 163 | #define DEV_HAS_MSI_X 0x0080 /* device supports MSI-X */ |
164 | #define DEV_HAS_POWER_CNTRL 0x0100 /* device supports power savings */ | ||
163 | 165 | ||
164 | enum { | 166 | enum { |
165 | NvRegIrqStatus = 0x000, | 167 | NvRegIrqStatus = 0x000, |
@@ -203,6 +205,8 @@ enum { | |||
203 | #define NVREG_MISC1_HD 0x02 | 205 | #define NVREG_MISC1_HD 0x02 |
204 | #define NVREG_MISC1_FORCE 0x3b0f3c | 206 | #define NVREG_MISC1_FORCE 0x3b0f3c |
205 | 207 | ||
208 | NvRegMacReset = 0x3c, | ||
209 | #define NVREG_MAC_RESET_ASSERT 0x0F3 | ||
206 | NvRegTransmitterControl = 0x084, | 210 | NvRegTransmitterControl = 0x084, |
207 | #define NVREG_XMITCTL_START 0x01 | 211 | #define NVREG_XMITCTL_START 0x01 |
208 | NvRegTransmitterStatus = 0x088, | 212 | NvRegTransmitterStatus = 0x088, |
@@ -326,6 +330,10 @@ enum { | |||
326 | NvRegMSIXMap0 = 0x3e0, | 330 | NvRegMSIXMap0 = 0x3e0, |
327 | NvRegMSIXMap1 = 0x3e4, | 331 | NvRegMSIXMap1 = 0x3e4, |
328 | NvRegMSIXIrqStatus = 0x3f0, | 332 | NvRegMSIXIrqStatus = 0x3f0, |
333 | |||
334 | NvRegPowerState2 = 0x600, | ||
335 | #define NVREG_POWERSTATE2_POWERUP_MASK 0x0F11 | ||
336 | #define NVREG_POWERSTATE2_POWERUP_REV_A3 0x0001 | ||
329 | }; | 337 | }; |
330 | 338 | ||
331 | /* Big endian: should work, but is untested */ | 339 | /* Big endian: should work, but is untested */ |
@@ -414,7 +422,8 @@ typedef union _ring_type { | |||
414 | #define NV_RX3_VLAN_TAG_MASK (0x0000FFFF) | 422 | #define NV_RX3_VLAN_TAG_MASK (0x0000FFFF) |
415 | 423 | ||
416 | /* Miscelaneous hardware related defines: */ | 424 | /* Miscelaneous hardware related defines: */ |
417 | #define NV_PCI_REGSZ 0x270 | 425 | #define NV_PCI_REGSZ_VER1 0x270 |
426 | #define NV_PCI_REGSZ_VER2 0x604 | ||
418 | 427 | ||
419 | /* various timeout delays: all in usec */ | 428 | /* various timeout delays: all in usec */ |
420 | #define NV_TXRX_RESET_DELAY 4 | 429 | #define NV_TXRX_RESET_DELAY 4 |
@@ -431,6 +440,7 @@ typedef union _ring_type { | |||
431 | #define NV_MIIBUSY_DELAY 50 | 440 | #define NV_MIIBUSY_DELAY 50 |
432 | #define NV_MIIPHY_DELAY 10 | 441 | #define NV_MIIPHY_DELAY 10 |
433 | #define NV_MIIPHY_DELAYMAX 10000 | 442 | #define NV_MIIPHY_DELAYMAX 10000 |
443 | #define NV_MAC_RESET_DELAY 64 | ||
434 | 444 | ||
435 | #define NV_WAKEUPPATTERNS 5 | 445 | #define NV_WAKEUPPATTERNS 5 |
436 | #define NV_WAKEUPMASKENTRIES 4 | 446 | #define NV_WAKEUPMASKENTRIES 4 |
@@ -552,6 +562,8 @@ struct fe_priv { | |||
552 | u32 desc_ver; | 562 | u32 desc_ver; |
553 | u32 txrxctl_bits; | 563 | u32 txrxctl_bits; |
554 | u32 vlanctl_bits; | 564 | u32 vlanctl_bits; |
565 | u32 driver_data; | ||
566 | u32 register_size; | ||
555 | 567 | ||
556 | void __iomem *base; | 568 | void __iomem *base; |
557 | 569 | ||
@@ -919,6 +931,24 @@ static void nv_txrx_reset(struct net_device *dev) | |||
919 | pci_push(base); | 931 | pci_push(base); |
920 | } | 932 | } |
921 | 933 | ||
934 | static void nv_mac_reset(struct net_device *dev) | ||
935 | { | ||
936 | struct fe_priv *np = netdev_priv(dev); | ||
937 | u8 __iomem *base = get_hwbase(dev); | ||
938 | |||
939 | dprintk(KERN_DEBUG "%s: nv_mac_reset\n", dev->name); | ||
940 | writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl); | ||
941 | pci_push(base); | ||
942 | writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset); | ||
943 | pci_push(base); | ||
944 | udelay(NV_MAC_RESET_DELAY); | ||
945 | writel(0, base + NvRegMacReset); | ||
946 | pci_push(base); | ||
947 | udelay(NV_MAC_RESET_DELAY); | ||
948 | writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl); | ||
949 | pci_push(base); | ||
950 | } | ||
951 | |||
922 | /* | 952 | /* |
923 | * nv_get_stats: dev->get_stats function | 953 | * nv_get_stats: dev->get_stats function |
924 | * Get latest stats value from the nic. | 954 | * Get latest stats value from the nic. |
@@ -1331,7 +1361,7 @@ static void nv_tx_timeout(struct net_device *dev) | |||
1331 | dev->name, (unsigned long)np->ring_addr, | 1361 | dev->name, (unsigned long)np->ring_addr, |
1332 | np->next_tx, np->nic_tx); | 1362 | np->next_tx, np->nic_tx); |
1333 | printk(KERN_INFO "%s: Dumping tx registers\n", dev->name); | 1363 | printk(KERN_INFO "%s: Dumping tx registers\n", dev->name); |
1334 | for (i=0;i<0x400;i+= 32) { | 1364 | for (i=0;i<=np->register_size;i+= 32) { |
1335 | printk(KERN_INFO "%3x: %08x %08x %08x %08x %08x %08x %08x %08x\n", | 1365 | printk(KERN_INFO "%3x: %08x %08x %08x %08x %08x %08x %08x %08x\n", |
1336 | i, | 1366 | i, |
1337 | readl(base + i + 0), readl(base + i + 4), | 1367 | readl(base + i + 0), readl(base + i + 4), |
@@ -2488,11 +2518,11 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
2488 | } | 2518 | } |
2489 | 2519 | ||
2490 | #define FORCEDETH_REGS_VER 1 | 2520 | #define FORCEDETH_REGS_VER 1 |
2491 | #define FORCEDETH_REGS_SIZE 0x400 /* 256 32-bit registers */ | ||
2492 | 2521 | ||
2493 | static int nv_get_regs_len(struct net_device *dev) | 2522 | static int nv_get_regs_len(struct net_device *dev) |
2494 | { | 2523 | { |
2495 | return FORCEDETH_REGS_SIZE; | 2524 | struct fe_priv *np = netdev_priv(dev); |
2525 | return np->register_size; | ||
2496 | } | 2526 | } |
2497 | 2527 | ||
2498 | static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf) | 2528 | static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf) |
@@ -2504,7 +2534,7 @@ static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void | |||
2504 | 2534 | ||
2505 | regs->version = FORCEDETH_REGS_VER; | 2535 | regs->version = FORCEDETH_REGS_VER; |
2506 | spin_lock_irq(&np->lock); | 2536 | spin_lock_irq(&np->lock); |
2507 | for (i=0;i<FORCEDETH_REGS_SIZE/sizeof(u32);i++) | 2537 | for (i = 0;i <= np->register_size/sizeof(u32); i++) |
2508 | rbuf[i] = readl(base + i*sizeof(u32)); | 2538 | rbuf[i] = readl(base + i*sizeof(u32)); |
2509 | spin_unlock_irq(&np->lock); | 2539 | spin_unlock_irq(&np->lock); |
2510 | } | 2540 | } |
@@ -2608,6 +2638,8 @@ static int nv_open(struct net_device *dev) | |||
2608 | dprintk(KERN_DEBUG "nv_open: begin\n"); | 2638 | dprintk(KERN_DEBUG "nv_open: begin\n"); |
2609 | 2639 | ||
2610 | /* 1) erase previous misconfiguration */ | 2640 | /* 1) erase previous misconfiguration */ |
2641 | if (np->driver_data & DEV_HAS_POWER_CNTRL) | ||
2642 | nv_mac_reset(dev); | ||
2611 | /* 4.1-1: stop adapter: ignored, 4.3 seems to be overkill */ | 2643 | /* 4.1-1: stop adapter: ignored, 4.3 seems to be overkill */ |
2612 | writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA); | 2644 | writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA); |
2613 | writel(0, base + NvRegMulticastAddrB); | 2645 | writel(0, base + NvRegMulticastAddrB); |
@@ -2878,6 +2910,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
2878 | unsigned long addr; | 2910 | unsigned long addr; |
2879 | u8 __iomem *base; | 2911 | u8 __iomem *base; |
2880 | int err, i; | 2912 | int err, i; |
2913 | u32 powerstate; | ||
2881 | 2914 | ||
2882 | dev = alloc_etherdev(sizeof(struct fe_priv)); | 2915 | dev = alloc_etherdev(sizeof(struct fe_priv)); |
2883 | err = -ENOMEM; | 2916 | err = -ENOMEM; |
@@ -2910,6 +2943,11 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
2910 | if (err < 0) | 2943 | if (err < 0) |
2911 | goto out_disable; | 2944 | goto out_disable; |
2912 | 2945 | ||
2946 | if (id->driver_data & (DEV_HAS_VLAN|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL)) | ||
2947 | np->register_size = NV_PCI_REGSZ_VER2; | ||
2948 | else | ||
2949 | np->register_size = NV_PCI_REGSZ_VER1; | ||
2950 | |||
2913 | err = -EINVAL; | 2951 | err = -EINVAL; |
2914 | addr = 0; | 2952 | addr = 0; |
2915 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { | 2953 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { |
@@ -2918,7 +2956,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
2918 | pci_resource_len(pci_dev, i), | 2956 | pci_resource_len(pci_dev, i), |
2919 | pci_resource_flags(pci_dev, i)); | 2957 | pci_resource_flags(pci_dev, i)); |
2920 | if (pci_resource_flags(pci_dev, i) & IORESOURCE_MEM && | 2958 | if (pci_resource_flags(pci_dev, i) & IORESOURCE_MEM && |
2921 | pci_resource_len(pci_dev, i) >= NV_PCI_REGSZ) { | 2959 | pci_resource_len(pci_dev, i) >= np->register_size) { |
2922 | addr = pci_resource_start(pci_dev, i); | 2960 | addr = pci_resource_start(pci_dev, i); |
2923 | break; | 2961 | break; |
2924 | } | 2962 | } |
@@ -2929,6 +2967,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
2929 | goto out_relreg; | 2967 | goto out_relreg; |
2930 | } | 2968 | } |
2931 | 2969 | ||
2970 | /* copy of driver data */ | ||
2971 | np->driver_data = id->driver_data; | ||
2972 | |||
2932 | /* handle different descriptor versions */ | 2973 | /* handle different descriptor versions */ |
2933 | if (id->driver_data & DEV_HAS_HIGH_DMA) { | 2974 | if (id->driver_data & DEV_HAS_HIGH_DMA) { |
2934 | /* packet format 3: supports 40-bit addressing */ | 2975 | /* packet format 3: supports 40-bit addressing */ |
@@ -2986,7 +3027,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
2986 | } | 3027 | } |
2987 | 3028 | ||
2988 | err = -ENOMEM; | 3029 | err = -ENOMEM; |
2989 | np->base = ioremap(addr, NV_PCI_REGSZ); | 3030 | np->base = ioremap(addr, np->register_size); |
2990 | if (!np->base) | 3031 | if (!np->base) |
2991 | goto out_relreg; | 3032 | goto out_relreg; |
2992 | dev->base_addr = (unsigned long)np->base; | 3033 | dev->base_addr = (unsigned long)np->base; |
@@ -3062,6 +3103,20 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
3062 | writel(0, base + NvRegWakeUpFlags); | 3103 | writel(0, base + NvRegWakeUpFlags); |
3063 | np->wolenabled = 0; | 3104 | np->wolenabled = 0; |
3064 | 3105 | ||
3106 | if (id->driver_data & DEV_HAS_POWER_CNTRL) { | ||
3107 | u8 revision_id; | ||
3108 | pci_read_config_byte(pci_dev, PCI_REVISION_ID, &revision_id); | ||
3109 | |||
3110 | /* take phy and nic out of low power mode */ | ||
3111 | powerstate = readl(base + NvRegPowerState2); | ||
3112 | powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK; | ||
3113 | if ((id->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 || | ||
3114 | id->device == PCI_DEVICE_ID_NVIDIA_NVENET_13) && | ||
3115 | revision_id >= 0xA3) | ||
3116 | powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3; | ||
3117 | writel(powerstate, base + NvRegPowerState2); | ||
3118 | } | ||
3119 | |||
3065 | if (np->desc_ver == DESC_VER_1) { | 3120 | if (np->desc_ver == DESC_VER_1) { |
3066 | np->tx_flags = NV_TX_VALID; | 3121 | np->tx_flags = NV_TX_VALID; |
3067 | } else { | 3122 | } else { |
@@ -3223,19 +3278,19 @@ static struct pci_device_id pci_tbl[] = { | |||
3223 | }, | 3278 | }, |
3224 | { /* MCP51 Ethernet Controller */ | 3279 | { /* MCP51 Ethernet Controller */ |
3225 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12), | 3280 | 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, | 3281 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL, |
3227 | }, | 3282 | }, |
3228 | { /* MCP51 Ethernet Controller */ | 3283 | { /* MCP51 Ethernet Controller */ |
3229 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_13), | 3284 | 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, | 3285 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL, |
3231 | }, | 3286 | }, |
3232 | { /* MCP55 Ethernet Controller */ | 3287 | { /* MCP55 Ethernet Controller */ |
3233 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14), | 3288 | 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, | 3289 | .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 | }, | 3290 | }, |
3236 | { /* MCP55 Ethernet Controller */ | 3291 | { /* MCP55 Ethernet Controller */ |
3237 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15), | 3292 | 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, | 3293 | .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 | }, | 3294 | }, |
3240 | {0,}, | 3295 | {0,}, |
3241 | }; | 3296 | }; |
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/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/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h index 2d520e4b0276..b7d77638ba8c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h | |||
@@ -213,6 +213,14 @@ static inline | |||
213 | void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) | 213 | void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) |
214 | { | 214 | { |
215 | } | 215 | } |
216 | static inline | ||
217 | void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring) | ||
218 | { | ||
219 | } | ||
220 | static inline | ||
221 | void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring) | ||
222 | { | ||
223 | } | ||
216 | 224 | ||
217 | #endif /* CONFIG_BCM43XX_DMA */ | 225 | #endif /* CONFIG_BCM43XX_DMA */ |
218 | #endif /* BCM43xx_DMA_H_ */ | 226 | #endif /* BCM43xx_DMA_H_ */ |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index c59ddd40680d..0aa1bd269a25 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "bcm43xx_pio.h" | 27 | #include "bcm43xx_pio.h" |
28 | #include "bcm43xx_main.h" | 28 | #include "bcm43xx_main.h" |
29 | #include "bcm43xx_xmit.h" | 29 | #include "bcm43xx_xmit.h" |
30 | #include "bcm43xx_power.h" | ||
30 | 31 | ||
31 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
32 | 33 | ||
@@ -44,10 +45,10 @@ static void tx_octet(struct bcm43xx_pioqueue *queue, | |||
44 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, | 45 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, |
45 | octet); | 46 | octet); |
46 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | 47 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, |
47 | BCM43xx_PIO_TXCTL_WRITEHI); | 48 | BCM43xx_PIO_TXCTL_WRITELO); |
48 | } else { | 49 | } else { |
49 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | 50 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, |
50 | BCM43xx_PIO_TXCTL_WRITEHI); | 51 | BCM43xx_PIO_TXCTL_WRITELO); |
51 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, | 52 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, |
52 | octet); | 53 | octet); |
53 | } | 54 | } |
@@ -103,7 +104,7 @@ static void tx_complete(struct bcm43xx_pioqueue *queue, | |||
103 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, | 104 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, |
104 | skb->data[skb->len - 1]); | 105 | skb->data[skb->len - 1]); |
105 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | 106 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, |
106 | BCM43xx_PIO_TXCTL_WRITEHI | | 107 | BCM43xx_PIO_TXCTL_WRITELO | |
107 | BCM43xx_PIO_TXCTL_COMPLETE); | 108 | BCM43xx_PIO_TXCTL_COMPLETE); |
108 | } else { | 109 | } else { |
109 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | 110 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, |
@@ -112,9 +113,10 @@ static void tx_complete(struct bcm43xx_pioqueue *queue, | |||
112 | } | 113 | } |
113 | 114 | ||
114 | static u16 generate_cookie(struct bcm43xx_pioqueue *queue, | 115 | static u16 generate_cookie(struct bcm43xx_pioqueue *queue, |
115 | int packetindex) | 116 | struct bcm43xx_pio_txpacket *packet) |
116 | { | 117 | { |
117 | u16 cookie = 0x0000; | 118 | u16 cookie = 0x0000; |
119 | int packetindex; | ||
118 | 120 | ||
119 | /* We use the upper 4 bits for the PIO | 121 | /* We use the upper 4 bits for the PIO |
120 | * controller ID and the lower 12 bits | 122 | * controller ID and the lower 12 bits |
@@ -135,6 +137,7 @@ static u16 generate_cookie(struct bcm43xx_pioqueue *queue, | |||
135 | default: | 137 | default: |
136 | assert(0); | 138 | assert(0); |
137 | } | 139 | } |
140 | packetindex = pio_txpacket_getindex(packet); | ||
138 | assert(((u16)packetindex & 0xF000) == 0x0000); | 141 | assert(((u16)packetindex & 0xF000) == 0x0000); |
139 | cookie |= (u16)packetindex; | 142 | cookie |= (u16)packetindex; |
140 | 143 | ||
@@ -184,7 +187,7 @@ static void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue, | |||
184 | bcm43xx_generate_txhdr(queue->bcm, | 187 | bcm43xx_generate_txhdr(queue->bcm, |
185 | &txhdr, skb->data, skb->len, | 188 | &txhdr, skb->data, skb->len, |
186 | (packet->xmitted_frags == 0), | 189 | (packet->xmitted_frags == 0), |
187 | generate_cookie(queue, pio_txpacket_getindex(packet))); | 190 | generate_cookie(queue, packet)); |
188 | 191 | ||
189 | tx_start(queue); | 192 | tx_start(queue); |
190 | octets = skb->len + sizeof(txhdr); | 193 | octets = skb->len + sizeof(txhdr); |
@@ -241,7 +244,7 @@ static int pio_tx_packet(struct bcm43xx_pio_txpacket *packet) | |||
241 | queue->tx_devq_packets++; | 244 | queue->tx_devq_packets++; |
242 | queue->tx_devq_used += octets; | 245 | queue->tx_devq_used += octets; |
243 | 246 | ||
244 | assert(packet->xmitted_frags <= packet->txb->nr_frags); | 247 | assert(packet->xmitted_frags < packet->txb->nr_frags); |
245 | packet->xmitted_frags++; | 248 | packet->xmitted_frags++; |
246 | packet->xmitted_octets += octets; | 249 | packet->xmitted_octets += octets; |
247 | } | 250 | } |
@@ -257,8 +260,14 @@ static void tx_tasklet(unsigned long d) | |||
257 | unsigned long flags; | 260 | unsigned long flags; |
258 | struct bcm43xx_pio_txpacket *packet, *tmp_packet; | 261 | struct bcm43xx_pio_txpacket *packet, *tmp_packet; |
259 | int err; | 262 | int err; |
263 | u16 txctl; | ||
260 | 264 | ||
261 | bcm43xx_lock_mmio(bcm, flags); | 265 | bcm43xx_lock_mmio(bcm, flags); |
266 | |||
267 | txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); | ||
268 | if (txctl & BCM43xx_PIO_TXCTL_SUSPEND) | ||
269 | goto out_unlock; | ||
270 | |||
262 | list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { | 271 | list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { |
263 | assert(packet->xmitted_frags < packet->txb->nr_frags); | 272 | assert(packet->xmitted_frags < packet->txb->nr_frags); |
264 | if (packet->xmitted_frags == 0) { | 273 | if (packet->xmitted_frags == 0) { |
@@ -288,6 +297,7 @@ static void tx_tasklet(unsigned long d) | |||
288 | next_packet: | 297 | next_packet: |
289 | continue; | 298 | continue; |
290 | } | 299 | } |
300 | out_unlock: | ||
291 | bcm43xx_unlock_mmio(bcm, flags); | 301 | bcm43xx_unlock_mmio(bcm, flags); |
292 | } | 302 | } |
293 | 303 | ||
@@ -330,12 +340,19 @@ struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm, | |||
330 | (unsigned long)queue); | 340 | (unsigned long)queue); |
331 | 341 | ||
332 | value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); | 342 | value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); |
333 | value |= BCM43xx_SBF_XFER_REG_BYTESWAP; | 343 | value &= ~BCM43xx_SBF_XFER_REG_BYTESWAP; |
334 | bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value); | 344 | bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value); |
335 | 345 | ||
336 | qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE); | 346 | qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE); |
347 | if (qsize == 0) { | ||
348 | printk(KERN_ERR PFX "ERROR: This card does not support PIO " | ||
349 | "operation mode. Please use DMA mode " | ||
350 | "(module parameter pio=0).\n"); | ||
351 | goto err_freequeue; | ||
352 | } | ||
337 | if (qsize <= BCM43xx_PIO_TXQADJUST) { | 353 | if (qsize <= BCM43xx_PIO_TXQADJUST) { |
338 | printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", qsize); | 354 | printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", |
355 | qsize); | ||
339 | goto err_freequeue; | 356 | goto err_freequeue; |
340 | } | 357 | } |
341 | qsize -= BCM43xx_PIO_TXQADJUST; | 358 | qsize -= BCM43xx_PIO_TXQADJUST; |
@@ -444,15 +461,10 @@ int bcm43xx_pio_tx(struct bcm43xx_private *bcm, | |||
444 | { | 461 | { |
445 | struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1; | 462 | struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1; |
446 | struct bcm43xx_pio_txpacket *packet; | 463 | struct bcm43xx_pio_txpacket *packet; |
447 | u16 tmp; | ||
448 | 464 | ||
449 | assert(!queue->tx_suspended); | 465 | assert(!queue->tx_suspended); |
450 | assert(!list_empty(&queue->txfree)); | 466 | assert(!list_empty(&queue->txfree)); |
451 | 467 | ||
452 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); | ||
453 | if (tmp & BCM43xx_PIO_TXCTL_SUSPEND) | ||
454 | return -EBUSY; | ||
455 | |||
456 | packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list); | 468 | packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list); |
457 | packet->txb = txb; | 469 | packet->txb = txb; |
458 | packet->xmitted_frags = 0; | 470 | packet->xmitted_frags = 0; |
@@ -462,7 +474,7 @@ int bcm43xx_pio_tx(struct bcm43xx_private *bcm, | |||
462 | assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS); | 474 | assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS); |
463 | 475 | ||
464 | /* Suspend TX, if we are out of packets in the "free" queue. */ | 476 | /* Suspend TX, if we are out of packets in the "free" queue. */ |
465 | if (unlikely(list_empty(&queue->txfree))) { | 477 | if (list_empty(&queue->txfree)) { |
466 | netif_stop_queue(queue->bcm->net_dev); | 478 | netif_stop_queue(queue->bcm->net_dev); |
467 | queue->tx_suspended = 1; | 479 | queue->tx_suspended = 1; |
468 | } | 480 | } |
@@ -480,15 +492,15 @@ void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, | |||
480 | 492 | ||
481 | queue = parse_cookie(bcm, status->cookie, &packet); | 493 | queue = parse_cookie(bcm, status->cookie, &packet); |
482 | assert(queue); | 494 | assert(queue); |
483 | //TODO | 495 | |
484 | if (!queue) | ||
485 | return; | ||
486 | free_txpacket(packet, 1); | 496 | free_txpacket(packet, 1); |
487 | if (unlikely(queue->tx_suspended)) { | 497 | if (queue->tx_suspended) { |
488 | queue->tx_suspended = 0; | 498 | queue->tx_suspended = 0; |
489 | netif_wake_queue(queue->bcm->net_dev); | 499 | netif_wake_queue(queue->bcm->net_dev); |
490 | } | 500 | } |
491 | /* If there are packets on the txqueue, poke the tasklet. */ | 501 | /* If there are packets on the txqueue, poke the tasklet |
502 | * to transmit them. | ||
503 | */ | ||
492 | if (!list_empty(&queue->txqueue)) | 504 | if (!list_empty(&queue->txqueue)) |
493 | tasklet_schedule(&queue->txtask); | 505 | tasklet_schedule(&queue->txtask); |
494 | } | 506 | } |
@@ -519,12 +531,9 @@ void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) | |||
519 | int i, preamble_readwords; | 531 | int i, preamble_readwords; |
520 | struct sk_buff *skb; | 532 | struct sk_buff *skb; |
521 | 533 | ||
522 | return; | ||
523 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); | 534 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); |
524 | if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) { | 535 | if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) |
525 | dprintkl(KERN_ERR PFX "PIO RX: No data available\n");//TODO: remove this printk. | ||
526 | return; | 536 | return; |
527 | } | ||
528 | bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, | 537 | bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, |
529 | BCM43xx_PIO_RXCTL_DATAAVAILABLE); | 538 | BCM43xx_PIO_RXCTL_DATAAVAILABLE); |
530 | 539 | ||
@@ -538,8 +547,7 @@ return; | |||
538 | return; | 547 | return; |
539 | data_ready: | 548 | data_ready: |
540 | 549 | ||
541 | //FIXME: endianess in this function. | 550 | len = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); |
542 | len = le16_to_cpu(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); | ||
543 | if (unlikely(len > 0x700)) { | 551 | if (unlikely(len > 0x700)) { |
544 | pio_rx_error(queue, 0, "len > 0x700"); | 552 | pio_rx_error(queue, 0, "len > 0x700"); |
545 | return; | 553 | return; |
@@ -555,7 +563,7 @@ data_ready: | |||
555 | preamble_readwords = 18 / sizeof(u16); | 563 | preamble_readwords = 18 / sizeof(u16); |
556 | for (i = 0; i < preamble_readwords; i++) { | 564 | for (i = 0; i < preamble_readwords; i++) { |
557 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); | 565 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); |
558 | preamble[i + 1] = cpu_to_be16(tmp);//FIXME? | 566 | preamble[i + 1] = cpu_to_le16(tmp); |
559 | } | 567 | } |
560 | rxhdr = (struct bcm43xx_rxhdr *)preamble; | 568 | rxhdr = (struct bcm43xx_rxhdr *)preamble; |
561 | rxflags2 = le16_to_cpu(rxhdr->flags2); | 569 | rxflags2 = le16_to_cpu(rxhdr->flags2); |
@@ -591,16 +599,40 @@ data_ready: | |||
591 | } | 599 | } |
592 | skb_put(skb, len); | 600 | skb_put(skb, len); |
593 | for (i = 0; i < len - 1; i += 2) { | 601 | for (i = 0; i < len - 1; i += 2) { |
594 | tmp = cpu_to_be16(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); | 602 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); |
595 | *((u16 *)(skb->data + i)) = tmp; | 603 | *((u16 *)(skb->data + i)) = cpu_to_le16(tmp); |
596 | } | 604 | } |
597 | if (len % 2) { | 605 | if (len % 2) { |
598 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); | 606 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); |
599 | skb->data[len - 1] = (tmp & 0x00FF); | 607 | skb->data[len - 1] = (tmp & 0x00FF); |
608 | /* The specs say the following is required, but | ||
609 | * it is wrong and corrupts the PLCP. If we don't do | ||
610 | * this, the PLCP seems to be correct. So ifdef it out for now. | ||
611 | */ | ||
612 | #if 0 | ||
600 | if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) | 613 | if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) |
601 | skb->data[0x20] = (tmp & 0xFF00) >> 8; | 614 | skb->data[2] = (tmp & 0xFF00) >> 8; |
602 | else | 615 | else |
603 | skb->data[0x1E] = (tmp & 0xFF00) >> 8; | 616 | skb->data[0] = (tmp & 0xFF00) >> 8; |
617 | #endif | ||
604 | } | 618 | } |
619 | skb_trim(skb, len - IEEE80211_FCS_LEN); | ||
605 | bcm43xx_rx(queue->bcm, skb, rxhdr); | 620 | bcm43xx_rx(queue->bcm, skb, rxhdr); |
606 | } | 621 | } |
622 | |||
623 | void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue) | ||
624 | { | ||
625 | bcm43xx_power_saving_ctl_bits(queue->bcm, -1, 1); | ||
626 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | ||
627 | bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL) | ||
628 | | BCM43xx_PIO_TXCTL_SUSPEND); | ||
629 | } | ||
630 | |||
631 | void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue) | ||
632 | { | ||
633 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | ||
634 | bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL) | ||
635 | & ~BCM43xx_PIO_TXCTL_SUSPEND); | ||
636 | bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1); | ||
637 | tasklet_schedule(&queue->txtask); | ||
638 | } | ||
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h index 970627bc1769..dfc78209e3a3 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h | |||
@@ -14,8 +14,8 @@ | |||
14 | #define BCM43xx_PIO_RXCTL 0x08 | 14 | #define BCM43xx_PIO_RXCTL 0x08 |
15 | #define BCM43xx_PIO_RXDATA 0x0A | 15 | #define BCM43xx_PIO_RXDATA 0x0A |
16 | 16 | ||
17 | #define BCM43xx_PIO_TXCTL_WRITEHI (1 << 0) | 17 | #define BCM43xx_PIO_TXCTL_WRITELO (1 << 0) |
18 | #define BCM43xx_PIO_TXCTL_WRITELO (1 << 1) | 18 | #define BCM43xx_PIO_TXCTL_WRITEHI (1 << 1) |
19 | #define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2) | 19 | #define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2) |
20 | #define BCM43xx_PIO_TXCTL_INIT (1 << 3) | 20 | #define BCM43xx_PIO_TXCTL_INIT (1 << 3) |
21 | #define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7) | 21 | #define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7) |
@@ -95,6 +95,7 @@ void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue, | |||
95 | u16 offset, u16 value) | 95 | u16 offset, u16 value) |
96 | { | 96 | { |
97 | bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value); | 97 | bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value); |
98 | mmiowb(); | ||
98 | } | 99 | } |
99 | 100 | ||
100 | 101 | ||
@@ -107,6 +108,9 @@ void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, | |||
107 | struct bcm43xx_xmitstatus *status); | 108 | struct bcm43xx_xmitstatus *status); |
108 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue); | 109 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue); |
109 | 110 | ||
111 | void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue); | ||
112 | void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue); | ||
113 | |||
110 | #else /* CONFIG_BCM43XX_PIO */ | 114 | #else /* CONFIG_BCM43XX_PIO */ |
111 | 115 | ||
112 | static inline | 116 | static inline |
@@ -133,6 +137,14 @@ static inline | |||
133 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) | 137 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) |
134 | { | 138 | { |
135 | } | 139 | } |
140 | static inline | ||
141 | void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue) | ||
142 | { | ||
143 | } | ||
144 | static inline | ||
145 | void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue) | ||
146 | { | ||
147 | } | ||
136 | 148 | ||
137 | #endif /* CONFIG_BCM43XX_PIO */ | 149 | #endif /* CONFIG_BCM43XX_PIO */ |
138 | #endif /* BCM43xx_PIO_H_ */ | 150 | #endif /* BCM43xx_PIO_H_ */ |
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index 8b37e824dfcb..8399de581893 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c | |||
@@ -1860,7 +1860,7 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
1860 | memset(&iwe, 0, sizeof(iwe)); | 1860 | memset(&iwe, 0, sizeof(iwe)); |
1861 | iwe.cmd = SIOCGIWFREQ; | 1861 | iwe.cmd = SIOCGIWFREQ; |
1862 | if (scan) { | 1862 | if (scan) { |
1863 | chan = scan->chid; | 1863 | chan = le16_to_cpu(scan->chid); |
1864 | } else if (bss) { | 1864 | } else if (bss) { |
1865 | chan = bss->chan; | 1865 | chan = bss->chan; |
1866 | } else { | 1866 | } else { |
@@ -1868,7 +1868,7 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
1868 | } | 1868 | } |
1869 | 1869 | ||
1870 | if (chan > 0) { | 1870 | if (chan > 0) { |
1871 | iwe.u.freq.m = freq_list[le16_to_cpu(chan - 1)] * 100000; | 1871 | iwe.u.freq.m = freq_list[chan - 1] * 100000; |
1872 | iwe.u.freq.e = 1; | 1872 | iwe.u.freq.e = 1; |
1873 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 1873 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, |
1874 | IW_EV_FREQ_LEN); | 1874 | IW_EV_FREQ_LEN); |
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/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/s390mach.c b/drivers/s390/s390mach.c index 3bf466603512..5ae14803091f 100644 --- a/drivers/s390/s390mach.c +++ b/drivers/s390/s390mach.c | |||
@@ -362,12 +362,19 @@ s390_revalidate_registers(struct mci *mci) | |||
362 | return kill_task; | 362 | return kill_task; |
363 | } | 363 | } |
364 | 364 | ||
365 | #define MAX_IPD_COUNT 29 | ||
366 | #define MAX_IPD_TIME (5 * 60 * 100 * 1000) /* 5 minutes */ | ||
367 | |||
365 | /* | 368 | /* |
366 | * machine check handler. | 369 | * machine check handler. |
367 | */ | 370 | */ |
368 | void | 371 | void |
369 | s390_do_machine_check(struct pt_regs *regs) | 372 | s390_do_machine_check(struct pt_regs *regs) |
370 | { | 373 | { |
374 | static DEFINE_SPINLOCK(ipd_lock); | ||
375 | static unsigned long long last_ipd; | ||
376 | static int ipd_count; | ||
377 | unsigned long long tmp; | ||
371 | struct mci *mci; | 378 | struct mci *mci; |
372 | struct mcck_struct *mcck; | 379 | struct mcck_struct *mcck; |
373 | int umode; | 380 | int umode; |
@@ -404,11 +411,27 @@ s390_do_machine_check(struct pt_regs *regs) | |||
404 | s390_handle_damage("processing backup machine " | 411 | s390_handle_damage("processing backup machine " |
405 | "check with damage."); | 412 | "check with damage."); |
406 | } | 413 | } |
407 | if (!umode) | 414 | |
408 | s390_handle_damage("processing backup machine " | 415 | /* |
409 | "check in kernel mode."); | 416 | * Nullifying exigent condition, therefore we might |
410 | mcck->kill_task = 1; | 417 | * retry this instruction. |
411 | mcck->mcck_code = *(unsigned long long *) mci; | 418 | */ |
419 | |||
420 | spin_lock(&ipd_lock); | ||
421 | |||
422 | tmp = get_clock(); | ||
423 | |||
424 | if (((tmp - last_ipd) >> 12) < MAX_IPD_TIME) | ||
425 | ipd_count++; | ||
426 | else | ||
427 | ipd_count = 1; | ||
428 | |||
429 | last_ipd = tmp; | ||
430 | |||
431 | if (ipd_count == MAX_IPD_COUNT) | ||
432 | s390_handle_damage("too many ipd retries."); | ||
433 | |||
434 | spin_unlock(&ipd_lock); | ||
412 | } | 435 | } |
413 | else { | 436 | else { |
414 | /* Processing damage -> stopping machine */ | 437 | /* Processing damage -> stopping machine */ |
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/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), |