From 23a75eee070f1370bee803a34f285cf81eb5f331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szilveszter=20=C3=96rd=C3=B6g?= Date: Fri, 6 Aug 2010 09:26:38 +0800 Subject: crypto: hash - Fix handling of small unaligned buffers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a scatterwalk chain contains an entry with an unaligned offset then hash_walk_next() will cut off the next step at the next alignment point. However, if the entry ends before the next alignment point then we a loop, which leads to a kernel oops. Fix this by checking whether the next aligment point is before the end of the current entry. Signed-off-by: Szilveszter Ördög Acked-by: David S. Miller Signed-off-by: Herbert Xu diff --git a/crypto/ahash.c b/crypto/ahash.c index b8c59b8..f669822 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -47,8 +47,11 @@ static int hash_walk_next(struct crypto_hash_walk *walk) walk->data = crypto_kmap(walk->pg, 0); walk->data += offset; - if (offset & alignmask) - nbytes = alignmask + 1 - (offset & alignmask); + if (offset & alignmask) { + unsigned int unaligned = alignmask + 1 - (offset & alignmask); + if (nbytes > unaligned) + nbytes = unaligned; + } walk->entrylen -= nbytes; return nbytes; -- cgit v0.10.2 From 326a6346ffb5b19eb593530d9d3096d409e46f62 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 6 Aug 2010 09:40:28 +0800 Subject: crypto: testmgr - Fix test disabling option This patch fixes a serious bug in the test disabling patch where it can cause an spurious load of the cryptomgr module even when it's compiled in. It also negates the test disabling option so that its absence causes tests to be enabled. The Kconfig option is also now behind EMBEDDED. Signed-off-by: Herbert Xu diff --git a/crypto/Kconfig b/crypto/Kconfig index 1cd497d..6f5c50f 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -101,13 +101,12 @@ config CRYPTO_MANAGER2 select CRYPTO_BLKCIPHER2 select CRYPTO_PCOMP2 -config CRYPTO_MANAGER_TESTS - bool "Run algolithms' self-tests" - default y - depends on CRYPTO_MANAGER2 +config CRYPTO_MANAGER_DISABLE_TESTS + bool "Disable run-time self tests" + depends on CRYPTO_MANAGER2 && EMBEDDED help - Run cryptomanager's tests for the new crypto algorithms being - registered. + Disable run-time self tests that normally take place at + algorithm registration. config CRYPTO_GF128MUL tristate "GF(2^128) multiplication functions (EXPERIMENTAL)" diff --git a/crypto/algboss.c b/crypto/algboss.c index 40bd391..791d194 100644 --- a/crypto/algboss.c +++ b/crypto/algboss.c @@ -206,13 +206,16 @@ err: return NOTIFY_OK; } -#ifdef CONFIG_CRYPTO_MANAGER_TESTS static int cryptomgr_test(void *data) { struct crypto_test_param *param = data; u32 type = param->type; int err = 0; +#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS + goto skiptest; +#endif + if (type & CRYPTO_ALG_TESTED) goto skiptest; @@ -267,7 +270,6 @@ err_put_module: err: return NOTIFY_OK; } -#endif /* CONFIG_CRYPTO_MANAGER_TESTS */ static int cryptomgr_notify(struct notifier_block *this, unsigned long msg, void *data) @@ -275,10 +277,8 @@ static int cryptomgr_notify(struct notifier_block *this, unsigned long msg, switch (msg) { case CRYPTO_MSG_ALG_REQUEST: return cryptomgr_schedule_probe(data); -#ifdef CONFIG_CRYPTO_MANAGER_TESTS case CRYPTO_MSG_ALG_REGISTER: return cryptomgr_schedule_test(data); -#endif } return NOTIFY_DONE; diff --git a/crypto/testmgr.c b/crypto/testmgr.c index abd980c7..fa8c8f7 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -23,7 +23,7 @@ #include "internal.h" -#ifndef CONFIG_CRYPTO_MANAGER_TESTS +#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS /* a perfect nop */ int alg_test(const char *driver, const char *alg, u32 type, u32 mask) @@ -2542,6 +2542,6 @@ non_fips_alg: return -EINVAL; } -#endif /* CONFIG_CRYPTO_MANAGER_TESTS */ +#endif /* CONFIG_CRYPTO_MANAGER_DISABLE_TESTS */ EXPORT_SYMBOL_GPL(alg_test); -- cgit v0.10.2 From 00ca28a507b215dcd121735f16764ea4173c4ff9 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 6 Aug 2010 10:34:00 +0800 Subject: crypto: testmgr - Default to no tests On Thu, Aug 05, 2010 at 07:01:21PM -0700, Linus Torvalds wrote: > On Thu, Aug 5, 2010 at 6:40 PM, Herbert Xu wrote: > > > > -config CRYPTO_MANAGER_TESTS > > - bool "Run algolithms' self-tests" > > - default y > > - depends on CRYPTO_MANAGER2 > > +config CRYPTO_MANAGER_DISABLE_TESTS > > + bool "Disable run-time self tests" > > + depends on CRYPTO_MANAGER2 && EMBEDDED > > Why do you still want to force-enable those tests? I was going to > complain about the "default y" anyway, now I'm _really_ complaining, > because you've now made it impossible to disable those tests. Why? As requested, this patch sets the default to y and removes the EMBEDDED dependency. Signed-off-by: Herbert Xu diff --git a/crypto/Kconfig b/crypto/Kconfig index 6f5c50f..e573077 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -103,7 +103,8 @@ config CRYPTO_MANAGER2 config CRYPTO_MANAGER_DISABLE_TESTS bool "Disable run-time self tests" - depends on CRYPTO_MANAGER2 && EMBEDDED + default y + depends on CRYPTO_MANAGER2 help Disable run-time self tests that normally take place at algorithm registration. -- cgit v0.10.2 From 18cb2aef91b37dbce2bec2f39bb1dddd0e9dd838 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Sat, 7 Aug 2010 03:26:23 +0900 Subject: percpu: handle __percpu notations in UP accessors UP accessors didn't take care of __percpu notations leading to a lot of spurious sparse warnings on UP configurations. Fix it. Signed-off-by: Namhyung Kim Signed-off-by: Tejun Heo diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h index b5043a9..08923b6 100644 --- a/include/asm-generic/percpu.h +++ b/include/asm-generic/percpu.h @@ -70,11 +70,16 @@ extern void setup_per_cpu_areas(void); #else /* ! SMP */ -#define per_cpu(var, cpu) (*((void)(cpu), &(var))) -#define __get_cpu_var(var) (var) -#define __raw_get_cpu_var(var) (var) -#define this_cpu_ptr(ptr) per_cpu_ptr(ptr, 0) -#define __this_cpu_ptr(ptr) this_cpu_ptr(ptr) +#define VERIFY_PERCPU_PTR(__p) ({ \ + __verify_pcpu_ptr((__p)); \ + (typeof(*(__p)) __kernel __force *)(__p); \ +}) + +#define per_cpu(var, cpu) (*((void)(cpu), VERIFY_PERCPU_PTR(&(var)))) +#define __get_cpu_var(var) (*VERIFY_PERCPU_PTR(&(var))) +#define __raw_get_cpu_var(var) (*VERIFY_PERCPU_PTR(&(var))) +#define this_cpu_ptr(ptr) per_cpu_ptr(ptr, 0) +#define __this_cpu_ptr(ptr) this_cpu_ptr(ptr) #endif /* SMP */ diff --git a/include/linux/percpu.h b/include/linux/percpu.h index b8b9084..49466b1 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h @@ -149,7 +149,7 @@ extern void __init percpu_init_late(void); #else /* CONFIG_SMP */ -#define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); (ptr); }) +#define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); VERIFY_PERCPU_PTR((ptr)); }) /* can't distinguish from other static vars, always false */ static inline bool is_kernel_percpu_address(unsigned long addr) -- cgit v0.10.2 From 94cb121c9483f1ec9b1ef0c249fbfc49c628fa6b Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Sat, 7 Aug 2010 03:26:24 +0900 Subject: percpu: add __percpu notations to UP allocator Add __percpu notations to UP percpu allocator. Signed-off-by: Namhyung Kim Signed-off-by: Tejun Heo diff --git a/mm/percpu_up.c b/mm/percpu_up.c index c4351c7..db884fa 100644 --- a/mm/percpu_up.c +++ b/mm/percpu_up.c @@ -14,13 +14,13 @@ void __percpu *__alloc_percpu(size_t size, size_t align) * percpu sections on SMP for which this path isn't used. */ WARN_ON_ONCE(align > SMP_CACHE_BYTES); - return kzalloc(size, GFP_KERNEL); + return (void __percpu __force *)kzalloc(size, GFP_KERNEL); } EXPORT_SYMBOL_GPL(__alloc_percpu); void free_percpu(void __percpu *p) { - kfree(p); + kfree(this_cpu_ptr(p)); } EXPORT_SYMBOL_GPL(free_percpu); -- cgit v0.10.2 From 50b6e71ae83714be509b80727dbf90fa8b1c0717 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 9 Aug 2010 10:29:28 -0400 Subject: Revert "hwrng: n2-drv - remove casts from void*" This reverts commit 8b9cfdca9c52f7d39c3ccfac1668e31c20c9f42e. This patch needs to wait for the HWRNG API to start using void * for priv first. Signed-off-by: Herbert Xu diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index 7a4f080..d8a4ca8 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c @@ -387,7 +387,7 @@ static int n2rng_init_control(struct n2rng *np) static int n2rng_data_read(struct hwrng *rng, u32 *data) { - struct n2rng *np = rng->priv; + struct n2rng *np = (struct n2rng *) rng->priv; unsigned long ra = __pa(&np->test_data); int len; -- cgit v0.10.2 From 92298e668372f2f6c8a79fb272f13d65161a4876 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 13 Aug 2010 10:22:17 +1000 Subject: PCI: provide stub pci_domain_nr function for !CONFIG_PCI configs Allows the new PCI domain aware DRM code to compile on m68k. Reported-by: Geert Uytterhoeven Signed-off-by: Dave Airlie Signed-off-by: Jesse Barnes diff --git a/include/linux/pci.h b/include/linux/pci.h index b1d1795..c8d95e3 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1214,6 +1214,9 @@ static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus, unsigned int devfn) { return NULL; } +static inline int pci_domain_nr(struct pci_bus *bus) +{ return 0; } + #define dev_is_pci(d) (false) #define dev_is_pf(d) (false) #define dev_num_vf(d) (0) -- cgit v0.10.2 From 8d9df9f0844ed87541453a3ef91bfc9f487053b7 Mon Sep 17 00:00:00 2001 From: Xiaotian Feng Date: Mon, 16 Aug 2010 09:54:28 +0200 Subject: workqueue: free rescuer on destroy_workqueue wq->rescuer is not freed when wq is destroyed, leads a memory leak then. This patch also remove a redundant line. Signed-off-by: Xiaotian Feng Signed-off-by: Tejun Heo Cc: Oleg Nesterov diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 2994a0e..1001b6e 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -2782,7 +2782,6 @@ struct workqueue_struct *__alloc_workqueue_key(const char *name, if (IS_ERR(rescuer->task)) goto err; - wq->rescuer = rescuer; rescuer->task->flags |= PF_THREAD_BOUND; wake_up_process(rescuer->task); } @@ -2848,6 +2847,7 @@ void destroy_workqueue(struct workqueue_struct *wq) if (wq->flags & WQ_RESCUER) { kthread_stop(wq->rescuer->task); free_mayday_mask(wq->mayday_mask); + kfree(wq->rescuer); } free_cwqs(wq); -- cgit v0.10.2 From 23b90cfd7bcf8ae1c0711df1cae7dfec3c01aec8 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 17 Aug 2010 09:15:24 -0700 Subject: x86/PCI: only define pci_domain_nr if PCI and PCI_DOMAINS are set Otherwise we'll duplicate definitions with the pci.h stubs. Reported-by: Randy Dunlap Acked-by: Randy Dunlap Signed-off-by: Jesse Barnes diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 404a880..d395540 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -27,6 +27,9 @@ extern struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops, int node); extern struct pci_bus *pci_scan_bus_with_sysdata(int busno); +#ifdef CONFIG_PCI + +#ifdef CONFIG_PCI_DOMAINS static inline int pci_domain_nr(struct pci_bus *bus) { struct pci_sysdata *sd = bus->sysdata; @@ -37,13 +40,12 @@ static inline int pci_proc_domain(struct pci_bus *bus) { return pci_domain_nr(bus); } - +#endif /* Can be used to override the logic in pci_scan_bus for skipping already-configured bus numbers - to be used for buggy BIOSes or architectures with incomplete PCI setup by the loader */ -#ifdef CONFIG_PCI extern unsigned int pcibios_assign_all_busses(void); extern int pci_legacy_init(void); # ifdef CONFIG_ACPI -- cgit v0.10.2 From 06bd6ebffae36d3b105677598c48e8bd0a10b205 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Sun, 22 Aug 2010 23:19:42 +0900 Subject: workqueue: annotate lock context change Some of internal functions called within gcwq->lock context releases and regrabs the lock but were missing proper annotations. Add it. Signed-off-by: Namhyung Kim Signed-off-by: Tejun Heo diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 1001b6e..7415f27a 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1485,6 +1485,8 @@ static void gcwq_mayday_timeout(unsigned long __gcwq) * otherwise. */ static bool maybe_create_worker(struct global_cwq *gcwq) +__releases(&gcwq->lock) +__acquires(&gcwq->lock) { if (!need_to_create_worker(gcwq)) return false; @@ -1722,6 +1724,8 @@ static void cwq_dec_nr_in_flight(struct cpu_workqueue_struct *cwq, int color) * spin_lock_irq(gcwq->lock) which is released and regrabbed. */ static void process_one_work(struct worker *worker, struct work_struct *work) +__releases(&gcwq->lock) +__acquires(&gcwq->lock) { struct cpu_workqueue_struct *cwq = get_work_cwq(work); struct global_cwq *gcwq = cwq->gcwq; @@ -3230,6 +3234,8 @@ static int __cpuinit trustee_thread(void *__gcwq) * multiple times. To be used by cpu_callback. */ static void __cpuinit wait_trustee_state(struct global_cwq *gcwq, int state) +__releases(&gcwq->lock) +__acquires(&gcwq->lock) { if (!(gcwq->trustee_state == state || gcwq->trustee_state == TRUSTEE_DONE)) { -- cgit v0.10.2 From 972fa1c5316d18c8297123e08e9b6930ca34f888 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Sun, 22 Aug 2010 23:19:43 +0900 Subject: workqueue: mark lock acquisition on worker_maybe_bind_and_lock() worker_maybe_bind_and_lock() actually grabs gcwq->lock but was missing proper annotation. Add it. So this patch will remove following sparse warnings: kernel/workqueue.c:1214:13: warning: context imbalance in 'worker_maybe_bind_and_lock' - wrong count at exit arch/x86/include/asm/irqflags.h:44:9: warning: context imbalance in 'worker_rebind_fn' - unexpected unlock kernel/workqueue.c:1991:17: warning: context imbalance in 'rescuer_thread' - unexpected unlock Signed-off-by: Namhyung Kim Signed-off-by: Tejun Heo diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 7415f27a..cc3456f 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1212,6 +1212,7 @@ static void worker_leave_idle(struct worker *worker) * bound), %false if offline. */ static bool worker_maybe_bind_and_lock(struct worker *worker) +__acquires(&gcwq->lock) { struct global_cwq *gcwq = worker->gcwq; struct task_struct *task = worker->task; -- cgit v0.10.2 From e41e704bc4f49057fc68b643108366e6e6781aa3 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 24 Aug 2010 14:22:47 +0200 Subject: workqueue: improve destroy_workqueue() debuggability Now that the worklist is global, having works pending after wq destruction can easily lead to oops and destroy_workqueue() have several BUG_ON()s to catch these cases. Unfortunately, BUG_ON() doesn't tell much about how the work became pending after the final flush_workqueue(). This patch adds WQ_DYING which is set before the final flush begins. If a work is requested to be queued on a dying workqueue, WARN_ON_ONCE() is triggered and the request is ignored. This clearly indicates which caller is trying to queue a work on a dying workqueue and keeps the system working in most cases. Locking rule comment is updated such that the 'I' rule includes modifying the field from destruction path. Signed-off-by: Tejun Heo diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 4f9d277b..c959666 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -241,6 +241,8 @@ enum { WQ_HIGHPRI = 1 << 4, /* high priority */ WQ_CPU_INTENSIVE = 1 << 5, /* cpu instensive workqueue */ + WQ_DYING = 1 << 6, /* internal: workqueue is dying */ + WQ_MAX_ACTIVE = 512, /* I like 512, better ideas? */ WQ_MAX_UNBOUND_PER_CPU = 4, /* 4 * #cpus for unbound wq */ WQ_DFL_ACTIVE = WQ_MAX_ACTIVE / 2, diff --git a/kernel/workqueue.c b/kernel/workqueue.c index cc3456f..362b50d 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -87,7 +87,8 @@ enum { /* * Structure fields follow one of the following exclusion rules. * - * I: Set during initialization and read-only afterwards. + * I: Modifiable by initialization/destruction paths and read-only for + * everyone else. * * P: Preemption protected. Disabling preemption is enough and should * only be modified and accessed from the local cpu. @@ -944,6 +945,9 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq, debug_work_activate(work); + if (WARN_ON_ONCE(wq->flags & WQ_DYING)) + return; + /* determine gcwq to use */ if (!(wq->flags & WQ_UNBOUND)) { struct global_cwq *last_gcwq; @@ -2828,6 +2832,7 @@ void destroy_workqueue(struct workqueue_struct *wq) { unsigned int cpu; + wq->flags |= WQ_DYING; flush_workqueue(wq); /* -- cgit v0.10.2 From f1a7bfaf6bb9cb195577e674c0ab2fd0a55d9014 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 21 Aug 2010 01:50:52 +0200 Subject: PCI: PCIe AER: Introduce pci_aer_available() Introduce a function allowing the caller to check whether to try to enable PCIe AER. Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 679c39d..7754a67 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -140,8 +140,10 @@ static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { } #ifdef CONFIG_PCIEAER void pci_no_aer(void); +bool pci_aer_available(void); #else static inline void pci_no_aer(void) { } +static inline bool pci_aer_available(void) { return false; } #endif static inline int pci_no_d1d2(struct pci_dev *dev) diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index 484cc55..f409948 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c @@ -72,6 +72,11 @@ void pci_no_aer(void) pcie_aer_disable = 1; /* has priority over 'forceload' */ } +bool pci_aer_available(void) +{ + return !pcie_aer_disable && pci_msi_enabled(); +} + static int set_device_error_reporting(struct pci_dev *dev, void *data) { bool enable = *((bool *)data); @@ -411,9 +416,7 @@ static void aer_error_resume(struct pci_dev *dev) */ static int __init aer_service_init(void) { - if (pcie_aer_disable) - return -ENXIO; - if (!pci_msi_enabled()) + if (!pci_aer_available()) return -ENXIO; return pcie_port_service_register(&aerdriver); } -- cgit v0.10.2 From 79dd9182db2072d63ccf160bb9a3463b1c952723 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 21 Aug 2010 01:51:44 +0200 Subject: PCI: PCIe: Introduce commad line switch for disabling port services Introduce kernel command line switch pcie_ports= allowing one to disable all of the native PCIe port services, so that PCIe ports are treated like PCI-to-PCI bridges. Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 873b680..b9008fc 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -2042,6 +2042,10 @@ and is between 256 and 4096 characters. It is defined in the file force Enable ASPM even on devices that claim not to support it. WARNING: Forcing ASPM on may cause system lockups. + pcie_ports= [PCIE] PCIe ports handling: + compat Treat PCIe ports as PCI-to-PCI bridges, disable the PCIe + ports driver. + pcie_pme= [PCIE,PM] Native PCIe PME signaling options: Format: {auto|force}[,nomsi] auto Use native PCIe PME signaling if the BIOS allows the diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index 813a5c3..966f6e9 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h @@ -20,6 +20,8 @@ #define get_descriptor_id(type, service) (((type - 4) << 4) | service) +extern bool pcie_ports_disabled; + extern struct bus_type pcie_port_bus_type; extern int pcie_port_device_register(struct pci_dev *dev); #ifdef CONFIG_PM diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index e73effb..2bf2fe5 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -494,6 +494,9 @@ static void pcie_port_shutdown_service(struct device *dev) {} */ int pcie_port_service_register(struct pcie_port_service_driver *new) { + if (pcie_ports_disabled) + return -ENODEV; + new->driver.name = (char *)new->name; new->driver.bus = &pcie_port_bus_type; new->driver.probe = pcie_port_probe_service; diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 3debed2..a04392d 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -29,6 +29,18 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); +/* If this switch is set, PCIe port native services should not be enabled. */ +bool pcie_ports_disabled; + +static int __init pcie_port_setup(char *str) +{ + if (!strncmp(str, "compat", 6)) + pcie_ports_disabled = true; + + return 1; +} +__setup("pcie_ports=", pcie_port_setup); + /* global data */ static int pcie_portdrv_restore_config(struct pci_dev *dev) @@ -301,6 +313,9 @@ static int __init pcie_portdrv_init(void) { int retval; + if (pcie_ports_disabled) + return -EACCES; + dmi_check_system(pcie_portdrv_dmi_table); retval = pcie_port_bus_register(); -- cgit v0.10.2 From b879dc4b3e81069e3f715b7569bb0f43eed76c76 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 21 Aug 2010 01:52:37 +0200 Subject: ACPI/PCI: Reorder checks in acpi_pci_osc_control_set() Make acpi_pci_osc_control_set() attempt to find the handle of the _OSC object under the given PCI root bridge object after verifying that its second argument is correct and that there is a struct acpi_pci_root object for the given root bridge handle, which is more logical than the old code. Signed-off-by: Rafael J. Wysocki Reviewed-by: Hidetoshi Seto Signed-off-by: Jesse Barnes diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 1f67057..e10dbaf 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -378,10 +378,6 @@ acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags) acpi_handle tmp; struct acpi_pci_root *root; - status = acpi_get_handle(handle, "_OSC", &tmp); - if (ACPI_FAILURE(status)) - return status; - control_req = (flags & OSC_PCI_CONTROL_MASKS); if (!control_req) return AE_TYPE; @@ -390,6 +386,10 @@ acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags) if (!root) return AE_NOT_EXIST; + status = acpi_get_handle(handle, "_OSC", &tmp); + if (ACPI_FAILURE(status)) + return status; + mutex_lock(&osc_lock); /* No need to evaluate _OSC if the control was already granted. */ if ((root->osc_control_set & control_req) == control_req) -- cgit v0.10.2 From ab8e8957a2ae21c0f036476c6db13e949be730ac Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 21 Aug 2010 01:53:27 +0200 Subject: ACPI/PCI: Make acpi_pci_query_osc() return control bits Make acpi_pci_query_osc() use an additional pointer argument to return the mask of control bits obtained from the BIOS to the caller. Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index e10dbaf..d2ae816 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -226,22 +226,35 @@ static acpi_status acpi_pci_run_osc(acpi_handle handle, return status; } -static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, u32 flags) +static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, + u32 support, + u32 *control) { acpi_status status; - u32 support_set, result, capbuf[3]; + u32 result, capbuf[3]; + + support &= OSC_PCI_SUPPORT_MASKS; + support |= root->osc_support_set; - /* do _OSC query for all possible controls */ - support_set = root->osc_support_set | (flags & OSC_PCI_SUPPORT_MASKS); capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; - capbuf[OSC_SUPPORT_TYPE] = support_set; - capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS; + capbuf[OSC_SUPPORT_TYPE] = support; + if (control) { + *control &= OSC_PCI_CONTROL_MASKS; + capbuf[OSC_CONTROL_TYPE] = *control | root->osc_control_set; + } else { + /* Run _OSC query for all possible controls. */ + capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS; + } status = acpi_pci_run_osc(root->device->handle, capbuf, &result); if (ACPI_SUCCESS(status)) { - root->osc_support_set = support_set; - root->osc_control_qry = result; - root->osc_queried = 1; + root->osc_support_set = support; + if (control) { + *control = result; + } else { + root->osc_control_qry = result; + root->osc_queried = 1; + } } return status; } @@ -255,7 +268,7 @@ static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags) if (ACPI_FAILURE(status)) return status; mutex_lock(&osc_lock); - status = acpi_pci_query_osc(root, flags); + status = acpi_pci_query_osc(root, flags, NULL); mutex_unlock(&osc_lock); return status; } @@ -397,7 +410,7 @@ acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags) /* Need to query controls first before requesting them */ if (!root->osc_queried) { - status = acpi_pci_query_osc(root, root->osc_support_set); + status = acpi_pci_query_osc(root, root->osc_support_set, NULL); if (ACPI_FAILURE(status)) goto out; } -- cgit v0.10.2 From 2b8fd9186d9275b07aef43e5bb4e98cd571f9a7d Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 23 Aug 2010 23:55:59 +0200 Subject: ACPI/PCI: Do not preserve _OSC control bits returned by a query There is the assumption in acpi_pci_osc_control_set() that it is always sufficient to compare the mask of _OSC control bits to be requested with the result of an _OSC query where all of the known control bits have been checked. However, in general, that need not be the case. For example, if an _OSC feature A depends on an _OSC feature B and control of A, B plus another _OSC feature C is requested simultaneously, the BIOS may return A, B, C, while it would only return C if A and C were requested without B. That may result in passing a wrong mask of _OSC control bits to an _OSC control request, in which case the BIOS may only grant control of a subset of the requested features. Moreover, acpi_pci_run_osc() will return error code if that happens and the caller of acpi_pci_osc_control_set() will not know that it's been granted control of some _OSC features. Consequently, the system will generally not work as expected. Apart from this acpi_pci_osc_control_set() always uses the mask of _OSC control bits returned by the very first invocation of acpi_pci_query_osc(), but that is done with the second argument equal to OSC_PCI_SEGMENT_GROUPS_SUPPORT which generally happens to affect the returned _OSC control bits. For these reasons, make acpi_pci_osc_control_set() always check if control of the requested _OSC features will be granted before making the final control request. As a result, the osc_control_qry and osc_queried members of struct acpi_pci_root are not necessary any more, so drop them and remove the remaining code referring to them. Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d2ae816..77cd196 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -249,12 +249,8 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, status = acpi_pci_run_osc(root->device->handle, capbuf, &result); if (ACPI_SUCCESS(status)) { root->osc_support_set = support; - if (control) { + if (control) *control = result; - } else { - root->osc_control_qry = result; - root->osc_queried = 1; - } } return status; } @@ -409,14 +405,12 @@ acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags) goto out; /* Need to query controls first before requesting them */ - if (!root->osc_queried) { - status = acpi_pci_query_osc(root, root->osc_support_set, NULL); - if (ACPI_FAILURE(status)) - goto out; - } - if ((root->osc_control_qry & control_req) != control_req) { - printk(KERN_DEBUG - "Firmware did not grant requested _OSC control\n"); + flags = control_req; + status = acpi_pci_query_osc(root, root->osc_support_set, &flags); + if (ACPI_FAILURE(status)) + goto out; + + if (flags != control_req) { status = AE_SUPPORT; goto out; } diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index baacd98..4de84ce 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -377,9 +377,6 @@ struct acpi_pci_root { u32 osc_support_set; /* _OSC state of support bits */ u32 osc_control_set; /* _OSC state of control bits */ - u32 osc_control_qry; /* the latest _OSC query result */ - - u32 osc_queried:1; /* has _OSC control been queried? */ }; /* helper */ -- cgit v0.10.2 From 75fb60f26befb59dbfa05cb122972642b7bdd219 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 23 Aug 2010 23:53:11 +0200 Subject: ACPI/PCI: Negotiate _OSC control bits before requesting them It is possible that the BIOS will not grant control of all _OSC features requested via acpi_pci_osc_control_set(), so it is recommended to negotiate the final set of _OSC features with the query flag set before calling _OSC to request control of these features. To implement it, rework acpi_pci_osc_control_set() so that the caller can specify the mask of _OSC control bits to negotiate and the mask of _OSC control bits that are absolutely necessary to it. Then, acpi_pci_osc_control_set() will run _OSC queries in a loop until the mask of _OSC control bits returned by the BIOS is equal to the mask passed to it. Also, before running the _OSC request acpi_pci_osc_control_set() will check if the caller's required control bits are present in the final mask. Using this mechanism we will be able to avoid situations in which the BIOS doesn't grant control of certain _OSC features, because they depend on some other _OSC features that have not been requested. Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 77cd196..c347131 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -374,21 +374,32 @@ out: EXPORT_SYMBOL_GPL(acpi_get_pci_dev); /** - * acpi_pci_osc_control_set - commit requested control to Firmware - * @handle: acpi_handle for the target ACPI object - * @flags: driver's requested control bits + * acpi_pci_osc_control_set - Request control of PCI root _OSC features. + * @handle: ACPI handle of a PCI root bridge (or PCIe Root Complex). + * @mask: Mask of _OSC bits to request control of, place to store control mask. + * @req: Mask of _OSC bits the control of is essential to the caller. * - * Attempt to take control from Firmware on requested control bits. + * Run _OSC query for @mask and if that is successful, compare the returned + * mask of control bits with @req. If all of the @req bits are set in the + * returned mask, run _OSC request for it. + * + * The variable at the @mask address may be modified regardless of whether or + * not the function returns success. On success it will contain the mask of + * _OSC bits the BIOS has granted control of, but its contents are meaningless + * on failure. **/ -acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags) +acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req) { + struct acpi_pci_root *root; acpi_status status; - u32 control_req, result, capbuf[3]; + u32 ctrl, capbuf[3]; acpi_handle tmp; - struct acpi_pci_root *root; - control_req = (flags & OSC_PCI_CONTROL_MASKS); - if (!control_req) + if (!mask) + return AE_BAD_PARAMETER; + + ctrl = *mask & OSC_PCI_CONTROL_MASKS; + if ((ctrl & req) != req) return AE_TYPE; root = acpi_pci_find_root(handle); @@ -400,27 +411,33 @@ acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags) return status; mutex_lock(&osc_lock); + + *mask = ctrl | root->osc_control_set; /* No need to evaluate _OSC if the control was already granted. */ - if ((root->osc_control_set & control_req) == control_req) + if ((root->osc_control_set & ctrl) == ctrl) goto out; - /* Need to query controls first before requesting them */ - flags = control_req; - status = acpi_pci_query_osc(root, root->osc_support_set, &flags); - if (ACPI_FAILURE(status)) - goto out; + /* Need to check the available controls bits before requesting them. */ + while (*mask) { + status = acpi_pci_query_osc(root, root->osc_support_set, mask); + if (ACPI_FAILURE(status)) + goto out; + if (ctrl == *mask) + break; + ctrl = *mask; + } - if (flags != control_req) { + if ((ctrl & req) != req) { status = AE_SUPPORT; goto out; } capbuf[OSC_QUERY_TYPE] = 0; capbuf[OSC_SUPPORT_TYPE] = root->osc_support_set; - capbuf[OSC_CONTROL_TYPE] = root->osc_control_set | control_req; - status = acpi_pci_run_osc(handle, capbuf, &result); + capbuf[OSC_CONTROL_TYPE] = ctrl; + status = acpi_pci_run_osc(handle, capbuf, mask); if (ACPI_SUCCESS(status)) - root->osc_control_set = result; + root->osc_control_set = *mask; out: mutex_unlock(&osc_lock); return status; @@ -551,8 +568,8 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) if (flags != base_flags) acpi_pci_osc_support(root, flags); - status = acpi_pci_osc_control_set(root->device->handle, - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); + flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL; + status = acpi_pci_osc_control_set(root->device->handle, &flags, flags); if (ACPI_FAILURE(status)) { printk(KERN_INFO "Unable to assume PCIe control: Disabling ASPM\n"); diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 45fcc1e..3d93d52 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -360,7 +360,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); dbg("Trying to get hotplug control for %s\n", (char *)string.pointer); - status = acpi_pci_osc_control_set(handle, flags); + status = acpi_pci_osc_control_set(handle, &flags, flags); if (ACPI_SUCCESS(status)) goto got_one; if (status == AE_SUPPORT) diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index f278d7b..3a276a0 100644 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c @@ -39,9 +39,9 @@ int aer_osc_setup(struct pcie_device *pciedev) handle = acpi_find_root_bridge_handle(pdev); if (handle) { - status = acpi_pci_osc_control_set(handle, - OSC_PCI_EXPRESS_AER_CONTROL | - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); + u32 flags = OSC_PCI_EXPRESS_AER_CONTROL | + OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL; + status = acpi_pci_osc_control_set(handle, &flags, flags); } if (ACPI_FAILURE(status)) { diff --git a/drivers/pci/pcie/pme/pcie_pme_acpi.c b/drivers/pci/pcie/pme/pcie_pme_acpi.c index 83ab228..be20222 100644 --- a/drivers/pci/pcie/pme/pcie_pme_acpi.c +++ b/drivers/pci/pcie/pme/pcie_pme_acpi.c @@ -28,6 +28,7 @@ int pcie_pme_acpi_setup(struct pcie_device *srv) acpi_status status = AE_NOT_FOUND; struct pci_dev *port = srv->port; acpi_handle handle; + u32 flags; int error = 0; if (acpi_pci_disabled) @@ -39,9 +40,10 @@ int pcie_pme_acpi_setup(struct pcie_device *srv) if (!handle) return -EINVAL; - status = acpi_pci_osc_control_set(handle, - OSC_PCI_EXPRESS_PME_CONTROL | - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); + flags = OSC_PCI_EXPRESS_PME_CONTROL | + OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL; + + status = acpi_pci_osc_control_set(handle, &flags, flags); if (ACPI_FAILURE(status)) { dev_info(&port->dev, "Failed to receive control of PCIe PME service: %s\n", diff --git a/include/linux/acpi.h b/include/linux/acpi.h index ccf94dc..c227757 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -304,8 +304,8 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); OSC_PCI_EXPRESS_PME_CONTROL | \ OSC_PCI_EXPRESS_AER_CONTROL | \ OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL) - -extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags); +extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, + u32 *mask, u32 req); extern void acpi_early_init(void); #else /* !CONFIG_ACPI */ -- cgit v0.10.2 From 28eb5f274a305bf3a13b2c80c4804d4515d05c64 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 21 Aug 2010 22:02:38 +0200 Subject: PCI: PCIe: Ask BIOS for control of all native services at once After commit 852972acff8f10f3a15679be2059bb94916cba5d (ACPI: Disable ASPM if the platform won't provide _OSC control for PCIe) control of the PCIe Capability Structure is unconditionally requested by acpi_pci_root_add(), which in principle may cause problems to happen in two ways. First, the BIOS may refuse to give control of the PCIe Capability Structure if it is not asked for any of the _OSC features depending on it at the same time. Second, the BIOS may assume that control of the _OSC features depending on the PCIe Capability Structure will be requested in the future and may behave incorrectly if that doesn't happen. For this reason, control of the PCIe Capability Structure should always be requested along with control of any other _OSC features that may depend on it (ie. PCIe native PME, PCIe native hot-plug, PCIe AER). Rework the PCIe port driver so that (1) it checks which native PCIe port services can be enabled, according to the BIOS, and (2) it requests control of all these services simultaneously. In particular, this causes pcie_portdrv_probe() to fail if the BIOS refuses to grant control of the PCIe Capability Structure, which means that no native PCIe port services can be enabled for the PCIe Root Complex the given port belongs to. If that happens, ASPM is disabled to avoid problems with mishandling it by the part of the PCIe hierarchy for which control of the PCIe Capability Structure has not been received. Make it possible to override this behavior using 'pcie_ports=native' (use the PCIe native services regardless of the BIOS response to the control request), or 'pcie_ports=compat' (do not use the PCIe native services at all). Accordingly, rework the existing PCIe port service drivers so that they don't request control of the services directly. Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index b9008fc..8f126e8 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -2043,18 +2043,17 @@ and is between 256 and 4096 characters. It is defined in the file WARNING: Forcing ASPM on may cause system lockups. pcie_ports= [PCIE] PCIe ports handling: + auto Ask the BIOS whether or not to use native PCIe services + associated with PCIe ports (PME, hot-plug, AER). Use + them only if that is allowed by the BIOS. + native Use native PCIe services associated with PCIe ports + unconditionally. compat Treat PCIe ports as PCI-to-PCI bridges, disable the PCIe ports driver. pcie_pme= [PCIE,PM] Native PCIe PME signaling options: - Format: {auto|force}[,nomsi] - auto Use native PCIe PME signaling if the BIOS allows the - kernel to control PCIe config registers of root ports. - force Use native PCIe PME signaling even if the BIOS refuses - to allow the kernel to control the relevant PCIe config - registers. nomsi Do not use MSI for native PCIe PME signaling (this makes - all PCIe root ports use INTx for everything). + all PCIe root ports use INTx for all services). pcmv= [HW,PCMCIA] BadgePAD 4 diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index c347131..3ba8d1f 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -568,14 +567,6 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) if (flags != base_flags) acpi_pci_osc_support(root, flags); - flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL; - status = acpi_pci_osc_control_set(root->device->handle, &flags, flags); - - if (ACPI_FAILURE(status)) { - printk(KERN_INFO "Unable to assume PCIe control: Disabling ASPM\n"); - pcie_no_aspm(); - } - pci_acpi_add_bus_pm_notifier(device, root->bus); if (device->wakeup.flags.run_wake) device_set_run_wake(root->bus->bridge, true); diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 3d93d52..3bc72d1 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -338,9 +338,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) acpi_handle chandle, handle; struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; - flags &= (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | - OSC_SHPC_NATIVE_HP_CONTROL | - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); + flags &= OSC_SHPC_NATIVE_HP_CONTROL; if (!flags) { err("Invalid flags %u specified!\n", flags); return -EINVAL; diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 4ed76b4..653de6f 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -176,19 +176,7 @@ static inline void pciehp_firmware_init(void) { pciehp_acpi_slot_detection_init(); } - -static inline int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) -{ - int retval; - u32 flags = (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); - retval = acpi_get_hp_hw_control_from_firmware(dev, flags); - if (retval) - return retval; - return pciehp_acpi_slot_detection_check(dev); -} #else #define pciehp_firmware_init() do {} while (0) -#define pciehp_get_hp_hw_control_from_firmware(dev) 0 #endif /* CONFIG_ACPI */ #endif /* _PCIEHP_H */ diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c index 1f4000a..2574700 100644 --- a/drivers/pci/hotplug/pciehp_acpi.c +++ b/drivers/pci/hotplug/pciehp_acpi.c @@ -85,9 +85,7 @@ static int __init dummy_probe(struct pcie_device *dev) acpi_handle handle; struct dummy_slot *slot, *tmp; struct pci_dev *pdev = dev->port; - /* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */ - if (pciehp_get_hp_hw_control_from_firmware(pdev)) - return -ENODEV; + pos = pci_pcie_cap(pdev); if (!pos) return -ENODEV; diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 3588ea6..aa5f3ff 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -59,7 +59,7 @@ module_param(pciehp_force, bool, 0644); MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not"); MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not"); MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds"); -MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing"); +MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if OSHP is missing"); #define PCIE_MODULE_NAME "pciehp" @@ -235,7 +235,7 @@ static int pciehp_probe(struct pcie_device *dev) dev_info(&dev->device, "Bypassing BIOS check for pciehp use on %s\n", pci_name(dev->port)); - else if (pciehp_get_hp_hw_control_from_firmware(dev->port)) + else if (pciehp_acpi_slot_detection_check(dev->port)) goto err_out_none; ctrl = pcie_init(dev); diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile index ea65454..4d2b187 100644 --- a/drivers/pci/pcie/Makefile +++ b/drivers/pci/pcie/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_PCIEASPM) += aspm.o pcieportdrv-y := portdrv_core.o portdrv_pci.o portdrv_bus.o +pcieportdrv-$(CONFIG_ACPI) += portdrv_acpi.o obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index 3a276a0..2bb9b89 100644 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c @@ -19,42 +19,6 @@ #include #include "aerdrv.h" -/** - * aer_osc_setup - run ACPI _OSC method - * @pciedev: pcie_device which AER is being enabled on - * - * @return: Zero on success. Nonzero otherwise. - * - * Invoked when PCIe bus loads AER service driver. To avoid conflict with - * BIOS AER support requires BIOS to yield AER control to OS native driver. - **/ -int aer_osc_setup(struct pcie_device *pciedev) -{ - acpi_status status = AE_NOT_FOUND; - struct pci_dev *pdev = pciedev->port; - acpi_handle handle = NULL; - - if (acpi_pci_disabled) - return -1; - - handle = acpi_find_root_bridge_handle(pdev); - if (handle) { - u32 flags = OSC_PCI_EXPRESS_AER_CONTROL | - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL; - status = acpi_pci_osc_control_set(handle, &flags, flags); - } - - if (ACPI_FAILURE(status)) { - dev_printk(KERN_DEBUG, &pciedev->device, "AER service couldn't " - "init device: %s\n", - (status == AE_SUPPORT || status == AE_NOT_FOUND) ? - "no _OSC support" : "_OSC failed"); - return -1; - } - - return 0; -} - #ifdef CONFIG_ACPI_APEI static inline int hest_match_pci(struct acpi_hest_aer_common *p, struct pci_dev *pci) diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index fc0b5a9..29e268f 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -772,22 +772,10 @@ void aer_isr(struct work_struct *work) */ int aer_init(struct pcie_device *dev) { - if (pcie_aer_get_firmware_first(dev->port)) { - dev_printk(KERN_DEBUG, &dev->device, - "PCIe errors handled by platform firmware.\n"); - goto out; - } - - if (aer_osc_setup(dev)) - goto out; - - return 0; -out: if (forceload) { dev_printk(KERN_DEBUG, &dev->device, "aerdrv forceload requested.\n"); pcie_aer_force_firmware_first(dev->port, 0); - return 0; } - return -ENXIO; + return 0; } diff --git a/drivers/pci/pcie/pme/Makefile b/drivers/pci/pcie/pme/Makefile index 8b92380..3c67bf4d 100644 --- a/drivers/pci/pcie/pme/Makefile +++ b/drivers/pci/pcie/pme/Makefile @@ -2,7 +2,4 @@ # Makefile for PCI-Express Root Port PME signaling driver # -obj-$(CONFIG_PCIE_PME) += pmedriver.o - -pmedriver-objs := pcie_pme.o -pmedriver-$(CONFIG_ACPI) += pcie_pme_acpi.o +obj-$(CONFIG_PCIE_PME) += pcie_pme.o diff --git a/drivers/pci/pcie/pme/pcie_pme.c b/drivers/pci/pcie/pme/pcie_pme.c index bbdea18..9d1361e 100644 --- a/drivers/pci/pcie/pme/pcie_pme.c +++ b/drivers/pci/pcie/pme/pcie_pme.c @@ -24,37 +24,12 @@ #include #include "../../pci.h" -#include "pcie_pme.h" +#include "../portdrv.h" #define PCI_EXP_RTSTA_PME 0x10000 /* PME status */ #define PCI_EXP_RTSTA_PENDING 0x20000 /* PME pending */ /* - * If set, this switch will prevent the PCIe root port PME service driver from - * being registered. Consequently, the interrupt-based PCIe PME signaling will - * not be used by any PCIe root ports in that case. - */ -static bool pcie_pme_disabled = true; - -/* - * The PCI Express Base Specification 2.0, Section 6.1.8, states the following: - * "In order to maintain compatibility with non-PCI Express-aware system - * software, system power management logic must be configured by firmware to use - * the legacy mechanism of signaling PME by default. PCI Express-aware system - * software must notify the firmware prior to enabling native, interrupt-based - * PME signaling." However, if the platform doesn't provide us with a suitable - * notification mechanism or the notification fails, it is not clear whether or - * not we are supposed to use the interrupt-based PCIe PME signaling. The - * switch below can be used to indicate the desired behaviour. When set, it - * will make the kernel use the interrupt-based PCIe PME signaling regardless of - * the platform notification status, although the kernel will attempt to notify - * the platform anyway. When unset, it will prevent the kernel from using the - * the interrupt-based PCIe PME signaling if the platform notification fails, - * which is the default. - */ -static bool pcie_pme_force_enable; - -/* * If this switch is set, MSI will not be used for PCIe PME signaling. This * causes the PCIe port driver to use INTx interrupts only, but it turns out * that using MSI for PCIe PME signaling doesn't play well with PCIe PME-based @@ -64,38 +39,13 @@ bool pcie_pme_msi_disabled; static int __init pcie_pme_setup(char *str) { - if (!strncmp(str, "auto", 4)) - pcie_pme_disabled = false; - else if (!strncmp(str, "force", 5)) - pcie_pme_force_enable = true; - - str = strchr(str, ','); - if (str) { - str++; - str += strspn(str, " \t"); - if (*str && !strcmp(str, "nomsi")) - pcie_pme_msi_disabled = true; - } + if (!strncmp(str, "nomsi", 5)) + pcie_pme_msi_disabled = true; return 1; } __setup("pcie_pme=", pcie_pme_setup); -/** - * pcie_pme_platform_setup - Ensure that the kernel controls the PCIe PME. - * @srv: PCIe PME root port service to use for carrying out the check. - * - * Notify the platform that the native PCIe PME is going to be used and return - * 'true' if the control of the PCIe PME registers has been acquired from the - * platform. - */ -static bool pcie_pme_platform_setup(struct pcie_device *srv) -{ - if (!pcie_pme_platform_notify(srv)) - return true; - return pcie_pme_force_enable; -} - struct pcie_pme_service_data { spinlock_t lock; struct pcie_device *srv; @@ -108,7 +58,7 @@ struct pcie_pme_service_data { * @dev: PCIe root port or event collector. * @enable: Enable or disable the interrupt. */ -static void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable) +void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable) { int rtctl_pos; u16 rtctl; @@ -417,9 +367,6 @@ static int pcie_pme_probe(struct pcie_device *srv) struct pcie_pme_service_data *data; int ret; - if (!pcie_pme_platform_setup(srv)) - return -EACCES; - data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -509,8 +456,7 @@ static struct pcie_port_service_driver pcie_pme_driver = { */ static int __init pcie_pme_service_init(void) { - return pcie_pme_disabled ? - -ENODEV : pcie_port_service_register(&pcie_pme_driver); + return pcie_port_service_register(&pcie_pme_driver); } module_init(pcie_pme_service_init); diff --git a/drivers/pci/pcie/pme/pcie_pme.h b/drivers/pci/pcie/pme/pcie_pme.h deleted file mode 100644 index b30d2b7..0000000 --- a/drivers/pci/pcie/pme/pcie_pme.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * drivers/pci/pcie/pme/pcie_pme.h - * - * PCI Express Root Port PME signaling support - * - * Copyright (C) 2009 Rafael J. Wysocki , Novell Inc. - */ - -#ifndef _PCIE_PME_H_ -#define _PCIE_PME_H_ - -struct pcie_device; - -#ifdef CONFIG_ACPI -extern int pcie_pme_acpi_setup(struct pcie_device *srv); - -static inline int pcie_pme_platform_notify(struct pcie_device *srv) -{ - return pcie_pme_acpi_setup(srv); -} -#else /* !CONFIG_ACPI */ -static inline int pcie_pme_platform_notify(struct pcie_device *srv) -{ - return 0; -} -#endif /* !CONFIG_ACPI */ - -#endif diff --git a/drivers/pci/pcie/pme/pcie_pme_acpi.c b/drivers/pci/pcie/pme/pcie_pme_acpi.c deleted file mode 100644 index be20222..0000000 --- a/drivers/pci/pcie/pme/pcie_pme_acpi.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * PCIe Native PME support, ACPI-related part - * - * Copyright (C) 2009 Rafael J. Wysocki , Novell Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License V2. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#include -#include -#include -#include -#include -#include - -/** - * pcie_pme_acpi_setup - Request the ACPI BIOS to release control over PCIe PME. - * @srv - PCIe PME service for a root port or event collector. - * - * Invoked when the PCIe bus type loads PCIe PME service driver. To avoid - * conflict with the BIOS PCIe support requires the BIOS to yield PCIe PME - * control to the kernel. - */ -int pcie_pme_acpi_setup(struct pcie_device *srv) -{ - acpi_status status = AE_NOT_FOUND; - struct pci_dev *port = srv->port; - acpi_handle handle; - u32 flags; - int error = 0; - - if (acpi_pci_disabled) - return -ENOSYS; - - dev_info(&port->dev, "Requesting control of PCIe PME from ACPI BIOS\n"); - - handle = acpi_find_root_bridge_handle(port); - if (!handle) - return -EINVAL; - - flags = OSC_PCI_EXPRESS_PME_CONTROL | - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL; - - status = acpi_pci_osc_control_set(handle, &flags, flags); - if (ACPI_FAILURE(status)) { - dev_info(&port->dev, - "Failed to receive control of PCIe PME service: %s\n", - (status == AE_SUPPORT || status == AE_NOT_FOUND) ? - "no _OSC support" : "ACPI _OSC failed"); - error = -ENODEV; - } - - return error; -} diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index 966f6e9..7b5aba0 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h @@ -21,6 +21,7 @@ #define get_descriptor_id(type, service) (((type - 4) << 4) | service) extern bool pcie_ports_disabled; +extern bool pcie_ports_auto; extern struct bus_type pcie_port_bus_type; extern int pcie_port_device_register(struct pci_dev *dev); @@ -32,6 +33,8 @@ extern void pcie_port_device_remove(struct pci_dev *dev); extern int __must_check pcie_port_bus_register(void); extern void pcie_port_bus_unregister(void); +struct pci_dev; + #ifdef CONFIG_PCIE_PME extern bool pcie_pme_msi_disabled; @@ -44,9 +47,26 @@ static inline bool pcie_pme_no_msi(void) { return pcie_pme_msi_disabled; } + +extern void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable); #else /* !CONFIG_PCIE_PME */ static inline void pcie_pme_disable_msi(void) {} static inline bool pcie_pme_no_msi(void) { return false; } +static inline void pcie_pme_interrupt_enable(struct pci_dev *dev, bool en) {} #endif /* !CONFIG_PCIE_PME */ +#ifdef CONFIG_ACPI +extern int pcie_port_acpi_setup(struct pci_dev *port, int *mask); + +static inline int pcie_port_platform_notify(struct pci_dev *port, int *mask) +{ + return pcie_port_acpi_setup(port, mask); +} +#else /* !CONFIG_ACPI */ +static inline int pcie_port_platform_notify(struct pci_dev *port, int *mask) +{ + return 0; +} +#endif /* !CONFIG_ACPI */ + #endif /* _PORTDRV_H_ */ diff --git a/drivers/pci/pcie/portdrv_acpi.c b/drivers/pci/pcie/portdrv_acpi.c new file mode 100644 index 0000000..b7c4cb1 --- /dev/null +++ b/drivers/pci/pcie/portdrv_acpi.c @@ -0,0 +1,77 @@ +/* + * PCIe Port Native Services Support, ACPI-Related Part + * + * Copyright (C) 2010 Rafael J. Wysocki , Novell Inc. + * + * This file is subject to the terms and conditions of the GNU General Public + * License V2. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include + +#include "aer/aerdrv.h" +#include "../pci.h" + +/** + * pcie_port_acpi_setup - Request the BIOS to release control of PCIe services. + * @port: PCIe Port service for a root port or event collector. + * @srv_mask: Bit mask of services that can be enabled for @port. + * + * Invoked when @port is identified as a PCIe port device. To avoid conflicts + * with the BIOS PCIe port native services support requires the BIOS to yield + * control of these services to the kernel. The mask of services that the BIOS + * allows to be enabled for @port is written to @srv_mask. + * + * NOTE: It turns out that we cannot do that for individual port services + * separately, because that would make some systems work incorrectly. + */ +int pcie_port_acpi_setup(struct pci_dev *port, int *srv_mask) +{ + acpi_status status; + acpi_handle handle; + u32 flags; + + if (acpi_pci_disabled) + return 0; + + handle = acpi_find_root_bridge_handle(port); + if (!handle) + return -EINVAL; + + flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL + | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL + | OSC_PCI_EXPRESS_PME_CONTROL; + + if (pci_aer_available()) { + if (pcie_aer_get_firmware_first(port)) + dev_dbg(&port->dev, "PCIe errors handled by BIOS.\n"); + else + flags |= OSC_PCI_EXPRESS_AER_CONTROL; + } + + status = acpi_pci_osc_control_set(handle, &flags, + OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); + if (ACPI_FAILURE(status)) { + dev_dbg(&port->dev, "ACPI _OSC request failed (code %d)\n", + status); + return -ENODEV; + } + + dev_info(&port->dev, "ACPI _OSC control granted for 0x%02x\n", flags); + + *srv_mask = PCIE_PORT_SERVICE_VC; + if (flags & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL) + *srv_mask |= PCIE_PORT_SERVICE_HP; + if (flags & OSC_PCI_EXPRESS_PME_CONTROL) + *srv_mask |= PCIE_PORT_SERVICE_PME; + if (flags & OSC_PCI_EXPRESS_AER_CONTROL) + *srv_mask |= PCIE_PORT_SERVICE_AER; + + return 0; +} diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index 2bf2fe5..d0245c8 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include "../pci.h" #include "portdrv.h" @@ -236,23 +238,40 @@ static int get_port_device_capability(struct pci_dev *dev) int services = 0, pos; u16 reg16; u32 reg32; + int cap_mask; + int err; + + err = pcie_port_platform_notify(dev, &cap_mask); + if (pcie_ports_auto) { + if (err) { + pcie_no_aspm(); + return 0; + } + } else { + cap_mask = PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP + | PCIE_PORT_SERVICE_VC; + if (pci_aer_available()) + cap_mask |= PCIE_PORT_SERVICE_AER; + } pos = pci_pcie_cap(dev); pci_read_config_word(dev, pos + PCI_EXP_FLAGS, ®16); /* Hot-Plug Capable */ - if (reg16 & PCI_EXP_FLAGS_SLOT) { + if ((cap_mask & PCIE_PORT_SERVICE_HP) && (reg16 & PCI_EXP_FLAGS_SLOT)) { pci_read_config_dword(dev, pos + PCI_EXP_SLTCAP, ®32); if (reg32 & PCI_EXP_SLTCAP_HPC) services |= PCIE_PORT_SERVICE_HP; } /* AER capable */ - if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) + if ((cap_mask & PCIE_PORT_SERVICE_AER) + && pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) services |= PCIE_PORT_SERVICE_AER; /* VC support */ if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC)) services |= PCIE_PORT_SERVICE_VC; /* Root ports are capable of generating PME too */ - if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) + if ((cap_mask & PCIE_PORT_SERVICE_PME) + && dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) services |= PCIE_PORT_SERVICE_PME; return services; diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index a04392d..8f1338d 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "portdrv.h" #include "aer/aerdrv.h" @@ -32,10 +33,23 @@ MODULE_LICENSE("GPL"); /* If this switch is set, PCIe port native services should not be enabled. */ bool pcie_ports_disabled; +/* + * If this switch is set, ACPI _OSC will be used to determine whether or not to + * enable PCIe port native services. + */ +bool pcie_ports_auto = true; + static int __init pcie_port_setup(char *str) { - if (!strncmp(str, "compat", 6)) + if (!strncmp(str, "compat", 6)) { pcie_ports_disabled = true; + } else if (!strncmp(str, "native", 6)) { + pcie_ports_disabled = false; + pcie_ports_auto = false; + } else if (!strncmp(str, "auto", 4)) { + pcie_ports_disabled = false; + pcie_ports_auto = true; + } return 1; } @@ -313,8 +327,10 @@ static int __init pcie_portdrv_init(void) { int retval; - if (pcie_ports_disabled) + if (pcie_ports_disabled) { + pcie_no_aspm(); return -EACCES; + } dmi_check_system(pcie_portdrv_dmi_table); -- cgit v0.10.2 From 2bd50dd800b52245294cfceb56be62020cdc7515 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 21 Aug 2010 01:57:39 +0200 Subject: PCI: PCIe: Disable PCIe port services during port initialization In principle PCIe port services may be enabled by the BIOS, so it's better to disable them during port initialization to avoid spurious events from being generated. Signed-off-by: Rafael J. Wysocki Reviewed-by: Hidetoshi Seto Signed-off-by: Jesse Barnes diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index d0245c8..a9c222d 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -259,20 +259,43 @@ static int get_port_device_capability(struct pci_dev *dev) /* Hot-Plug Capable */ if ((cap_mask & PCIE_PORT_SERVICE_HP) && (reg16 & PCI_EXP_FLAGS_SLOT)) { pci_read_config_dword(dev, pos + PCI_EXP_SLTCAP, ®32); - if (reg32 & PCI_EXP_SLTCAP_HPC) + if (reg32 & PCI_EXP_SLTCAP_HPC) { services |= PCIE_PORT_SERVICE_HP; + /* + * Disable hot-plug interrupts in case they have been + * enabled by the BIOS and the hot-plug service driver + * is not loaded. + */ + pos += PCI_EXP_SLTCTL; + pci_read_config_word(dev, pos, ®16); + reg16 &= ~(PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE); + pci_write_config_word(dev, pos, reg16); + } } /* AER capable */ if ((cap_mask & PCIE_PORT_SERVICE_AER) - && pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) + && pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) { services |= PCIE_PORT_SERVICE_AER; + /* + * Disable AER on this port in case it's been enabled by the + * BIOS (the AER service driver will enable it when necessary). + */ + pci_disable_pcie_error_reporting(dev); + } /* VC support */ if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC)) services |= PCIE_PORT_SERVICE_VC; /* Root ports are capable of generating PME too */ if ((cap_mask & PCIE_PORT_SERVICE_PME) - && dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) + && dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) { services |= PCIE_PORT_SERVICE_PME; + /* + * Disable PME interrupt on this port in case it's been enabled + * by the BIOS (the PME service driver will enable it when + * necessary). + */ + pcie_pme_interrupt_enable(dev, false); + } return services; } -- cgit v0.10.2 From 271fb719cc472af3b1e96d8c527bb0da7060a172 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 21 Aug 2010 01:58:22 +0200 Subject: PCI: PCIe: Move PCIe PME code to the pcie directory The PCIe PME code only consists of one file, so it doesn't need to occupy its own directory. Move it to drivers/pci/pcie/pme.c and remove the contents of drivers/pci/pcie/pme . Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile index 4d2b187..00c62df 100644 --- a/drivers/pci/pcie/Makefile +++ b/drivers/pci/pcie/Makefile @@ -13,4 +13,4 @@ obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o # Build PCI Express AER if needed obj-$(CONFIG_PCIEAER) += aer/ -obj-$(CONFIG_PCIE_PME) += pme/ +obj-$(CONFIG_PCIE_PME) += pme.o diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c new file mode 100644 index 0000000..2f3c904 --- /dev/null +++ b/drivers/pci/pcie/pme.c @@ -0,0 +1,462 @@ +/* + * PCIe Native PME support + * + * Copyright (C) 2007 - 2009 Intel Corp + * Copyright (C) 2007 - 2009 Shaohua Li + * Copyright (C) 2009 Rafael J. Wysocki , Novell Inc. + * + * This file is subject to the terms and conditions of the GNU General Public + * License V2. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../pci.h" +#include "portdrv.h" + +#define PCI_EXP_RTSTA_PME 0x10000 /* PME status */ +#define PCI_EXP_RTSTA_PENDING 0x20000 /* PME pending */ + +/* + * If this switch is set, MSI will not be used for PCIe PME signaling. This + * causes the PCIe port driver to use INTx interrupts only, but it turns out + * that using MSI for PCIe PME signaling doesn't play well with PCIe PME-based + * wake-up from system sleep states. + */ +bool pcie_pme_msi_disabled; + +static int __init pcie_pme_setup(char *str) +{ + if (!strncmp(str, "nomsi", 5)) + pcie_pme_msi_disabled = true; + + return 1; +} +__setup("pcie_pme=", pcie_pme_setup); + +struct pcie_pme_service_data { + spinlock_t lock; + struct pcie_device *srv; + struct work_struct work; + bool noirq; /* Don't enable the PME interrupt used by this service. */ +}; + +/** + * pcie_pme_interrupt_enable - Enable/disable PCIe PME interrupt generation. + * @dev: PCIe root port or event collector. + * @enable: Enable or disable the interrupt. + */ +void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable) +{ + int rtctl_pos; + u16 rtctl; + + rtctl_pos = pci_pcie_cap(dev) + PCI_EXP_RTCTL; + + pci_read_config_word(dev, rtctl_pos, &rtctl); + if (enable) + rtctl |= PCI_EXP_RTCTL_PMEIE; + else + rtctl &= ~PCI_EXP_RTCTL_PMEIE; + pci_write_config_word(dev, rtctl_pos, rtctl); +} + +/** + * pcie_pme_clear_status - Clear root port PME interrupt status. + * @dev: PCIe root port or event collector. + */ +static void pcie_pme_clear_status(struct pci_dev *dev) +{ + int rtsta_pos; + u32 rtsta; + + rtsta_pos = pci_pcie_cap(dev) + PCI_EXP_RTSTA; + + pci_read_config_dword(dev, rtsta_pos, &rtsta); + rtsta |= PCI_EXP_RTSTA_PME; + pci_write_config_dword(dev, rtsta_pos, rtsta); +} + +/** + * pcie_pme_walk_bus - Scan a PCI bus for devices asserting PME#. + * @bus: PCI bus to scan. + * + * Scan given PCI bus and all buses under it for devices asserting PME#. + */ +static bool pcie_pme_walk_bus(struct pci_bus *bus) +{ + struct pci_dev *dev; + bool ret = false; + + list_for_each_entry(dev, &bus->devices, bus_list) { + /* Skip PCIe devices in case we started from a root port. */ + if (!pci_is_pcie(dev) && pci_check_pme_status(dev)) { + pm_request_resume(&dev->dev); + pci_wakeup_event(dev); + ret = true; + } + + if (dev->subordinate && pcie_pme_walk_bus(dev->subordinate)) + ret = true; + } + + return ret; +} + +/** + * pcie_pme_from_pci_bridge - Check if PCIe-PCI bridge generated a PME. + * @bus: Secondary bus of the bridge. + * @devfn: Device/function number to check. + * + * PME from PCI devices under a PCIe-PCI bridge may be converted to an in-band + * PCIe PME message. In such that case the bridge should use the Requester ID + * of device/function number 0 on its secondary bus. + */ +static bool pcie_pme_from_pci_bridge(struct pci_bus *bus, u8 devfn) +{ + struct pci_dev *dev; + bool found = false; + + if (devfn) + return false; + + dev = pci_dev_get(bus->self); + if (!dev) + return false; + + if (pci_is_pcie(dev) && dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) { + down_read(&pci_bus_sem); + if (pcie_pme_walk_bus(bus)) + found = true; + up_read(&pci_bus_sem); + } + + pci_dev_put(dev); + return found; +} + +/** + * pcie_pme_handle_request - Find device that generated PME and handle it. + * @port: Root port or event collector that generated the PME interrupt. + * @req_id: PCIe Requester ID of the device that generated the PME. + */ +static void pcie_pme_handle_request(struct pci_dev *port, u16 req_id) +{ + u8 busnr = req_id >> 8, devfn = req_id & 0xff; + struct pci_bus *bus; + struct pci_dev *dev; + bool found = false; + + /* First, check if the PME is from the root port itself. */ + if (port->devfn == devfn && port->bus->number == busnr) { + if (pci_check_pme_status(port)) { + pm_request_resume(&port->dev); + found = true; + } else { + /* + * Apparently, the root port generated the PME on behalf + * of a non-PCIe device downstream. If this is done by + * a root port, the Requester ID field in its status + * register may contain either the root port's, or the + * source device's information (PCI Express Base + * Specification, Rev. 2.0, Section 6.1.9). + */ + down_read(&pci_bus_sem); + found = pcie_pme_walk_bus(port->subordinate); + up_read(&pci_bus_sem); + } + goto out; + } + + /* Second, find the bus the source device is on. */ + bus = pci_find_bus(pci_domain_nr(port->bus), busnr); + if (!bus) + goto out; + + /* Next, check if the PME is from a PCIe-PCI bridge. */ + found = pcie_pme_from_pci_bridge(bus, devfn); + if (found) + goto out; + + /* Finally, try to find the PME source on the bus. */ + down_read(&pci_bus_sem); + list_for_each_entry(dev, &bus->devices, bus_list) { + pci_dev_get(dev); + if (dev->devfn == devfn) { + found = true; + break; + } + pci_dev_put(dev); + } + up_read(&pci_bus_sem); + + if (found) { + /* The device is there, but we have to check its PME status. */ + found = pci_check_pme_status(dev); + if (found) { + pm_request_resume(&dev->dev); + pci_wakeup_event(dev); + } + pci_dev_put(dev); + } else if (devfn) { + /* + * The device is not there, but we can still try to recover by + * assuming that the PME was reported by a PCIe-PCI bridge that + * used devfn different from zero. + */ + dev_dbg(&port->dev, "PME interrupt generated for " + "non-existent device %02x:%02x.%d\n", + busnr, PCI_SLOT(devfn), PCI_FUNC(devfn)); + found = pcie_pme_from_pci_bridge(bus, 0); + } + + out: + if (!found) + dev_dbg(&port->dev, "Spurious native PME interrupt!\n"); +} + +/** + * pcie_pme_work_fn - Work handler for PCIe PME interrupt. + * @work: Work structure giving access to service data. + */ +static void pcie_pme_work_fn(struct work_struct *work) +{ + struct pcie_pme_service_data *data = + container_of(work, struct pcie_pme_service_data, work); + struct pci_dev *port = data->srv->port; + int rtsta_pos; + u32 rtsta; + + rtsta_pos = pci_pcie_cap(port) + PCI_EXP_RTSTA; + + spin_lock_irq(&data->lock); + + for (;;) { + if (data->noirq) + break; + + pci_read_config_dword(port, rtsta_pos, &rtsta); + if (rtsta & PCI_EXP_RTSTA_PME) { + /* + * Clear PME status of the port. If there are other + * pending PMEs, the status will be set again. + */ + pcie_pme_clear_status(port); + + spin_unlock_irq(&data->lock); + pcie_pme_handle_request(port, rtsta & 0xffff); + spin_lock_irq(&data->lock); + + continue; + } + + /* No need to loop if there are no more PMEs pending. */ + if (!(rtsta & PCI_EXP_RTSTA_PENDING)) + break; + + spin_unlock_irq(&data->lock); + cpu_relax(); + spin_lock_irq(&data->lock); + } + + if (!data->noirq) + pcie_pme_interrupt_enable(port, true); + + spin_unlock_irq(&data->lock); +} + +/** + * pcie_pme_irq - Interrupt handler for PCIe root port PME interrupt. + * @irq: Interrupt vector. + * @context: Interrupt context pointer. + */ +static irqreturn_t pcie_pme_irq(int irq, void *context) +{ + struct pci_dev *port; + struct pcie_pme_service_data *data; + int rtsta_pos; + u32 rtsta; + unsigned long flags; + + port = ((struct pcie_device *)context)->port; + data = get_service_data((struct pcie_device *)context); + + rtsta_pos = pci_pcie_cap(port) + PCI_EXP_RTSTA; + + spin_lock_irqsave(&data->lock, flags); + pci_read_config_dword(port, rtsta_pos, &rtsta); + + if (!(rtsta & PCI_EXP_RTSTA_PME)) { + spin_unlock_irqrestore(&data->lock, flags); + return IRQ_NONE; + } + + pcie_pme_interrupt_enable(port, false); + spin_unlock_irqrestore(&data->lock, flags); + + /* We don't use pm_wq, because it's freezable. */ + schedule_work(&data->work); + + return IRQ_HANDLED; +} + +/** + * pcie_pme_set_native - Set the PME interrupt flag for given device. + * @dev: PCI device to handle. + * @ign: Ignored. + */ +static int pcie_pme_set_native(struct pci_dev *dev, void *ign) +{ + dev_info(&dev->dev, "Signaling PME through PCIe PME interrupt\n"); + + device_set_run_wake(&dev->dev, true); + dev->pme_interrupt = true; + return 0; +} + +/** + * pcie_pme_mark_devices - Set the PME interrupt flag for devices below a port. + * @port: PCIe root port or event collector to handle. + * + * For each device below given root port, including the port itself (or for each + * root complex integrated endpoint if @port is a root complex event collector) + * set the flag indicating that it can signal run-time wake-up events via PCIe + * PME interrupts. + */ +static void pcie_pme_mark_devices(struct pci_dev *port) +{ + pcie_pme_set_native(port, NULL); + if (port->subordinate) { + pci_walk_bus(port->subordinate, pcie_pme_set_native, NULL); + } else { + struct pci_bus *bus = port->bus; + struct pci_dev *dev; + + /* Check if this is a root port event collector. */ + if (port->pcie_type != PCI_EXP_TYPE_RC_EC || !bus) + return; + + down_read(&pci_bus_sem); + list_for_each_entry(dev, &bus->devices, bus_list) + if (pci_is_pcie(dev) + && dev->pcie_type == PCI_EXP_TYPE_RC_END) + pcie_pme_set_native(dev, NULL); + up_read(&pci_bus_sem); + } +} + +/** + * pcie_pme_probe - Initialize PCIe PME service for given root port. + * @srv: PCIe service to initialize. + */ +static int pcie_pme_probe(struct pcie_device *srv) +{ + struct pci_dev *port; + struct pcie_pme_service_data *data; + int ret; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + spin_lock_init(&data->lock); + INIT_WORK(&data->work, pcie_pme_work_fn); + data->srv = srv; + set_service_data(srv, data); + + port = srv->port; + pcie_pme_interrupt_enable(port, false); + pcie_pme_clear_status(port); + + ret = request_irq(srv->irq, pcie_pme_irq, IRQF_SHARED, "PCIe PME", srv); + if (ret) { + kfree(data); + } else { + pcie_pme_mark_devices(port); + pcie_pme_interrupt_enable(port, true); + } + + return ret; +} + +/** + * pcie_pme_suspend - Suspend PCIe PME service device. + * @srv: PCIe service device to suspend. + */ +static int pcie_pme_suspend(struct pcie_device *srv) +{ + struct pcie_pme_service_data *data = get_service_data(srv); + struct pci_dev *port = srv->port; + + spin_lock_irq(&data->lock); + pcie_pme_interrupt_enable(port, false); + pcie_pme_clear_status(port); + data->noirq = true; + spin_unlock_irq(&data->lock); + + synchronize_irq(srv->irq); + + return 0; +} + +/** + * pcie_pme_resume - Resume PCIe PME service device. + * @srv - PCIe service device to resume. + */ +static int pcie_pme_resume(struct pcie_device *srv) +{ + struct pcie_pme_service_data *data = get_service_data(srv); + struct pci_dev *port = srv->port; + + spin_lock_irq(&data->lock); + data->noirq = false; + pcie_pme_clear_status(port); + pcie_pme_interrupt_enable(port, true); + spin_unlock_irq(&data->lock); + + return 0; +} + +/** + * pcie_pme_remove - Prepare PCIe PME service device for removal. + * @srv - PCIe service device to resume. + */ +static void pcie_pme_remove(struct pcie_device *srv) +{ + pcie_pme_suspend(srv); + free_irq(srv->irq, srv); + kfree(get_service_data(srv)); +} + +static struct pcie_port_service_driver pcie_pme_driver = { + .name = "pcie_pme", + .port_type = PCI_EXP_TYPE_ROOT_PORT, + .service = PCIE_PORT_SERVICE_PME, + + .probe = pcie_pme_probe, + .suspend = pcie_pme_suspend, + .resume = pcie_pme_resume, + .remove = pcie_pme_remove, +}; + +/** + * pcie_pme_service_init - Register the PCIe PME service driver. + */ +static int __init pcie_pme_service_init(void) +{ + return pcie_port_service_register(&pcie_pme_driver); +} + +module_init(pcie_pme_service_init); diff --git a/drivers/pci/pcie/pme/Makefile b/drivers/pci/pcie/pme/Makefile deleted file mode 100644 index 3c67bf4d..0000000 --- a/drivers/pci/pcie/pme/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for PCI-Express Root Port PME signaling driver -# - -obj-$(CONFIG_PCIE_PME) += pcie_pme.o diff --git a/drivers/pci/pcie/pme/pcie_pme.c b/drivers/pci/pcie/pme/pcie_pme.c deleted file mode 100644 index 9d1361e..0000000 --- a/drivers/pci/pcie/pme/pcie_pme.c +++ /dev/null @@ -1,462 +0,0 @@ -/* - * PCIe Native PME support - * - * Copyright (C) 2007 - 2009 Intel Corp - * Copyright (C) 2007 - 2009 Shaohua Li - * Copyright (C) 2009 Rafael J. Wysocki , Novell Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License V2. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../../pci.h" -#include "../portdrv.h" - -#define PCI_EXP_RTSTA_PME 0x10000 /* PME status */ -#define PCI_EXP_RTSTA_PENDING 0x20000 /* PME pending */ - -/* - * If this switch is set, MSI will not be used for PCIe PME signaling. This - * causes the PCIe port driver to use INTx interrupts only, but it turns out - * that using MSI for PCIe PME signaling doesn't play well with PCIe PME-based - * wake-up from system sleep states. - */ -bool pcie_pme_msi_disabled; - -static int __init pcie_pme_setup(char *str) -{ - if (!strncmp(str, "nomsi", 5)) - pcie_pme_msi_disabled = true; - - return 1; -} -__setup("pcie_pme=", pcie_pme_setup); - -struct pcie_pme_service_data { - spinlock_t lock; - struct pcie_device *srv; - struct work_struct work; - bool noirq; /* Don't enable the PME interrupt used by this service. */ -}; - -/** - * pcie_pme_interrupt_enable - Enable/disable PCIe PME interrupt generation. - * @dev: PCIe root port or event collector. - * @enable: Enable or disable the interrupt. - */ -void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable) -{ - int rtctl_pos; - u16 rtctl; - - rtctl_pos = pci_pcie_cap(dev) + PCI_EXP_RTCTL; - - pci_read_config_word(dev, rtctl_pos, &rtctl); - if (enable) - rtctl |= PCI_EXP_RTCTL_PMEIE; - else - rtctl &= ~PCI_EXP_RTCTL_PMEIE; - pci_write_config_word(dev, rtctl_pos, rtctl); -} - -/** - * pcie_pme_clear_status - Clear root port PME interrupt status. - * @dev: PCIe root port or event collector. - */ -static void pcie_pme_clear_status(struct pci_dev *dev) -{ - int rtsta_pos; - u32 rtsta; - - rtsta_pos = pci_pcie_cap(dev) + PCI_EXP_RTSTA; - - pci_read_config_dword(dev, rtsta_pos, &rtsta); - rtsta |= PCI_EXP_RTSTA_PME; - pci_write_config_dword(dev, rtsta_pos, rtsta); -} - -/** - * pcie_pme_walk_bus - Scan a PCI bus for devices asserting PME#. - * @bus: PCI bus to scan. - * - * Scan given PCI bus and all buses under it for devices asserting PME#. - */ -static bool pcie_pme_walk_bus(struct pci_bus *bus) -{ - struct pci_dev *dev; - bool ret = false; - - list_for_each_entry(dev, &bus->devices, bus_list) { - /* Skip PCIe devices in case we started from a root port. */ - if (!pci_is_pcie(dev) && pci_check_pme_status(dev)) { - pm_request_resume(&dev->dev); - pci_wakeup_event(dev); - ret = true; - } - - if (dev->subordinate && pcie_pme_walk_bus(dev->subordinate)) - ret = true; - } - - return ret; -} - -/** - * pcie_pme_from_pci_bridge - Check if PCIe-PCI bridge generated a PME. - * @bus: Secondary bus of the bridge. - * @devfn: Device/function number to check. - * - * PME from PCI devices under a PCIe-PCI bridge may be converted to an in-band - * PCIe PME message. In such that case the bridge should use the Requester ID - * of device/function number 0 on its secondary bus. - */ -static bool pcie_pme_from_pci_bridge(struct pci_bus *bus, u8 devfn) -{ - struct pci_dev *dev; - bool found = false; - - if (devfn) - return false; - - dev = pci_dev_get(bus->self); - if (!dev) - return false; - - if (pci_is_pcie(dev) && dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) { - down_read(&pci_bus_sem); - if (pcie_pme_walk_bus(bus)) - found = true; - up_read(&pci_bus_sem); - } - - pci_dev_put(dev); - return found; -} - -/** - * pcie_pme_handle_request - Find device that generated PME and handle it. - * @port: Root port or event collector that generated the PME interrupt. - * @req_id: PCIe Requester ID of the device that generated the PME. - */ -static void pcie_pme_handle_request(struct pci_dev *port, u16 req_id) -{ - u8 busnr = req_id >> 8, devfn = req_id & 0xff; - struct pci_bus *bus; - struct pci_dev *dev; - bool found = false; - - /* First, check if the PME is from the root port itself. */ - if (port->devfn == devfn && port->bus->number == busnr) { - if (pci_check_pme_status(port)) { - pm_request_resume(&port->dev); - found = true; - } else { - /* - * Apparently, the root port generated the PME on behalf - * of a non-PCIe device downstream. If this is done by - * a root port, the Requester ID field in its status - * register may contain either the root port's, or the - * source device's information (PCI Express Base - * Specification, Rev. 2.0, Section 6.1.9). - */ - down_read(&pci_bus_sem); - found = pcie_pme_walk_bus(port->subordinate); - up_read(&pci_bus_sem); - } - goto out; - } - - /* Second, find the bus the source device is on. */ - bus = pci_find_bus(pci_domain_nr(port->bus), busnr); - if (!bus) - goto out; - - /* Next, check if the PME is from a PCIe-PCI bridge. */ - found = pcie_pme_from_pci_bridge(bus, devfn); - if (found) - goto out; - - /* Finally, try to find the PME source on the bus. */ - down_read(&pci_bus_sem); - list_for_each_entry(dev, &bus->devices, bus_list) { - pci_dev_get(dev); - if (dev->devfn == devfn) { - found = true; - break; - } - pci_dev_put(dev); - } - up_read(&pci_bus_sem); - - if (found) { - /* The device is there, but we have to check its PME status. */ - found = pci_check_pme_status(dev); - if (found) { - pm_request_resume(&dev->dev); - pci_wakeup_event(dev); - } - pci_dev_put(dev); - } else if (devfn) { - /* - * The device is not there, but we can still try to recover by - * assuming that the PME was reported by a PCIe-PCI bridge that - * used devfn different from zero. - */ - dev_dbg(&port->dev, "PME interrupt generated for " - "non-existent device %02x:%02x.%d\n", - busnr, PCI_SLOT(devfn), PCI_FUNC(devfn)); - found = pcie_pme_from_pci_bridge(bus, 0); - } - - out: - if (!found) - dev_dbg(&port->dev, "Spurious native PME interrupt!\n"); -} - -/** - * pcie_pme_work_fn - Work handler for PCIe PME interrupt. - * @work: Work structure giving access to service data. - */ -static void pcie_pme_work_fn(struct work_struct *work) -{ - struct pcie_pme_service_data *data = - container_of(work, struct pcie_pme_service_data, work); - struct pci_dev *port = data->srv->port; - int rtsta_pos; - u32 rtsta; - - rtsta_pos = pci_pcie_cap(port) + PCI_EXP_RTSTA; - - spin_lock_irq(&data->lock); - - for (;;) { - if (data->noirq) - break; - - pci_read_config_dword(port, rtsta_pos, &rtsta); - if (rtsta & PCI_EXP_RTSTA_PME) { - /* - * Clear PME status of the port. If there are other - * pending PMEs, the status will be set again. - */ - pcie_pme_clear_status(port); - - spin_unlock_irq(&data->lock); - pcie_pme_handle_request(port, rtsta & 0xffff); - spin_lock_irq(&data->lock); - - continue; - } - - /* No need to loop if there are no more PMEs pending. */ - if (!(rtsta & PCI_EXP_RTSTA_PENDING)) - break; - - spin_unlock_irq(&data->lock); - cpu_relax(); - spin_lock_irq(&data->lock); - } - - if (!data->noirq) - pcie_pme_interrupt_enable(port, true); - - spin_unlock_irq(&data->lock); -} - -/** - * pcie_pme_irq - Interrupt handler for PCIe root port PME interrupt. - * @irq: Interrupt vector. - * @context: Interrupt context pointer. - */ -static irqreturn_t pcie_pme_irq(int irq, void *context) -{ - struct pci_dev *port; - struct pcie_pme_service_data *data; - int rtsta_pos; - u32 rtsta; - unsigned long flags; - - port = ((struct pcie_device *)context)->port; - data = get_service_data((struct pcie_device *)context); - - rtsta_pos = pci_pcie_cap(port) + PCI_EXP_RTSTA; - - spin_lock_irqsave(&data->lock, flags); - pci_read_config_dword(port, rtsta_pos, &rtsta); - - if (!(rtsta & PCI_EXP_RTSTA_PME)) { - spin_unlock_irqrestore(&data->lock, flags); - return IRQ_NONE; - } - - pcie_pme_interrupt_enable(port, false); - spin_unlock_irqrestore(&data->lock, flags); - - /* We don't use pm_wq, because it's freezable. */ - schedule_work(&data->work); - - return IRQ_HANDLED; -} - -/** - * pcie_pme_set_native - Set the PME interrupt flag for given device. - * @dev: PCI device to handle. - * @ign: Ignored. - */ -static int pcie_pme_set_native(struct pci_dev *dev, void *ign) -{ - dev_info(&dev->dev, "Signaling PME through PCIe PME interrupt\n"); - - device_set_run_wake(&dev->dev, true); - dev->pme_interrupt = true; - return 0; -} - -/** - * pcie_pme_mark_devices - Set the PME interrupt flag for devices below a port. - * @port: PCIe root port or event collector to handle. - * - * For each device below given root port, including the port itself (or for each - * root complex integrated endpoint if @port is a root complex event collector) - * set the flag indicating that it can signal run-time wake-up events via PCIe - * PME interrupts. - */ -static void pcie_pme_mark_devices(struct pci_dev *port) -{ - pcie_pme_set_native(port, NULL); - if (port->subordinate) { - pci_walk_bus(port->subordinate, pcie_pme_set_native, NULL); - } else { - struct pci_bus *bus = port->bus; - struct pci_dev *dev; - - /* Check if this is a root port event collector. */ - if (port->pcie_type != PCI_EXP_TYPE_RC_EC || !bus) - return; - - down_read(&pci_bus_sem); - list_for_each_entry(dev, &bus->devices, bus_list) - if (pci_is_pcie(dev) - && dev->pcie_type == PCI_EXP_TYPE_RC_END) - pcie_pme_set_native(dev, NULL); - up_read(&pci_bus_sem); - } -} - -/** - * pcie_pme_probe - Initialize PCIe PME service for given root port. - * @srv: PCIe service to initialize. - */ -static int pcie_pme_probe(struct pcie_device *srv) -{ - struct pci_dev *port; - struct pcie_pme_service_data *data; - int ret; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - spin_lock_init(&data->lock); - INIT_WORK(&data->work, pcie_pme_work_fn); - data->srv = srv; - set_service_data(srv, data); - - port = srv->port; - pcie_pme_interrupt_enable(port, false); - pcie_pme_clear_status(port); - - ret = request_irq(srv->irq, pcie_pme_irq, IRQF_SHARED, "PCIe PME", srv); - if (ret) { - kfree(data); - } else { - pcie_pme_mark_devices(port); - pcie_pme_interrupt_enable(port, true); - } - - return ret; -} - -/** - * pcie_pme_suspend - Suspend PCIe PME service device. - * @srv: PCIe service device to suspend. - */ -static int pcie_pme_suspend(struct pcie_device *srv) -{ - struct pcie_pme_service_data *data = get_service_data(srv); - struct pci_dev *port = srv->port; - - spin_lock_irq(&data->lock); - pcie_pme_interrupt_enable(port, false); - pcie_pme_clear_status(port); - data->noirq = true; - spin_unlock_irq(&data->lock); - - synchronize_irq(srv->irq); - - return 0; -} - -/** - * pcie_pme_resume - Resume PCIe PME service device. - * @srv - PCIe service device to resume. - */ -static int pcie_pme_resume(struct pcie_device *srv) -{ - struct pcie_pme_service_data *data = get_service_data(srv); - struct pci_dev *port = srv->port; - - spin_lock_irq(&data->lock); - data->noirq = false; - pcie_pme_clear_status(port); - pcie_pme_interrupt_enable(port, true); - spin_unlock_irq(&data->lock); - - return 0; -} - -/** - * pcie_pme_remove - Prepare PCIe PME service device for removal. - * @srv - PCIe service device to resume. - */ -static void pcie_pme_remove(struct pcie_device *srv) -{ - pcie_pme_suspend(srv); - free_irq(srv->irq, srv); - kfree(get_service_data(srv)); -} - -static struct pcie_port_service_driver pcie_pme_driver = { - .name = "pcie_pme", - .port_type = PCI_EXP_TYPE_ROOT_PORT, - .service = PCIE_PORT_SERVICE_PME, - - .probe = pcie_pme_probe, - .suspend = pcie_pme_suspend, - .resume = pcie_pme_resume, - .remove = pcie_pme_remove, -}; - -/** - * pcie_pme_service_init - Register the PCIe PME service driver. - */ -static int __init pcie_pme_service_init(void) -{ - return pcie_port_service_register(&pcie_pme_driver); -} - -module_init(pcie_pme_service_init); -- cgit v0.10.2 From a9d2a6df11f5b9dc19ad4147374e8b67c4438158 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Sat, 21 Aug 2010 01:59:10 +0200 Subject: PCI: PCIe: Remove the port driver module exit routine The PCIe port driver's module exit routine is never used, so drop it. Signed-off-by: Kenji Kaneshige Signed-off-by: Rafael J. Wysocki Reviewed-by: Hidetoshi Seto Signed-off-by: Jesse Barnes diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 8f1338d..f9033e1 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -346,11 +346,4 @@ static int __init pcie_portdrv_init(void) return retval; } -static void __exit pcie_portdrv_exit(void) -{ - pci_unregister_driver(&pcie_portdriver); - pcie_port_bus_unregister(); -} - module_init(pcie_portdrv_init); -module_exit(pcie_portdrv_exit); -- cgit v0.10.2 From 8a2e8e5dec7e29c56a46ba176c664ab6a3d04118 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 25 Aug 2010 10:33:56 +0200 Subject: workqueue: fix cwq->nr_active underflow cwq->nr_active is used to keep track of how many work items are active for the cpu workqueue, where 'active' is defined as either pending on global worklist or executing. This is used to implement the max_active limit and workqueue freezing. If a work item is queued after nr_active has already reached max_active, the work item doesn't increment nr_active and is put on the delayed queue and gets activated later as previous active work items retire. try_to_grab_pending() which is used in the cancellation path unconditionally decremented nr_active whether the work item being cancelled is currently active or delayed, so cancelling a delayed work item makes nr_active underflow. This breaks max_active enforcement and triggers BUG_ON() in destroy_workqueue() later on. This patch fixes this bug by adding a flag WORK_STRUCT_DELAYED, which is set while a work item in on the delayed list and making try_to_grab_pending() decrement nr_active iff the work item is currently active. The addition of the flag enlarges cwq alignment to 256 bytes which is getting a bit too large. It's scheduled to be reduced back to 128 bytes by merging WORK_STRUCT_PENDING and WORK_STRUCT_CWQ in the next devel cycle. Signed-off-by: Tejun Heo Reported-by: Johannes Berg diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index c959666..f11100f 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -25,18 +25,20 @@ typedef void (*work_func_t)(struct work_struct *work); enum { WORK_STRUCT_PENDING_BIT = 0, /* work item is pending execution */ - WORK_STRUCT_CWQ_BIT = 1, /* data points to cwq */ - WORK_STRUCT_LINKED_BIT = 2, /* next work is linked to this one */ + WORK_STRUCT_DELAYED_BIT = 1, /* work item is delayed */ + WORK_STRUCT_CWQ_BIT = 2, /* data points to cwq */ + WORK_STRUCT_LINKED_BIT = 3, /* next work is linked to this one */ #ifdef CONFIG_DEBUG_OBJECTS_WORK - WORK_STRUCT_STATIC_BIT = 3, /* static initializer (debugobjects) */ - WORK_STRUCT_COLOR_SHIFT = 4, /* color for workqueue flushing */ + WORK_STRUCT_STATIC_BIT = 4, /* static initializer (debugobjects) */ + WORK_STRUCT_COLOR_SHIFT = 5, /* color for workqueue flushing */ #else - WORK_STRUCT_COLOR_SHIFT = 3, /* color for workqueue flushing */ + WORK_STRUCT_COLOR_SHIFT = 4, /* color for workqueue flushing */ #endif WORK_STRUCT_COLOR_BITS = 4, WORK_STRUCT_PENDING = 1 << WORK_STRUCT_PENDING_BIT, + WORK_STRUCT_DELAYED = 1 << WORK_STRUCT_DELAYED_BIT, WORK_STRUCT_CWQ = 1 << WORK_STRUCT_CWQ_BIT, WORK_STRUCT_LINKED = 1 << WORK_STRUCT_LINKED_BIT, #ifdef CONFIG_DEBUG_OBJECTS_WORK @@ -59,8 +61,8 @@ enum { /* * Reserve 7 bits off of cwq pointer w/ debugobjects turned - * off. This makes cwqs aligned to 128 bytes which isn't too - * excessive while allowing 15 workqueue flush colors. + * off. This makes cwqs aligned to 256 bytes and allows 15 + * workqueue flush colors. */ WORK_STRUCT_FLAG_BITS = WORK_STRUCT_COLOR_SHIFT + WORK_STRUCT_COLOR_BITS, diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 362b50d..a2dccfc 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -941,6 +941,7 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq, struct global_cwq *gcwq; struct cpu_workqueue_struct *cwq; struct list_head *worklist; + unsigned int work_flags; unsigned long flags; debug_work_activate(work); @@ -990,14 +991,17 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq, BUG_ON(!list_empty(&work->entry)); cwq->nr_in_flight[cwq->work_color]++; + work_flags = work_color_to_flags(cwq->work_color); if (likely(cwq->nr_active < cwq->max_active)) { cwq->nr_active++; worklist = gcwq_determine_ins_pos(gcwq, cwq); - } else + } else { + work_flags |= WORK_STRUCT_DELAYED; worklist = &cwq->delayed_works; + } - insert_work(cwq, work, worklist, work_color_to_flags(cwq->work_color)); + insert_work(cwq, work, worklist, work_flags); spin_unlock_irqrestore(&gcwq->lock, flags); } @@ -1666,6 +1670,7 @@ static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq) struct list_head *pos = gcwq_determine_ins_pos(cwq->gcwq, cwq); move_linked_works(work, pos, NULL); + __clear_bit(WORK_STRUCT_DELAYED_BIT, work_data_bits(work)); cwq->nr_active++; } @@ -1673,6 +1678,7 @@ static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq) * cwq_dec_nr_in_flight - decrement cwq's nr_in_flight * @cwq: cwq of interest * @color: color of work which left the queue + * @delayed: for a delayed work * * A work either has completed or is removed from pending queue, * decrement nr_in_flight of its cwq and handle workqueue flushing. @@ -1680,19 +1686,22 @@ static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq) * CONTEXT: * spin_lock_irq(gcwq->lock). */ -static void cwq_dec_nr_in_flight(struct cpu_workqueue_struct *cwq, int color) +static void cwq_dec_nr_in_flight(struct cpu_workqueue_struct *cwq, int color, + bool delayed) { /* ignore uncolored works */ if (color == WORK_NO_COLOR) return; cwq->nr_in_flight[color]--; - cwq->nr_active--; - if (!list_empty(&cwq->delayed_works)) { - /* one down, submit a delayed one */ - if (cwq->nr_active < cwq->max_active) - cwq_activate_first_delayed(cwq); + if (!delayed) { + cwq->nr_active--; + if (!list_empty(&cwq->delayed_works)) { + /* one down, submit a delayed one */ + if (cwq->nr_active < cwq->max_active) + cwq_activate_first_delayed(cwq); + } } /* is flush in progress and are we at the flushing tip? */ @@ -1823,7 +1832,7 @@ __acquires(&gcwq->lock) hlist_del_init(&worker->hentry); worker->current_work = NULL; worker->current_cwq = NULL; - cwq_dec_nr_in_flight(cwq, work_color); + cwq_dec_nr_in_flight(cwq, work_color, false); } /** @@ -2388,7 +2397,8 @@ static int try_to_grab_pending(struct work_struct *work) debug_work_deactivate(work); list_del_init(&work->entry); cwq_dec_nr_in_flight(get_work_cwq(work), - get_work_color(work)); + get_work_color(work), + *work_data_bits(work) & WORK_STRUCT_DELAYED); ret = 1; } } -- cgit v0.10.2 From 6e63e80d88521a176989ed14b420f42dc418e46a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 25 Aug 2010 21:33:29 +0200 Subject: PCI hotplug: Fix build with CONFIG_ACPI unset One of the recent changes caused complilation of drivers/pci/hotplug/pciehp_core.c to fail. Fix this issue. Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 653de6f..73d5139 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -178,5 +178,9 @@ static inline void pciehp_firmware_init(void) } #else #define pciehp_firmware_init() do {} while (0) +static inline int pciehp_acpi_slot_detection_check(struct pci_dev *dev) +{ + return 0; +} #endif /* CONFIG_ACPI */ #endif /* _PCIEHP_H */ -- cgit v0.10.2 From a002d148426f40bc2b7dc066982eb177cdebeaaa Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Sun, 8 Aug 2010 14:39:07 +0200 Subject: percpu: fix a memory leak in pcpu_extend_area_map() The original code did not free the old map. This patch fixes it. tj: use @old as memcpy source instead of @chunk->map, and indentation and description update Signed-off-by: Huang Shijie Signed-off-by: Tejun Heo Cc: stable@kernel.org diff --git a/mm/percpu.c b/mm/percpu.c index e61dc2c..a1830d8 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -393,7 +393,9 @@ static int pcpu_extend_area_map(struct pcpu_chunk *chunk, int new_alloc) goto out_unlock; old_size = chunk->map_alloc * sizeof(chunk->map[0]); - memcpy(new, chunk->map, old_size); + old = chunk->map; + + memcpy(new, old, old_size); chunk->map_alloc = new_alloc; chunk->map = new; -- cgit v0.10.2 From 54157c44471f5e266508ac08d270f2bc5857e8bb Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 11 Aug 2010 11:19:19 +0900 Subject: percpu: fix a mismatch between code and comment When pcpu_build_alloc_info() searches best_upa value, it ignores current value if the number of waste units exceeds 1/3 of the number of total cpus. But the comment on the code says that it will ignore if wastage is over 25%. Modify the comment. Signed-off-by: Namhyung Kim Signed-off-by: Tejun Heo diff --git a/mm/percpu.c b/mm/percpu.c index a1830d8..58c572b 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -1164,7 +1164,7 @@ static struct pcpu_alloc_info * __init pcpu_build_alloc_info( } /* - * Don't accept if wastage is over 25%. The + * Don't accept if wastage is over 1/3. The * greater-than comparison ensures upa==1 always * passes the following check. */ -- cgit v0.10.2 From 7c38875a0d0a9b90eee66be79e36995c86acc70c Mon Sep 17 00:00:00 2001 From: Jason Baron Date: Thu, 26 Aug 2010 10:35:43 -0400 Subject: workqueue: Add a workqueue chapter to the tracepoint docbook Add a workqueue chapter to the traceopint docbook. Current book is at: http://www.kernel.org/doc/htmldocs/tracepoint/ Signed-off-by: Jason Baron Signed-off-by: Tejun Heo diff --git a/Documentation/DocBook/tracepoint.tmpl b/Documentation/DocBook/tracepoint.tmpl index e8473ea..b57a9ed 100644 --- a/Documentation/DocBook/tracepoint.tmpl +++ b/Documentation/DocBook/tracepoint.tmpl @@ -104,4 +104,9 @@ Block IO !Iinclude/trace/events/block.h + + + Workqueue +!Iinclude/trace/events/workqueue.h + -- cgit v0.10.2 From 557de5eb29caeab56c2f97b49eec02e32a2cbe32 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 22 Aug 2010 14:22:40 +0300 Subject: libertas: if_sdio: fix buffer alignment in struct if_sdio_card The commit 886275ce41a9751117367fb387ed171049eb6148 (param: lock if_sdio's lbs_helper_name and lbs_fw_name against sysfs changes) introduced new fields into the if_sdio_card structure. It caused missalignment of the if_sdio_card.buffer field and failure at driver load time: ~# modprobe libertas_sdio [ 62.315124] libertas_sdio: Libertas SDIO driver [ 62.319976] libertas_sdio: Copyright Pierre Ossman [ 63.020629] DMA misaligned error with device 48 [ 63.025207] mmci-omap-hs mmci-omap-hs.1: unexpected dma status 800 [ 66.005035] libertas: command 0x0003 timed out [ 66.009826] libertas: Timeout submitting command 0x0003 [ 66.016296] libertas: PREP_CMD: command 0x0003 failed: -110 Adding explicit alignment attribute for the if_sdio_card.buffer field fixes this problem. Signed-off-by: Mike Rapoport Acked-by: Marek Vasut Acked-by: Dan Williams Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 6e71346..382f237 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -126,7 +126,7 @@ struct if_sdio_card { const char *helper; const char *firmware; - u8 buffer[65536]; + u8 buffer[65536] __attribute__((aligned(4))); spinlock_t lock; struct if_sdio_packet *packets; -- cgit v0.10.2 From 7619b1b2e2b96842459f499fd48ec32e3d223d02 Mon Sep 17 00:00:00 2001 From: Ken Kawasaki Date: Sat, 28 Aug 2010 12:45:01 +0000 Subject: pcnet_cs: add new_id pcnet_cs: add new_id: "KENTRONICS KEP-230" 10Base-T PCMCIA card. Signed-off-by: Ken Kawasaki Signed-off-by: David S. Miller diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index bfdef72..7fd8c55 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -1644,6 +1644,7 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCETTX", 0x547e66dc, 0x6fc5459b), PCMCIA_DEVICE_PROD_ID12("iPort", "10/100 Ethernet Card", 0x56c538d2, 0x11b0ffc0), PCMCIA_DEVICE_PROD_ID12("KANSAI ELECTRIC CO.,LTD", "KLA-PCM/T", 0xb18dc3b4, 0xcc51a956), + PCMCIA_DEVICE_PROD_ID12("KENTRONICS", "KEP-230", 0xaf8144c9, 0x868f6616), PCMCIA_DEVICE_PROD_ID12("KCI", "PE520 PCMCIA Ethernet Adapter", 0xa89b87d3, 0x1eb88e64), PCMCIA_DEVICE_PROD_ID12("KINGMAX", "EN10T2T", 0x7bcb459a, 0xa5c81fa5), PCMCIA_DEVICE_PROD_ID12("Kingston", "KNE-PC2", 0x1128e633, 0xce2a89b3), -- cgit v0.10.2 From 8807286e569c4f12fa2bc980187f3e2abc606d11 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 10 Aug 2010 12:33:20 -0400 Subject: drm/radeon/kms: use tracked values for sclk and mclk Rather than calling get_memory_clock and get_engine_clock, used the tracked values from the pm code. Calling the tables adds additional latency in the modesetting and pm paths. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c index 14448a7..690d8907 100644 --- a/drivers/gpu/drm/radeon/radeon_clocks.c +++ b/drivers/gpu/drm/radeon/radeon_clocks.c @@ -327,6 +327,14 @@ void radeon_get_clock_info(struct drm_device *dev) mpll->max_feedback_div = 0xff; mpll->best_vco = 0; + if (!rdev->clock.default_sclk) + rdev->clock.default_sclk = radeon_get_engine_clock(rdev); + if ((!rdev->clock.default_mclk) && rdev->asic->get_memory_clock) + rdev->clock.default_mclk = radeon_get_memory_clock(rdev); + + rdev->pm.current_sclk = rdev->clock.default_sclk; + rdev->pm.current_mclk = rdev->clock.default_mclk; + } /* 10 khz */ diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 69b3c22..256d204 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -293,30 +293,20 @@ bool radeon_card_posted(struct radeon_device *rdev) void radeon_update_bandwidth_info(struct radeon_device *rdev) { fixed20_12 a; - u32 sclk, mclk; + u32 sclk = rdev->pm.current_sclk; + u32 mclk = rdev->pm.current_mclk; - if (rdev->flags & RADEON_IS_IGP) { - sclk = radeon_get_engine_clock(rdev); - mclk = rdev->clock.default_mclk; - - a.full = dfixed_const(100); - rdev->pm.sclk.full = dfixed_const(sclk); - rdev->pm.sclk.full = dfixed_div(rdev->pm.sclk, a); - rdev->pm.mclk.full = dfixed_const(mclk); - rdev->pm.mclk.full = dfixed_div(rdev->pm.mclk, a); + /* sclk/mclk in Mhz */ + a.full = dfixed_const(100); + rdev->pm.sclk.full = dfixed_const(sclk); + rdev->pm.sclk.full = dfixed_div(rdev->pm.sclk, a); + rdev->pm.mclk.full = dfixed_const(mclk); + rdev->pm.mclk.full = dfixed_div(rdev->pm.mclk, a); + if (rdev->flags & RADEON_IS_IGP) { a.full = dfixed_const(16); /* core_bandwidth = sclk(Mhz) * 16 */ rdev->pm.core_bandwidth.full = dfixed_div(rdev->pm.sclk, a); - } else { - sclk = radeon_get_engine_clock(rdev); - mclk = radeon_get_memory_clock(rdev); - - a.full = dfixed_const(100); - rdev->pm.sclk.full = dfixed_const(sclk); - rdev->pm.sclk.full = dfixed_div(rdev->pm.sclk, a); - rdev->pm.mclk.full = dfixed_const(mclk); - rdev->pm.mclk.full = dfixed_div(rdev->pm.mclk, a); } } diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index 0416804..6a13ee3 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -213,7 +213,7 @@ static void post_xfer(struct i2c_adapter *i2c_adap) static u32 radeon_get_i2c_prescale(struct radeon_device *rdev) { - u32 sclk = radeon_get_engine_clock(rdev); + u32 sclk = rdev->pm.current_sclk; u32 prescale = 0; u32 nm; u8 n, m, loop; -- cgit v0.10.2 From 87cbf8f2c5d1b1fc4642c3dc0bb6efc587479603 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 27 Aug 2010 13:59:54 -0400 Subject: drm/radeon/kms: fix a regression on r7xx AGP due to the HDP flush fix commit: 812d046915f48236657f02c06d7dc47140e9ceda drm/radeon/kms/r7xx: add workaround for hw issue with HDP flush breaks on AGP boards since there is no VRAM gart table. This patch fixes the issue by creating a VRAM scratch page so that can be used on both AGP and PCIE. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=29834 Signed-off-by: Alex Deucher Cc: stable@kernel.org Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index d0ebae9..aee8376 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3541,7 +3541,7 @@ void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo) * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL */ if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) { - void __iomem *ptr = (void *)rdev->gart.table.vram.ptr; + void __iomem *ptr = (void *)rdev->vram_scratch.ptr; u32 tmp; WREG32(HDP_DEBUG1, 0); diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 3dfcfa3..e90d9e3 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1013,6 +1013,11 @@ int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data, int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); +/* VRAM scratch page for HDP bug */ +struct r700_vram_scratch { + struct radeon_bo *robj; + volatile uint32_t *ptr; +}; /* * Core structure, functions and helpers. @@ -1079,6 +1084,7 @@ struct radeon_device { const struct firmware *pfp_fw; /* r6/700 PFP firmware */ const struct firmware *rlc_fw; /* r6/700 RLC firmware */ struct r600_blit r600_blit; + struct r700_vram_scratch vram_scratch; int msi_enabled; /* msi enabled */ struct r600_ih ih; /* r6/700 interrupt ring */ struct workqueue_struct *wq; diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index f1c79681..a84e386 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -905,6 +905,54 @@ static void rv770_gpu_init(struct radeon_device *rdev) } +static int rv770_vram_scratch_init(struct radeon_device *rdev) +{ + int r; + u64 gpu_addr; + + if (rdev->vram_scratch.robj == NULL) { + r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, + true, RADEON_GEM_DOMAIN_VRAM, + &rdev->vram_scratch.robj); + if (r) { + return r; + } + } + + r = radeon_bo_reserve(rdev->vram_scratch.robj, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_pin(rdev->vram_scratch.robj, + RADEON_GEM_DOMAIN_VRAM, &gpu_addr); + if (r) { + radeon_bo_unreserve(rdev->vram_scratch.robj); + return r; + } + r = radeon_bo_kmap(rdev->vram_scratch.robj, + (void **)&rdev->vram_scratch.ptr); + if (r) + radeon_bo_unpin(rdev->vram_scratch.robj); + radeon_bo_unreserve(rdev->vram_scratch.robj); + + return r; +} + +static void rv770_vram_scratch_fini(struct radeon_device *rdev) +{ + int r; + + if (rdev->vram_scratch.robj == NULL) { + return; + } + r = radeon_bo_reserve(rdev->vram_scratch.robj, false); + if (likely(r == 0)) { + radeon_bo_kunmap(rdev->vram_scratch.robj); + radeon_bo_unpin(rdev->vram_scratch.robj); + radeon_bo_unreserve(rdev->vram_scratch.robj); + } + radeon_bo_unref(&rdev->vram_scratch.robj); +} + int rv770_mc_init(struct radeon_device *rdev) { u32 tmp; @@ -970,6 +1018,9 @@ static int rv770_startup(struct radeon_device *rdev) if (r) return r; } + r = rv770_vram_scratch_init(rdev); + if (r) + return r; rv770_gpu_init(rdev); r = r600_blit_init(rdev); if (r) { @@ -1195,6 +1246,7 @@ void rv770_fini(struct radeon_device *rdev) r600_irq_fini(rdev); radeon_irq_kms_fini(rdev); rv770_pcie_gart_fini(rdev); + rv770_vram_scratch_fini(rdev); radeon_gem_fini(rdev); radeon_fence_driver_fini(rdev); radeon_clocks_fini(rdev); -- cgit v0.10.2 From 4afc31345e5f543e5d89a47aeadaaad1d91a5bc8 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Sun, 29 Aug 2010 01:55:38 +0900 Subject: nilfs2: fix leak of shadow dat inode in error path of load_nilfs If load_nilfs() gets an error while doing recovery, it will fail to free the shadow inode of dat (nilfs->ns_gc_dat). This fixes the leak issue. Signed-off-by: Ryusuke Konishi diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 4317f17..ba7c10c 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c @@ -446,6 +446,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) nilfs_mdt_destroy(nilfs->ns_cpfile); nilfs_mdt_destroy(nilfs->ns_sufile); nilfs_mdt_destroy(nilfs->ns_dat); + nilfs_mdt_destroy(nilfs->ns_gc_dat); failed: nilfs_clear_recovery_info(&ri); -- cgit v0.10.2 From 01ebc12f5f2e88a1c6a5436b71a506ac2bf66d6b Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 7 Aug 2010 11:09:29 +0200 Subject: UBI: eliminate update of list_for_each_entry loop cursor list_for_each_entry uses its first argument to move from one element to the next, so modifying it can break the iteration. The variable re1 is already used within the loop as a temporary variable, and is not live here. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r@ iterator name list_for_each_entry; expression x,E; position p1,p2; @@ list_for_each_entry@p1(x,...) { <... x =@p2 E ...> } @@ expression x,E; position r.p1,r.p2; statement S; @@ *x =@p2 E ... list_for_each_entry@p1(x,...) S // Signed-off-by: Julia Lawall Signed-off-by: Artem Bityutskiy diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index 4dfa6b9..3d2d1a6 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -798,18 +798,18 @@ static int rename_volumes(struct ubi_device *ubi, goto out_free; } - re = kzalloc(sizeof(struct ubi_rename_entry), GFP_KERNEL); - if (!re) { + re1 = kzalloc(sizeof(struct ubi_rename_entry), GFP_KERNEL); + if (!re1) { err = -ENOMEM; ubi_close_volume(desc); goto out_free; } - re->remove = 1; - re->desc = desc; - list_add(&re->list, &rename_list); + re1->remove = 1; + re1->desc = desc; + list_add(&re1->list, &rename_list); dbg_msg("will remove volume %d, name \"%s\"", - re->desc->vol->vol_id, re->desc->vol->name); + re1->desc->vol->vol_id, re1->desc->vol->name); } mutex_lock(&ubi->device_mutex); -- cgit v0.10.2 From 80c1c16fb89e7055acb560e6d90c881b5c7496c1 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sat, 28 Aug 2010 12:11:40 +0300 Subject: UBI: fix forward compatibility Commit 0798cea8c2e1afee59686c51d27d0e96b05e42d1 "UBI: improve corrupted flash handling" broke delet-compatible volumes handling - it introduced a limit of 8 eraseblocks which may be corrupted. And delete-compatible eraseblocks are added to the "corrupted" list, so if we'd have a large delete-compatible volume, UBI would refuse it. The fix is to add delete-compatible volumes to the erase list instead. Indeed, they are corrupted, we just have to erase them. Signed-off-by: Artem Bityutskiy diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 372a15a..69b52e9 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -843,7 +843,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, case UBI_COMPAT_DELETE: ubi_msg("\"delete\" compatible internal volume %d:%d" " found, will remove it", vol_id, lnum); - err = add_to_list(si, pnum, ec, &si->corr); + err = add_to_list(si, pnum, ec, &si->erase); if (err) return err; return 0; -- cgit v0.10.2 From 7c44ece988a3419e51c833cf14be186a22224dd1 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 30 Aug 2010 17:35:52 +1000 Subject: Move .gitignore from drivers/md to lib/raid6 Another missing bit of the raid6 -> /lib move. Reported-by: Andreas Schwab Signed-off-by: NeilBrown diff --git a/drivers/md/.gitignore b/drivers/md/.gitignore deleted file mode 100644 index a7afec6..0000000 --- a/drivers/md/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -mktables -raid6altivec*.c -raid6int*.c -raid6tables.c diff --git a/lib/raid6/.gitignore b/lib/raid6/.gitignore new file mode 100644 index 0000000..162beca --- /dev/null +++ b/lib/raid6/.gitignore @@ -0,0 +1,4 @@ +mktables +altivec*.c +int*.c +tables.c -- cgit v0.10.2 From bd52b746262c8d77e73903d6608014fb2fcdcd9d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 30 Aug 2010 17:33:33 +1000 Subject: md: don't clear MD_CHANGE_CLEAN in md_update_sb() for external arrays If this bit is cleared in md_update_sb() the kernel will allow writes to the array if userspace triggers md_allow_write(), e.g. through stripe_cache_size, when mdmon is not active. When mdmon is active the array transitions to active-idle bypassing write-pending, setting up a race for mdmon to set the array clean before a write arrives. Signed-off-by: Dan Williams Signed-off-by: NeilBrown diff --git a/drivers/md/md.c b/drivers/md/md.c index c148b63..a1f6b59 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2167,9 +2167,10 @@ repeat: rdev->recovery_offset = mddev->curr_resync_completed; } - if (mddev->external || !mddev->persistent) { + if (!mddev->persistent) { + if (!mddev->external) + clear_bit(MD_CHANGE_CLEAN, &mddev->flags); clear_bit(MD_CHANGE_DEVS, &mddev->flags); - clear_bit(MD_CHANGE_CLEAN, &mddev->flags); wake_up(&mddev->sb_wait); return; } -- cgit v0.10.2 From 070dc6dd7103b6b3f7e4d46e754354a5c15f366e Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 30 Aug 2010 17:33:34 +1000 Subject: md: resolve confusion of MD_CHANGE_CLEAN MD_CHANGE_CLEAN is used for two different purposes and this leads to confusion. One of the purposes is largely mirrored by MD_CHANGE_PENDING which is not used for anything else, so have MD_CHANGE_PENDING take over that purpose fully. The two purposes are: 1/ tell md_update_sb that an update is needed and that it is just a clean/dirty transition. 2/ tell user-space that an transition from clean to dirty is pending (something wants to write), and tell te kernel (by clearin the flag) that the transition is OK. The first purpose remains wit MD_CHANGE_CLEAN, the second is moved fully to MD_CHANGE_PENDING. This means that various places which conditionally set or cleared MD_CHANGE_CLEAN no longer need to be conditional. Signed-off-by: NeilBrown diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 1ba1e12..ed4900a 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1542,8 +1542,7 @@ void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector) atomic_read(&bitmap->mddev->recovery_active) == 0); bitmap->mddev->curr_resync_completed = bitmap->mddev->curr_resync; - if (bitmap->mddev->persistent) - set_bit(MD_CHANGE_CLEAN, &bitmap->mddev->flags); + set_bit(MD_CHANGE_CLEAN, &bitmap->mddev->flags); sector &= ~((1ULL << CHUNK_BLOCK_SHIFT(bitmap)) - 1); s = 0; while (s < sector && s < bitmap->mddev->resync_max_sectors) { diff --git a/drivers/md/md.c b/drivers/md/md.c index a1f6b59..43cf9cc 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2168,8 +2168,7 @@ repeat: } if (!mddev->persistent) { - if (!mddev->external) - clear_bit(MD_CHANGE_CLEAN, &mddev->flags); + clear_bit(MD_CHANGE_CLEAN, &mddev->flags); clear_bit(MD_CHANGE_DEVS, &mddev->flags); wake_up(&mddev->sb_wait); return; @@ -2179,7 +2178,6 @@ repeat: mddev->utime = get_seconds(); - set_bit(MD_CHANGE_PENDING, &mddev->flags); if (test_and_clear_bit(MD_CHANGE_DEVS, &mddev->flags)) force_change = 1; if (test_and_clear_bit(MD_CHANGE_CLEAN, &mddev->flags)) @@ -3372,7 +3370,7 @@ array_state_show(mddev_t *mddev, char *page) case 0: if (mddev->in_sync) st = clean; - else if (test_bit(MD_CHANGE_CLEAN, &mddev->flags)) + else if (test_bit(MD_CHANGE_PENDING, &mddev->flags)) st = write_pending; else if (mddev->safemode) st = active_idle; @@ -3453,9 +3451,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) mddev->in_sync = 1; if (mddev->safemode == 1) mddev->safemode = 0; - if (mddev->persistent) - set_bit(MD_CHANGE_CLEAN, - &mddev->flags); + set_bit(MD_CHANGE_CLEAN, &mddev->flags); } err = 0; } else @@ -3467,8 +3463,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) case active: if (mddev->pers) { restart_array(mddev); - if (mddev->external) - clear_bit(MD_CHANGE_CLEAN, &mddev->flags); + clear_bit(MD_CHANGE_PENDING, &mddev->flags); wake_up(&mddev->sb_wait); err = 0; } else { @@ -6573,6 +6568,7 @@ void md_write_start(mddev_t *mddev, struct bio *bi) if (mddev->in_sync) { mddev->in_sync = 0; set_bit(MD_CHANGE_CLEAN, &mddev->flags); + set_bit(MD_CHANGE_PENDING, &mddev->flags); md_wakeup_thread(mddev->thread); did_change = 1; } @@ -6581,7 +6577,6 @@ void md_write_start(mddev_t *mddev, struct bio *bi) if (did_change) sysfs_notify_dirent_safe(mddev->sysfs_state); wait_event(mddev->sb_wait, - !test_bit(MD_CHANGE_CLEAN, &mddev->flags) && !test_bit(MD_CHANGE_PENDING, &mddev->flags)); } @@ -6617,6 +6612,7 @@ int md_allow_write(mddev_t *mddev) if (mddev->in_sync) { mddev->in_sync = 0; set_bit(MD_CHANGE_CLEAN, &mddev->flags); + set_bit(MD_CHANGE_PENDING, &mddev->flags); if (mddev->safemode_delay && mddev->safemode == 0) mddev->safemode = 1; @@ -6626,7 +6622,7 @@ int md_allow_write(mddev_t *mddev) } else spin_unlock_irq(&mddev->write_lock); - if (test_bit(MD_CHANGE_CLEAN, &mddev->flags)) + if (test_bit(MD_CHANGE_PENDING, &mddev->flags)) return -EAGAIN; else return 0; @@ -6824,8 +6820,7 @@ void md_do_sync(mddev_t *mddev) atomic_read(&mddev->recovery_active) == 0); mddev->curr_resync_completed = mddev->curr_resync; - if (mddev->persistent) - set_bit(MD_CHANGE_CLEAN, &mddev->flags); + set_bit(MD_CHANGE_CLEAN, &mddev->flags); sysfs_notify(&mddev->kobj, NULL, "sync_completed"); } @@ -7104,8 +7099,7 @@ void md_check_recovery(mddev_t *mddev) mddev->recovery_cp == MaxSector) { mddev->in_sync = 1; did_change = 1; - if (mddev->persistent) - set_bit(MD_CHANGE_CLEAN, &mddev->flags); + set_bit(MD_CHANGE_CLEAN, &mddev->flags); } if (mddev->safemode == 1) mddev->safemode = 0; diff --git a/drivers/md/md.h b/drivers/md/md.h index a953fe2..3931299 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -140,7 +140,7 @@ struct mddev_s unsigned long flags; #define MD_CHANGE_DEVS 0 /* Some device status has changed */ #define MD_CHANGE_CLEAN 1 /* transition to or from 'clean' */ -#define MD_CHANGE_PENDING 2 /* superblock update in progress */ +#define MD_CHANGE_PENDING 2 /* switch from 'clean' to 'active' in progress */ int suspended; atomic_t active_io; -- cgit v0.10.2 From 1deacd7a1d4bb22f812908c34e3254de76e4faa8 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 12 Aug 2010 12:10:59 -0700 Subject: UBI: fix kconfig unmet dependency warning: (OPTPROBES && KPROBES && HAVE_OPTPROBES && !PREEMPT && DEBUG_KERNEL || MTD_UBI_DEBUG && MTD && SYSFS && MTD_UBI || UBIFS_FS_DEBUG && MISC_FILESYSTEMS && UBIFS_FS || LOCKDEP && DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT || LATENCYTOP && HAVE_LATENCYTOP_SUPPORT && DEBUG_KERNEL && STACKTRACE_SUPPORT && PROC_FS) selects KALLSYMS_ALL which has unmet direct dependencies (DEBUG_KERNEL && KALLSYMS) Signed-off-by: Randy Dunlap Signed-off-by: Artem Bityutskiy diff --git a/drivers/mtd/ubi/Kconfig.debug b/drivers/mtd/ubi/Kconfig.debug index 2246f15..61f6e5e 100644 --- a/drivers/mtd/ubi/Kconfig.debug +++ b/drivers/mtd/ubi/Kconfig.debug @@ -6,7 +6,7 @@ config MTD_UBI_DEBUG depends on SYSFS depends on MTD_UBI select DEBUG_FS - select KALLSYMS_ALL + select KALLSYMS_ALL if KALLSYMS && DEBUG_KERNEL help This option enables UBI debugging. -- cgit v0.10.2 From d3f6e6c666c0f68991d785177c4c62fcd1d651f2 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sun, 29 Aug 2010 23:34:44 +0300 Subject: UBI: do not oops when erroneous PEB is scheduled for scrubbing When an erroneous PEB is scheduling for scrubbing, we end up with the following oops: [] (prot_queue_del+0x0/0x50) from [] (ubi_wl_scrub_peb+0xec/0x13c) [] (ubi_wl_scrub_peb+0x0/0x13c) from [] (ubi_eba_read_leb+0x200/0x428) [] (ubi_eba_read_leb+0x0/0x428) from [] (ubi_leb_read+0xe8/0x138) [] (ubi_leb_read+0x0/0x138) from [] (ubifs_start_scan+0x7c/0xf4) [] (ubifs_start_scan+0x0/0xf4) from [] (ubifs_recover_leb+0x3c/0x730) [] (ubifs_recover_leb+0x0/0x730) from [] (ubifs_recover_log_leb+0xc8/0x2dc) [] (ubifs_recover_log_leb+0x0/0x2dc) from [] (ubifs_replay_journal+0xb90/0x13a4) [] (ubifs_replay_journal+0x0/0x13a4) from [] (ubifs_fill_super+0xb84/0x1054) [] (ubifs_fill_super+0x0/0x1054) from [] (ubifs_get_sb+0xc4/0x2ac) [] (ubifs_get_sb+0x0/0x2ac) from [] (vfs_kern_mount+0x58/0x94) [] (vfs_kern_mount+0x0/0x94) from [] (do_kern_mount+0x40/0xe8) [] (do_kern_mount+0x0/0xe8) from [] (do_new_mount+0x68/0x8c) [] (do_new_mount+0x0/0x8c) from [] (do_mount+0x15c/0x1b8) [] (do_mount+0x0/0x1b8) from [] (sys_mount+0x8c/0xd4) [] (sys_mount+0x0/0xd4) from [] (ret_fast_syscall+0x0/0x2c) Kernel panic - not syncing: Fatal exception The problem is that 'ubi_wl_scrub_peb()' does not expect that PEBs may be in the erroneous tree, which is a bug. This patch fixes the bug and adds corresponding check to 'ubi_wl_scrub_peb()'. Now it will simply ignore erroneous PEBs, instead of causing an oops. Reported-by: Matthieu CASTET Signed-off-by: Artem Bityutskiy diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index ee7b1d8..97a4356 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -1212,7 +1212,8 @@ int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum) retry: spin_lock(&ubi->wl_lock); e = ubi->lookuptbl[pnum]; - if (e == ubi->move_from || in_wl_tree(e, &ubi->scrub)) { + if (e == ubi->move_from || in_wl_tree(e, &ubi->scrub) || + in_wl_tree(e, &ubi->erroneous)) { spin_unlock(&ubi->wl_lock); return 0; } -- cgit v0.10.2 From 8f587df479c3cea14ba1a9b9d58f34fd2fd6d58b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 4 Aug 2010 16:27:45 +0000 Subject: 9p: potential ERR_PTR() dereference p9_client_walk() can return error values if we run out of space or there is a problem with the network. Signed-off-by: Dan Carpenter Signed-off-by: Eric Van Hensbergen diff --git a/fs/9p/fid.c b/fs/9p/fid.c index 3585636..6406f89 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c @@ -242,7 +242,8 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry) } kfree(wnames); fid_out: - v9fs_fid_add(dentry, fid); + if (!IS_ERR(fid)) + v9fs_fid_add(dentry, fid); err_out: up_read(&v9ses->rename_sem); return fid; -- cgit v0.10.2 From d8e1ba76d619dbc0be8fbeee4e6c683b5c812d3a Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 24 Aug 2010 15:27:34 -0400 Subject: ath5k: check return value of ieee80211_get_tx_rate This avoids a NULL pointer dereference as reported here: https://bugzilla.redhat.com/show_bug.cgi?id=625889 When the WARN condition is hit in ieee80211_get_tx_rate, it will return NULL. So, we need to check the return value and avoid dereferencing it in that case. Signed-off-by: John W. Linville Cc: stable@kernel.org Acked-by: Bob Copeland diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 373dcfe..d77ce99 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1327,6 +1327,10 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, PCI_DMA_TODEVICE); rate = ieee80211_get_tx_rate(sc->hw, info); + if (!rate) { + ret = -EINVAL; + goto err_unmap; + } if (info->flags & IEEE80211_TX_CTL_NO_ACK) flags |= AR5K_TXDESC_NOACK; -- cgit v0.10.2 From f880c2050f30b23c9b6f80028c09f76e693bf309 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 24 Aug 2010 22:54:05 +0200 Subject: p54: fix tx feedback status flag check Michael reported that p54* never really entered power save mode, even tough it was enabled. It turned out that upon a power save mode change the firmware will set a special flag onto the last outgoing frame tx status (which in this case is almost always the designated PSM nullfunc frame). This flag confused the driver; It erroneously reported transmission failures to the stack, which then generated the next nullfunc. and so on... Cc: Reported-by: Michael Buesch Tested-by: Michael Buesch Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 173aec3..0e937dc 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -446,7 +446,7 @@ static void p54_rx_frame_sent(struct p54_common *priv, struct sk_buff *skb) } if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && - (!payload->status)) + !(payload->status & P54_TX_FAILED)) info->flags |= IEEE80211_TX_STAT_ACK; if (payload->status & P54_TX_PSM_CANCELLED) info->flags |= IEEE80211_TX_STAT_TX_FILTERED; -- cgit v0.10.2 From 071249b1d501b1f31a6b1af3fbcbe03158a84e5c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 25 Aug 2010 14:47:38 +0200 Subject: mac80211: delete work timer The new workqueue changes helped me find this bug that's been lingering since the changes to the work processing in mac80211 -- the work timer is never deleted properly. Do that to avoid having it fire after all data structures have been freed. It can't be re-armed because all it will do, if running, is schedule the work, but that gets flushed later and won't have anything to do since all work items are gone by now (by way of interface removal). Cc: stable@kernel.org [2.6.34+] Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 798a91b..ded5c38 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -732,6 +732,12 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) rtnl_unlock(); + /* + * Now all work items will be gone, but the + * timer might still be armed, so delete it + */ + del_timer_sync(&local->work_timer); + cancel_work_sync(&local->reconfig_filter); ieee80211_clear_tx_pending(local); -- cgit v0.10.2 From 9ef808048564928a83f3a52c65c5725688cf5cbe Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 27 Aug 2010 09:44:12 -0400 Subject: MAINTAINERS: change broken url for prism54 Reported-by: Joe Perches Signed-off-by: John W. Linville diff --git a/MAINTAINERS b/MAINTAINERS index 44620ae..8e85429 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4549,7 +4549,7 @@ F: include/linux/preempt.h PRISM54 WIRELESS DRIVER M: "Luis R. Rodriguez" L: linux-wireless@vger.kernel.org -W: http://prism54.org +W: http://wireless.kernel.org/en/users/Drivers/p54 S: Obsolete F: drivers/net/wireless/prism54/ -- cgit v0.10.2 From 42da2f948d949efd0111309f5827bf0298bcc9a4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 30 Aug 2010 12:24:54 +0200 Subject: wireless extensions: fix kernel heap content leak Wireless extensions have an unfortunate, undocumented requirement which requires drivers to always fill iwp->length when returning a successful status. When a driver doesn't do this, it leads to a kernel heap content leak when userspace offers a larger buffer than would have been necessary. Arguably, this is a driver bug, as it should, if it returns 0, fill iwp->length, even if it separately indicated that the buffer contents was not valid. However, we can also at least avoid the memory content leak if the driver doesn't do this by setting the iwp length to max_tokens, which then reflects how big the buffer is that the driver may fill, regardless of how big the userspace buffer is. To illustrate the point, this patch also fixes a corresponding cfg80211 bug (since this requirement isn't documented nor was ever pointed out by anyone during code review, I don't trust all drivers nor all cfg80211 handlers to implement it correctly). Cc: stable@kernel.org [all the way back] Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index bb5e0a5..7e5c3a4 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -1420,6 +1420,9 @@ int cfg80211_wext_giwessid(struct net_device *dev, { struct wireless_dev *wdev = dev->ieee80211_ptr; + data->flags = 0; + data->length = 0; + switch (wdev->iftype) { case NL80211_IFTYPE_ADHOC: return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index 0ef17bc..8f5116f 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c @@ -782,6 +782,22 @@ static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd, } } + if (IW_IS_GET(cmd) && !(descr->flags & IW_DESCR_FLAG_NOMAX)) { + /* + * If this is a GET, but not NOMAX, it means that the extra + * data is not bounded by userspace, but by max_tokens. Thus + * set the length to max_tokens. This matches the extra data + * allocation. + * The driver should fill it with the number of tokens it + * provided, and it may check iwp->length rather than having + * knowledge of max_tokens. If the driver doesn't change the + * iwp->length, this ioctl just copies back max_token tokens + * filled with zeroes. Hopefully the driver isn't claiming + * them to be valid data. + */ + iwp->length = descr->max_tokens; + } + err = handler(dev, info, (union iwreq_data *) iwp, extra); iwp->length += essid_compat; -- cgit v0.10.2 From 4562c986f0d694124de20815adf7e1aad8a94668 Mon Sep 17 00:00:00 2001 From: Matthew McClintock Date: Fri, 27 Aug 2010 11:58:21 +0000 Subject: powerpc/kexec: Adds correct calling convention for kexec purgatory Call kexec purgatory code correctly. We were getting lucky before. If you examine the powerpc 32bit kexec "purgatory" code you will see it expects the following: >From kexec-tools: purgatory/arch/ppc/v2wrap_32.S -> calling convention: -> r3 = physical number of this cpu (all cpus) -> r4 = address of this chunk (master only) As such, we need to set r3 to the current core, r4 happens to be unused by purgatory at the moment but we go ahead and set it here as well Signed-off-by: Matthew McClintock Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 6bbd7a6..a7a570d 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -810,6 +810,9 @@ relocate_new_kernel: isync sync + mfspr r3, SPRN_PIR /* current core we are running on */ + mr r4, r5 /* load physical address of chunk called */ + /* jump to the entry point, usually the setup routine */ mtlr r5 blrl -- cgit v0.10.2 From b0d278b7d3ae9115939ddcea93f516308cc367e2 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 10 Aug 2010 20:38:23 +0000 Subject: powerpc/perf_event: Reduce latency of calling perf_event_do_pending Commit 0fe1ac48 ("powerpc/perf_event: Fix oops due to perf_event_do_pending call") moved the call to perf_event_do_pending in timer_interrupt() down so that it was after the irq_enter() call. Unfortunately this moved it after the code that checks whether it is time for the next decrementer clock event. The result is that the call to perf_event_do_pending() won't happen until the next decrementer clock event is due. This was pointed out by Milton Miller. This fixes it by moving the check for whether it's time for the next decrementer clock event down to the point where we're about to call the event handler, after we've called perf_event_do_pending. This has the side effect that on old pre-Core99 Powermacs where we use the ppc_n_lost_interrupts mechanism to replay interrupts, a replayed interrupt will incur a little more latency since it will now do the code from the irq_enter down to the irq_exit, that it used to skip. However, these machines are now old and rare enough that this doesn't matter. To make it clear that ppc_n_lost_interrupts is only used on Powermacs, and to speed up the code slightly on non-Powermac ppc32 machines, the code that tests ppc_n_lost_interrupts is now conditional on CONFIG_PMAC as well as CONFIG_PPC32. Signed-off-by: Paul Mackerras Cc: stable@kernel.org Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index ce53dfa..8533b3b 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -577,20 +577,11 @@ void timer_interrupt(struct pt_regs * regs) * some CPUs will continuue to take decrementer exceptions */ set_dec(DECREMENTER_MAX); -#ifdef CONFIG_PPC32 +#if defined(CONFIG_PPC32) && defined(CONFIG_PMAC) if (atomic_read(&ppc_n_lost_interrupts) != 0) do_IRQ(regs); #endif - now = get_tb_or_rtc(); - if (now < decrementer->next_tb) { - /* not time for this event yet */ - now = decrementer->next_tb - now; - if (now <= DECREMENTER_MAX) - set_dec((int)now); - trace_timer_interrupt_exit(regs); - return; - } old_regs = set_irq_regs(regs); irq_enter(); @@ -606,8 +597,16 @@ void timer_interrupt(struct pt_regs * regs) get_lppaca()->int_dword.fields.decr_int = 0; #endif - if (evt->event_handler) - evt->event_handler(evt); + now = get_tb_or_rtc(); + if (now >= decrementer->next_tb) { + decrementer->next_tb = ~(u64)0; + if (evt->event_handler) + evt->event_handler(evt); + } else { + now = decrementer->next_tb - now; + if (now <= DECREMENTER_MAX) + set_dec((int)now); + } #ifdef CONFIG_PPC_ISERIES if (firmware_has_feature(FW_FEATURE_ISERIES) && hvlpevent_is_pending()) -- cgit v0.10.2 From 54a834043314c257210db2a9d59f8cc605571639 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Wed, 25 Aug 2010 21:04:25 +0000 Subject: powerpc: Don't use kernel stack with translation off In f761622e59433130bc33ad086ce219feee9eb961 we changed early_setup_secondary so it's called using the proper kernel stack rather than the emergency one. Unfortunately, this stack pointer can't be used when translation is off on PHYP as this stack pointer might be outside the RMO. This results in the following on all non zero cpus: cpu 0x1: Vector: 300 (Data Access) at [c00000001639fd10] pc: 000000000001c50c lr: 000000000000821c sp: c00000001639ff90 msr: 8000000000001000 dar: c00000001639ffa0 dsisr: 42000000 current = 0xc000000016393540 paca = 0xc000000006e00200 pid = 0, comm = swapper The original patch was only tested on bare metal system, so it never caught this problem. This changes __secondary_start so that we calculate the new stack pointer but only start using it after we've called early_setup_secondary. With this patch, the above problem goes away. Signed-off-by: Michael Neuling Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 4d6681d..c571cd3 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -575,13 +575,19 @@ __secondary_start: /* Initialize the kernel stack. Just a repeat for iSeries. */ LOAD_REG_ADDR(r3, current_set) sldi r28,r24,3 /* get current_set[cpu#] */ - ldx r1,r3,r28 - addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD - std r1,PACAKSAVE(r13) + ldx r14,r3,r28 + addi r14,r14,THREAD_SIZE-STACK_FRAME_OVERHEAD + std r14,PACAKSAVE(r13) /* Do early setup for that CPU (stab, slb, hash table pointer) */ bl .early_setup_secondary + /* + * setup the new stack pointer, but *don't* use this until + * translation is on. + */ + mr r1, r14 + /* Clear backchain so we get nice backtraces */ li r7,0 mtlr r7 -- cgit v0.10.2 From 628e300cccaa628d8fb92aa28cb7530a3d5f2257 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 30 Aug 2010 18:35:24 -0700 Subject: irda: Correctly clean up self->ias_obj on irda_bind() failure. If irda_open_tsap() fails, the irda_bind() code tries to destroy the ->ias_obj object by hand, but does so wrongly. In particular, it fails to a) release the hashbin attached to the object and b) reset the self->ias_obj pointer to NULL. Fix both problems by using irias_delete_object() and explicitly setting self->ias_obj to NULL, just as irda_release() does. Reported-by: Tavis Ormandy Signed-off-by: David S. Miller diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 79986a6..fd55b51 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -824,8 +824,8 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) err = irda_open_tsap(self, addr->sir_lsap_sel, addr->sir_name); if (err < 0) { - kfree(self->ias_obj->name); - kfree(self->ias_obj); + irias_delete_object(self->ias_obj); + self->ias_obj = NULL; goto out; } -- cgit v0.10.2 From 477a3c33d1efa0342a74bd02da2e049191993e2c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 31 Aug 2010 10:54:35 +0200 Subject: workqueue: fix GCWQ_DISASSOCIATED initialization init_workqueues() incorrectly marks workqueues for all possible CPUs associated. Combined with mayday_mask initialization bug, this can make rescuers keep trying to bind to an offline gcwq indefinitely. Fix init_workqueues() such that only online CPUs have their gcwqs have GCWQ_DISASSOCIATED cleared. Signed-off-by: Tejun Heo Reported-by: CAI Qian diff --git a/kernel/workqueue.c b/kernel/workqueue.c index a2dccfc..c8183b2 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -3558,8 +3558,7 @@ static int __init init_workqueues(void) spin_lock_init(&gcwq->lock); INIT_LIST_HEAD(&gcwq->worklist); gcwq->cpu = cpu; - if (cpu == WORK_CPU_UNBOUND) - gcwq->flags |= GCWQ_DISASSOCIATED; + gcwq->flags |= GCWQ_DISASSOCIATED; INIT_LIST_HEAD(&gcwq->idle_list); for (i = 0; i < BUSY_WORKER_HASH_SIZE; i++) @@ -3583,6 +3582,8 @@ static int __init init_workqueues(void) struct global_cwq *gcwq = get_gcwq(cpu); struct worker *worker; + if (cpu != WORK_CPU_UNBOUND) + gcwq->flags &= ~GCWQ_DISASSOCIATED; worker = create_worker(gcwq, true); BUG_ON(!worker); spin_lock_irq(&gcwq->lock); -- cgit v0.10.2 From 9c37547ab62f88aac3e1e3c2065b611f811de9b5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 31 Aug 2010 11:18:34 +0200 Subject: workqueue: use zalloc_cpumask_var() for gcwq->mayday_mask alloc_mayday_mask() was using alloc_cpumask_var() making gcwq->mayday_mask contain garbage after initialization on CONFIG_CPUMASK_OFFSTACK=y configurations. This combined with the previously fixed GCWQ_DISASSOCIATED initialization bug could make rescuers fall into infinite loop trying to bind to an offline cpu. Signed-off-by: Tejun Heo Reported-by: CAI Qian diff --git a/kernel/workqueue.c b/kernel/workqueue.c index c8183b2..7855429 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -196,7 +196,7 @@ typedef cpumask_var_t mayday_mask_t; cpumask_test_and_set_cpu((cpu), (mask)) #define mayday_clear_cpu(cpu, mask) cpumask_clear_cpu((cpu), (mask)) #define for_each_mayday_cpu(cpu, mask) for_each_cpu((cpu), (mask)) -#define alloc_mayday_mask(maskp, gfp) alloc_cpumask_var((maskp), (gfp)) +#define alloc_mayday_mask(maskp, gfp) zalloc_cpumask_var((maskp), (gfp)) #define free_mayday_mask(mask) free_cpumask_var((mask)) #else typedef unsigned long mayday_mask_t; -- cgit v0.10.2 From 6d4f2fb0860c36e7ef16cc41126242a8b6542771 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 31 Aug 2010 04:15:22 +0200 Subject: powerpc/85xx: Fix compilation of mpc85xx_mds.c Commit 99d8238f berobbed the for_each loop of its iterator! Let's be nice and give it back, so it compiles for us. CC: Anton Vorontsov Signed-off-by: Alexander Graf Signed-off-by: Kumar Gala diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index da64be1..aa34cac 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c @@ -357,6 +357,7 @@ static void __init mpc85xx_mds_setup_arch(void) { #ifdef CONFIG_PCI struct pci_controller *hose; + struct device_node *np; #endif dma_addr_t max = 0xffffffff; -- cgit v0.10.2 From dc1c41f450a5f201f1d8c19aef32319f3b84c273 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Tue, 31 Aug 2010 11:39:25 -0500 Subject: powerpc/85xx: Fix compile issue with p1022_ds due to lmb rename to memblock arch/powerpc/platforms/85xx/p1022_ds.c:22:23: error: linux/lmb.h: No such file or directory arch/powerpc/platforms/85xx/p1022_ds.c: In function 'p1022_ds_setup_arch': arch/powerpc/platforms/85xx/p1022_ds.c:100: error: implicit declaration of function 'memblock_end_of_DRAM' arch/powerpc/platforms/85xx/p1022_ds.c: At top level: arch/powerpc/platforms/85xx/p1022_ds.c:147: error: 'udbg_progress' undeclared here (not in a function) make[2]: *** [arch/powerpc/platforms/85xx/p1022_ds.o] Error 1 Signed-off-by: Kumar Gala diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c index e1467c9..34e0090 100644 --- a/arch/powerpc/platforms/85xx/p1022_ds.c +++ b/arch/powerpc/platforms/85xx/p1022_ds.c @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include @@ -97,7 +97,7 @@ static void __init p1022_ds_setup_arch(void) #endif #ifdef CONFIG_SWIOTLB - if (lmb_end_of_DRAM() > max) { + if (memblock_end_of_DRAM() > max) { ppc_swiotlb_enable = 1; set_pci_dma_ops(&swiotlb_dma_ops); ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; -- cgit v0.10.2 From b963ea89f00f13c648af4082e5efb2172d369727 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 30 Aug 2010 19:08:01 -0700 Subject: netlink: Make NETLINK_USERSOCK work again. Once we started enforcing the a nl_table[] entry exist for a protocol, NETLINK_USERSOCK stopped working. Add a dummy table entry so that it works again. Reported-by: Thomas Voegtle Tested-by: Thomas Voegtle Signed-off-by: David S. Miller diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 980fe4a..cd96ed3 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -2102,6 +2102,26 @@ static void __net_exit netlink_net_exit(struct net *net) #endif } +static void __init netlink_add_usersock_entry(void) +{ + unsigned long *listeners; + int groups = 32; + + listeners = kzalloc(NLGRPSZ(groups) + sizeof(struct listeners_rcu_head), + GFP_KERNEL); + if (!listeners) + panic("netlink_add_usersock_entry: Cannot allocate listneres\n"); + + netlink_table_grab(); + + nl_table[NETLINK_USERSOCK].groups = groups; + nl_table[NETLINK_USERSOCK].listeners = listeners; + nl_table[NETLINK_USERSOCK].module = THIS_MODULE; + nl_table[NETLINK_USERSOCK].registered = 1; + + netlink_table_ungrab(); +} + static struct pernet_operations __net_initdata netlink_net_ops = { .init = netlink_net_init, .exit = netlink_net_exit, @@ -2150,6 +2170,8 @@ static int __init netlink_proto_init(void) hash->rehash_time = jiffies; } + netlink_add_usersock_entry(); + sock_register(&netlink_family_ops); register_pernet_subsys(&netlink_net_ops); /* The netlink device handler may be needed early. */ -- cgit v0.10.2 From c3d34d5d9654ec9c2510f9341bfb1030b8f029d1 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 30 Aug 2010 17:36:40 -0400 Subject: wireless: register wiphy rfkill w/o holding cfg80211_mutex Otherwise lockdep complains... https://bugzilla.kernel.org/show_bug.cgi?id=17311 [ INFO: possible circular locking dependency detected ] 2.6.36-rc2-git4 #12 ------------------------------------------------------- kworker/0:3/3630 is trying to acquire lock: (rtnl_mutex){+.+.+.}, at: [] rtnl_lock+0x12/0x14 but task is already holding lock: (rfkill_global_mutex){+.+.+.}, at: [] rfkill_switch_all+0x24/0x49 [rfkill] which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #2 (rfkill_global_mutex){+.+.+.}: [] lock_acquire+0x120/0x15b [] __mutex_lock_common+0x54/0x52e [] mutex_lock_nested+0x34/0x39 [] rfkill_register+0x2b/0x29c [rfkill] [] wiphy_register+0x1ae/0x270 [cfg80211] [] ieee80211_register_hw+0x1b4/0x3cf [mac80211] [] iwl_ucode_callback+0x9e9/0xae3 [iwlagn] [] request_firmware_work_func+0x54/0x6f [] kthread+0x8c/0x94 [] kernel_thread_helper+0x4/0x10 -> #1 (cfg80211_mutex){+.+.+.}: [] lock_acquire+0x120/0x15b [] __mutex_lock_common+0x54/0x52e [] mutex_lock_nested+0x34/0x39 [] cfg80211_get_dev_from_ifindex+0x1b/0x7c [cfg80211] [] cfg80211_wext_giwscan+0x58/0x990 [cfg80211] [] ioctl_standard_iw_point+0x1a8/0x272 [] ioctl_standard_call+0x91/0xa7 [] T.723+0xbd/0x12c [] wext_handle_ioctl+0x31/0x6d [] dev_ioctl+0x63d/0x67a [] sock_ioctl+0x48/0x21d [] do_vfs_ioctl+0x4ba/0x509 [] sys_ioctl+0x51/0x74 [] system_call_fastpath+0x16/0x1b -> #0 (rtnl_mutex){+.+.+.}: [] __lock_acquire+0xa93/0xd9a [] lock_acquire+0x120/0x15b [] __mutex_lock_common+0x54/0x52e [] mutex_lock_nested+0x34/0x39 [] rtnl_lock+0x12/0x14 [] cfg80211_rfkill_set_block+0x1a/0x7b [cfg80211] [] rfkill_set_block+0x80/0xd5 [rfkill] [] __rfkill_switch_all+0x3f/0x6f [rfkill] [] rfkill_switch_all+0x38/0x49 [rfkill] [] rfkill_op_handler+0x105/0x136 [rfkill] [] process_one_work+0x248/0x403 [] worker_thread+0x139/0x214 [] kthread+0x8c/0x94 [] kernel_thread_helper+0x4/0x10 Signed-off-by: John W. Linville Acked-by: Johannes Berg diff --git a/net/wireless/core.c b/net/wireless/core.c index 541e2ff..d6d046b 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -475,12 +475,10 @@ int wiphy_register(struct wiphy *wiphy) mutex_lock(&cfg80211_mutex); res = device_add(&rdev->wiphy.dev); - if (res) - goto out_unlock; - - res = rfkill_register(rdev->rfkill); - if (res) - goto out_rm_dev; + if (res) { + mutex_unlock(&cfg80211_mutex); + return res; + } /* set up regulatory info */ wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); @@ -509,13 +507,18 @@ int wiphy_register(struct wiphy *wiphy) cfg80211_debugfs_rdev_add(rdev); mutex_unlock(&cfg80211_mutex); + /* + * due to a locking dependency this has to be outside of the + * cfg80211_mutex lock + */ + res = rfkill_register(rdev->rfkill); + if (res) + goto out_rm_dev; + return 0; out_rm_dev: device_del(&rdev->wiphy.dev); - -out_unlock: - mutex_unlock(&cfg80211_mutex); return res; } EXPORT_SYMBOL(wiphy_register); -- cgit v0.10.2 From 803288e61e346ba367373bc7d5eeb6e11c81a33c Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 30 Aug 2010 19:26:32 -0400 Subject: ath9k_hw: Fix EEPROM uncompress block reading on AR9003 The EEPROM is compressed on AR9003, upon decompression the wrong upper limit was being used for the block which prevented the 5 GHz CTL indexes from being used, which are stored towards the end of the EEPROM block. This fix allows the actual intended regulatory limits to be used on AR9003 hardware. Cc: stable@kernel.org [2.6.36+] Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index b883b17..057fb69 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -797,7 +797,7 @@ static bool ar9300_uncompress_block(struct ath_hw *ah, length = block[it+1]; length &= 0xff; - if (length > 0 && spot >= 0 && spot+length < mdataSize) { + if (length > 0 && spot >= 0 && spot+length <= mdataSize) { ath_print(common, ATH_DBG_EEPROM, "Restore at %d: spot=%d " "offset=%d length=%d\n", -- cgit v0.10.2 From 904879748d7439a6dabdc6be9aad983e216b027d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 30 Aug 2010 19:26:33 -0400 Subject: ath9k_hw: fix parsing of HT40 5 GHz CTLs The 5 GHz CTL indexes were not being read for all hardware devices due to the masking out through the CTL_MODE_M mask being one bit too short. Without this the calibrated regulatory maximum values were not being picked up when devices operate on 5 GHz in HT40 mode. The final output power used for Atheros devices is the minimum between the calibrated CTL values and what CRDA provides. Cc: stable@kernel.org [2.6.27+] Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 7f48df1..0b09db0 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -62,7 +62,7 @@ #define SD_NO_CTL 0xE0 #define NO_CTL 0xff -#define CTL_MODE_M 7 +#define CTL_MODE_M 0xf #define CTL_11A 0 #define CTL_11B 1 #define CTL_11G 2 diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h index a1c3952..345dd97 100644 --- a/drivers/net/wireless/ath/regd.h +++ b/drivers/net/wireless/ath/regd.h @@ -31,7 +31,6 @@ enum ctl_group { #define NO_CTL 0xff #define SD_NO_CTL 0xE0 #define NO_CTL 0xff -#define CTL_MODE_M 7 #define CTL_11A 0 #define CTL_11B 1 #define CTL_11G 2 -- cgit v0.10.2 From ff33f1821259d00d3fd85d86f59783e2ca3c9ee1 Mon Sep 17 00:00:00 2001 From: Li Yang Date: Fri, 18 Jun 2010 14:24:20 +0800 Subject: fsl_rio: fix compile errors Fixes the following compile problem on E500 platforms: arch/powerpc/sysdev/fsl_rio.c: In function 'fsl_rio_mcheck_exception': arch/powerpc/sysdev/fsl_rio.c:248: error: 'MCSR_MASK' undeclared (first use in this function) Also fixes the compile problem on non-E500 platforms. Signed-off-by: Li Yang Signed-off-by: Kumar Gala diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 6425abe..3017532 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -240,12 +240,13 @@ struct rio_priv { static void __iomem *rio_regs_win; +#ifdef CONFIG_E500 static int (*saved_mcheck_exception)(struct pt_regs *regs); static int fsl_rio_mcheck_exception(struct pt_regs *regs) { const struct exception_table_entry *entry = NULL; - unsigned long reason = (mfspr(SPRN_MCSR) & MCSR_MASK); + unsigned long reason = mfspr(SPRN_MCSR); if (reason & MCSR_BUS_RBERR) { reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR)); @@ -269,6 +270,7 @@ static int fsl_rio_mcheck_exception(struct pt_regs *regs) else return cur_cpu_spec->machine_check(regs); } +#endif /** * fsl_rio_doorbell_send - Send a MPC85xx doorbell message @@ -1517,8 +1519,10 @@ int fsl_rio_setup(struct platform_device *dev) fsl_rio_doorbell_init(port); fsl_rio_port_write_init(port); +#ifdef CONFIG_E500 saved_mcheck_exception = ppc_md.machine_check_exception; ppc_md.machine_check_exception = fsl_rio_mcheck_exception; +#endif /* Ensure that RFXE is set */ mtspr(SPRN_HID1, (mfspr(SPRN_HID1) | 0x20000)); -- cgit v0.10.2 From fa9fc821f8892590211a9aa9e855eb83152b9870 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 29 Aug 2010 21:47:18 +0200 Subject: arch/powerpc/platforms/83xx/mpc837x_mds.c: Add missing iounmap The function of_iomap returns the result of calling ioremap, so iounmap should be called on the result in the error handling code, as done in the normal exit of the function. The sematic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r exists@ local idexpression x; expression E,E1; identifier l; statement S; @@ *x = of_iomap(...); ... when != iounmap(x) when != if (...) { ... iounmap(x); ... } when != E = x when any ( if (x == NULL) S | if (...) { ... when != iounmap(x) when != if (...) { ... iounmap(x); ... } ( return <+...x...+>; | * return ...; ) } ) ... when != x = E1 when any iounmap(x); // Signed-off-by: Julia Lawall Signed-off-by: Kumar Gala diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c index f9751c8..8306832 100644 --- a/arch/powerpc/platforms/83xx/mpc837x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c @@ -48,8 +48,10 @@ static int mpc837xmds_usb_cfg(void) return -1; np = of_find_node_by_name(NULL, "usb"); - if (!np) - return -ENODEV; + if (!np) { + ret = -ENODEV; + goto out; + } phy_type = of_get_property(np, "phy_type", NULL); if (phy_type && !strcmp(phy_type, "ulpi")) { clrbits8(bcsr_regs + 12, BCSR12_USB_SER_PIN); @@ -65,8 +67,9 @@ static int mpc837xmds_usb_cfg(void) } of_node_put(np); +out: iounmap(bcsr_regs); - return 0; + return ret; } /* ************************************************************************ -- cgit v0.10.2 From 5aac4d73dc234fe7be91679b547af2436d7f8d1e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 29 Aug 2010 11:52:44 +0200 Subject: arch/powerpc/sysdev/qe_lib/qe.c: Add of_node_put to avoid memory leak Add a call to of_node_put in the error handling code following a call to of_find_compatible_node. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r exists@ local idexpression x; expression E,E1; statement S; @@ *x = (of_find_node_by_path |of_find_node_by_name |of_find_node_by_phandle |of_get_parent |of_get_next_parent |of_get_next_child |of_find_compatible_node |of_match_node )(...); ... if (x == NULL) S <... when != x = E *if (...) { ... when != of_node_put(x) when != if (...) { ... of_node_put(x); ... } ( return <+...x...+>; | * return ...; ) } ...> of_node_put(x); // Signed-off-by: Julia Lawall Acked-by: Timur Tabi Signed-off-by: Kumar Gala diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c index 3da8014..90020de 100644 --- a/arch/powerpc/sysdev/qe_lib/qe.c +++ b/arch/powerpc/sysdev/qe_lib/qe.c @@ -640,6 +640,7 @@ unsigned int qe_get_num_of_snums(void) if ((num_of_snums < 28) || (num_of_snums > QE_NUM_OF_SNUM)) { /* No QE ever has fewer than 28 SNUMs */ pr_err("QE: number of snum is invalid\n"); + of_node_put(qe); return -EINVAL; } } -- cgit v0.10.2 From a28dec2f26013aad89446b1f708f948617bc28a2 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sun, 8 Aug 2010 18:03:33 +0400 Subject: powerpc/85xx: Add P1021 PCI IDs and quirks This is needed for proper PCI-E support on P1021 SoCs. Signed-off-by: Anton Vorontsov Signed-off-by: Kumar Gala diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 209384b..4ae9332 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -399,6 +399,8 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1013E, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1013, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1020E, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1020, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1021E, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1021, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1022E, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1022, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010E, quirk_fsl_pcie_header); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index f6a3b2d..10d3330 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2300,6 +2300,8 @@ #define PCI_DEVICE_ID_P2010 0x0079 #define PCI_DEVICE_ID_P1020E 0x0100 #define PCI_DEVICE_ID_P1020 0x0101 +#define PCI_DEVICE_ID_P1021E 0x0102 +#define PCI_DEVICE_ID_P1021 0x0103 #define PCI_DEVICE_ID_P1011E 0x0108 #define PCI_DEVICE_ID_P1011 0x0109 #define PCI_DEVICE_ID_P1022E 0x0110 -- cgit v0.10.2 From 17134d96735115644cc2f0e2b1bab51ca6e3ab95 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 31 Aug 2010 15:25:55 -0700 Subject: PCI: bus speed strings should be const Signed-off-by: Stephen Hemminger Signed-off-by: Jesse Barnes diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index 659eaa0..968cfea 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c @@ -49,7 +49,7 @@ static ssize_t address_read_file(struct pci_slot *slot, char *buf) } /* these strings match up with the values in pci_bus_speed */ -static char *pci_bus_speed_strings[] = { +static const char *pci_bus_speed_strings[] = { "33 MHz PCI", /* 0x00 */ "66 MHz PCI", /* 0x01 */ "66 MHz PCI-X", /* 0x02 */ -- cgit v0.10.2 From 6445671b00b3c4bcb26c8e0fc74abe780a67b901 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Tue, 31 Aug 2010 22:26:15 -0400 Subject: alpha: remove homegrown L1_CACHE_ALIGN macro Let's use the standard L1_CACHE_ALIGN macro instead. Signed-off-by: FUJITA Tomonori Signed-off-by: Matt Turner diff --git a/arch/alpha/include/asm/cache.h b/arch/alpha/include/asm/cache.h index f199e69..ad368a9 100644 --- a/arch/alpha/include/asm/cache.h +++ b/arch/alpha/include/asm/cache.h @@ -17,7 +17,6 @@ # define L1_CACHE_SHIFT 5 #endif -#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1)) #define SMP_CACHE_BYTES L1_CACHE_BYTES #endif -- cgit v0.10.2 From 59b25ed91400ace98d6cf0d59b1cb6928ad5cd37 Mon Sep 17 00:00:00 2001 From: "Morten H. Larsen" Date: Tue, 31 Aug 2010 22:29:13 -0400 Subject: Fix call to replaced SuperIO functions This patch fixes the failure to compile Alpha Generic because of previously overlooked calls to ns87312_enable_ide(). The function has been replaced by newer SuperIO code. Tested-by: Michael Cree Signed-off-by: Morten H. Larsen Signed-off-by: Matt Turner diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h index 3d2627e..d3e52d3 100644 --- a/arch/alpha/kernel/proto.h +++ b/arch/alpha/kernel/proto.h @@ -156,9 +156,6 @@ extern void SMC669_Init(int); /* es1888.c */ extern void es1888_init(void); -/* ns87312.c */ -extern void ns87312_enable_ide(long ide_base); - /* ../lib/fpreg.c */ extern void alpha_write_fp_reg (unsigned long reg, unsigned long val); extern unsigned long alpha_read_fp_reg (unsigned long reg); diff --git a/arch/alpha/kernel/sys_cabriolet.c b/arch/alpha/kernel/sys_cabriolet.c index affd0f3..14c8898 100644 --- a/arch/alpha/kernel/sys_cabriolet.c +++ b/arch/alpha/kernel/sys_cabriolet.c @@ -33,7 +33,7 @@ #include "irq_impl.h" #include "pci_impl.h" #include "machvec_impl.h" - +#include "pc873xx.h" /* Note mask bit is true for DISABLED irqs. */ static unsigned long cached_irq_mask = ~0UL; @@ -236,17 +236,30 @@ cabriolet_map_irq(struct pci_dev *dev, u8 slot, u8 pin) } static inline void __init +cabriolet_enable_ide(void) +{ + if (pc873xx_probe() == -1) { + printk(KERN_ERR "Probing for PC873xx Super IO chip failed.\n"); + } else { + printk(KERN_INFO "Found %s Super IO chip at 0x%x\n", + pc873xx_get_model(), pc873xx_get_base()); + + pc873xx_enable_ide(); + } +} + +static inline void __init cabriolet_init_pci(void) { common_init_pci(); - ns87312_enable_ide(0x398); + cabriolet_enable_ide(); } static inline void __init cia_cab_init_pci(void) { cia_init_pci(); - ns87312_enable_ide(0x398); + cabriolet_enable_ide(); } /* diff --git a/arch/alpha/kernel/sys_takara.c b/arch/alpha/kernel/sys_takara.c index 2304648..4da596b 100644 --- a/arch/alpha/kernel/sys_takara.c +++ b/arch/alpha/kernel/sys_takara.c @@ -29,7 +29,7 @@ #include "irq_impl.h" #include "pci_impl.h" #include "machvec_impl.h" - +#include "pc873xx.h" /* Note mask bit is true for DISABLED irqs. */ static unsigned long cached_irq_mask[2] = { -1, -1 }; @@ -264,7 +264,14 @@ takara_init_pci(void) alpha_mv.pci_map_irq = takara_map_irq_srm; cia_init_pci(); - ns87312_enable_ide(0x26e); + + if (pc873xx_probe() == -1) { + printk(KERN_ERR "Probing for PC873xx Super IO chip failed.\n"); + } else { + printk(KERN_INFO "Found %s Super IO chip at 0x%x\n", + pc873xx_get_model(), pc873xx_get_base()); + pc873xx_enable_ide(); + } } -- cgit v0.10.2 From 7b598cdd03e35a4361f4ff7ebc630aa508c35be6 Mon Sep 17 00:00:00 2001 From: Michael Cree Date: Tue, 31 Aug 2010 22:46:04 -0400 Subject: alpha: convert perf_event to use local_t Updates the Alpha perf_event code to match the changes recently made to the core perf_event code in commit e78505958cf123048fb48cb56b79cebb8edd15fb. Signed-off-by: Michael Cree Signed-off-by: Matt Turner diff --git a/arch/alpha/kernel/perf_event.c b/arch/alpha/kernel/perf_event.c index 51c39fa..85d8e4f 100644 --- a/arch/alpha/kernel/perf_event.c +++ b/arch/alpha/kernel/perf_event.c @@ -241,20 +241,20 @@ static inline unsigned long alpha_read_pmc(int idx) static int alpha_perf_event_set_period(struct perf_event *event, struct hw_perf_event *hwc, int idx) { - long left = atomic64_read(&hwc->period_left); + long left = local64_read(&hwc->period_left); long period = hwc->sample_period; int ret = 0; if (unlikely(left <= -period)) { left = period; - atomic64_set(&hwc->period_left, left); + local64_set(&hwc->period_left, left); hwc->last_period = period; ret = 1; } if (unlikely(left <= 0)) { left += period; - atomic64_set(&hwc->period_left, left); + local64_set(&hwc->period_left, left); hwc->last_period = period; ret = 1; } @@ -269,7 +269,7 @@ static int alpha_perf_event_set_period(struct perf_event *event, if (left > (long)alpha_pmu->pmc_max_period[idx]) left = alpha_pmu->pmc_max_period[idx]; - atomic64_set(&hwc->prev_count, (unsigned long)(-left)); + local64_set(&hwc->prev_count, (unsigned long)(-left)); alpha_write_pmc(idx, (unsigned long)(-left)); @@ -300,10 +300,10 @@ static unsigned long alpha_perf_event_update(struct perf_event *event, long delta; again: - prev_raw_count = atomic64_read(&hwc->prev_count); + prev_raw_count = local64_read(&hwc->prev_count); new_raw_count = alpha_read_pmc(idx); - if (atomic64_cmpxchg(&hwc->prev_count, prev_raw_count, + if (local64_cmpxchg(&hwc->prev_count, prev_raw_count, new_raw_count) != prev_raw_count) goto again; @@ -316,8 +316,8 @@ again: delta += alpha_pmu->pmc_max_period[idx] + 1; } - atomic64_add(delta, &event->count); - atomic64_sub(delta, &hwc->period_left); + local64_add(delta, &event->count); + local64_sub(delta, &hwc->period_left); return new_raw_count; } @@ -636,7 +636,7 @@ static int __hw_perf_event_init(struct perf_event *event) if (!hwc->sample_period) { hwc->sample_period = alpha_pmu->pmc_max_period[0]; hwc->last_period = hwc->sample_period; - atomic64_set(&hwc->period_left, hwc->sample_period); + local64_set(&hwc->period_left, hwc->sample_period); } return 0; -- cgit v0.10.2 From 3e073367a57d41e506f20aebb98e308387ce3090 Mon Sep 17 00:00:00 2001 From: Michael Cree Date: Wed, 1 Sep 2010 11:25:17 -0400 Subject: alpha: Fix printk format errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When compiling alpha generic build get errors such as: arch/alpha/kernel/err_marvel.c: In function ‘marvel_print_err_cyc’: arch/alpha/kernel/err_marvel.c:119: error: format ‘%ld’ expects type ‘long int’, but argument 6 has type ‘u64’ Replaced a number of %ld format specifiers with %lld since u64 is unsigned long long. Signed-off-by: Michael Cree Signed-off-by: Matt Turner diff --git a/arch/alpha/kernel/err_marvel.c b/arch/alpha/kernel/err_marvel.c index 52a79df..5c905aa 100644 --- a/arch/alpha/kernel/err_marvel.c +++ b/arch/alpha/kernel/err_marvel.c @@ -109,7 +109,7 @@ marvel_print_err_cyc(u64 err_cyc) #define IO7__ERR_CYC__CYCLE__M (0x7) printk("%s Packet In Error: %s\n" - "%s Error in %s, cycle %ld%s%s\n", + "%s Error in %s, cycle %lld%s%s\n", err_print_prefix, packet_desc[EXTRACT(err_cyc, IO7__ERR_CYC__PACKET)], err_print_prefix, @@ -313,7 +313,7 @@ marvel_print_po7_ugbge_sym(u64 ugbge_sym) } printk("%s Up Hose Garbage Symptom:\n" - "%s Source Port: %ld - Dest PID: %ld - OpCode: %s\n", + "%s Source Port: %lld - Dest PID: %lld - OpCode: %s\n", err_print_prefix, err_print_prefix, EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_SRC_PORT), @@ -552,7 +552,7 @@ marvel_print_pox_spl_cmplt(u64 spl_cmplt) #define IO7__POX_SPLCMPLT__REM_BYTE_COUNT__M (0xfff) printk("%s Split Completion Error:\n" - "%s Source (Bus:Dev:Func): %ld:%ld:%ld\n", + "%s Source (Bus:Dev:Func): %lld:%lld:%lld\n", err_print_prefix, err_print_prefix, EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__SOURCE_BUS), -- cgit v0.10.2 From aa8a9e25c5e865de85410be4e9269b552974f7a2 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Wed, 1 Sep 2010 13:10:53 -0700 Subject: MAINTAINERS: Add ehea driver as Supported This change just add the IBM eHEA 10Gb network drivers as supported. Signed-off-by: Breno Leitao Signed-off-by: David S. Miller diff --git a/MAINTAINERS b/MAINTAINERS index 8e85429..db6b351 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2171,6 +2171,12 @@ L: linux-rdma@vger.kernel.org S: Supported F: drivers/infiniband/hw/ehca/ +EHEA (IBM pSeries eHEA 10Gb ethernet adapter) DRIVER +M: Breno Leitao +L: netdev@vger.kernel.org +S: Maintained +F: drivers/net/ehea/ + EMBEDDED LINUX M: Paul Gortmaker M: Matt Mackall -- cgit v0.10.2 From 78b620ce9e168d08ecfac2f4bb056c511b0601ec Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 31 Aug 2010 02:05:57 +0000 Subject: vhost: stop worker only if created Its currently illegal to call kthread_stop(NULL) Reported-by: Ingo Molnar Signed-off-by: Eric Dumazet Acked-by: Tejun Heo Signed-off-by: David S. Miller diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index e05557d..4b99117 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -323,7 +323,10 @@ void vhost_dev_cleanup(struct vhost_dev *dev) dev->mm = NULL; WARN_ON(!list_empty(&dev->work_list)); - kthread_stop(dev->worker); + if (dev->worker) { + kthread_stop(dev->worker); + dev->worker = NULL; + } } static int log_access_ok(void __user *log_base, u64 addr, unsigned long sz) -- cgit v0.10.2 From 0f04cfd098fb81fded74e78ea1a1b86cc6c6c31e Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Tue, 31 Aug 2010 13:21:42 +0000 Subject: net sched: fix kernel leak in act_police While reviewing commit 1c40be12f7d8ca1d387510d39787b12e512a7ce8, I audited other users of tc_action_ops->dump for information leaks. That commit covered almost all of them but act_police still had a leak. opt.limit and opt.capab aren't zeroed out before the structure is passed out. This patch uses the C99 initializers to zero everything unused out. Signed-off-by: Jeff Mahoney Acked-by: Jeff Mahoney Signed-off-by: David S. Miller diff --git a/net/sched/act_police.c b/net/sched/act_police.c index 537a487..7ebf743 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c @@ -350,22 +350,19 @@ tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) { unsigned char *b = skb_tail_pointer(skb); struct tcf_police *police = a->priv; - struct tc_police opt; - - opt.index = police->tcf_index; - opt.action = police->tcf_action; - opt.mtu = police->tcfp_mtu; - opt.burst = police->tcfp_burst; - opt.refcnt = police->tcf_refcnt - ref; - opt.bindcnt = police->tcf_bindcnt - bind; + struct tc_police opt = { + .index = police->tcf_index, + .action = police->tcf_action, + .mtu = police->tcfp_mtu, + .burst = police->tcfp_burst, + .refcnt = police->tcf_refcnt - ref, + .bindcnt = police->tcf_bindcnt - bind, + }; + if (police->tcfp_R_tab) opt.rate = police->tcfp_R_tab->rate; - else - memset(&opt.rate, 0, sizeof(opt.rate)); if (police->tcfp_P_tab) opt.peakrate = police->tcfp_P_tab->rate; - else - memset(&opt.peakrate, 0, sizeof(opt.peakrate)); NLA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt); if (police->tcfp_result) NLA_PUT_U32(skb, TCA_POLICE_RESULT, police->tcfp_result); -- cgit v0.10.2 From 9c01ae58d4fee39e2af5b1379ee5431dd585cf62 Mon Sep 17 00:00:00 2001 From: Denis Kirjanov Date: Sun, 29 Aug 2010 21:21:38 +0000 Subject: pxa168_eth: fix a mdiobus leak mdiobus resources must be released on exit Signed-off-by: Denis Kirjanov Acked-by: Dan Carpenter Signed-off-by: David S. Miller diff --git a/drivers/net/pxa168_eth.c b/drivers/net/pxa168_eth.c index 410ea0a..85eddda 100644 --- a/drivers/net/pxa168_eth.c +++ b/drivers/net/pxa168_eth.c @@ -1606,6 +1606,8 @@ static int pxa168_eth_remove(struct platform_device *pdev) iounmap(pep->base); pep->base = NULL; + mdiobus_unregister(pep->smi_bus); + mdiobus_free(pep->smi_bus); unregister_netdev(dev); flush_scheduled_work(); free_netdev(dev); -- cgit v0.10.2 From 3b2eb6131e2f6ff646abb0fc69648179b8b70216 Mon Sep 17 00:00:00 2001 From: Michal Soltys Date: Mon, 30 Aug 2010 11:34:10 +0000 Subject: net/sched/sch_hfsc.c: initialize parent's cl_cfmin properly in init_vf() This patch fixes init_vf() function, so on each new backlog period parent's cl_cfmin is properly updated (including further propgation towards the root), even if the activated leaf has no upperlimit curve defined. Signed-off-by: Michal Soltys Signed-off-by: David S. Miller diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index abd904b..4749609 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -761,8 +761,8 @@ init_vf(struct hfsc_class *cl, unsigned int len) if (f != cl->cl_f) { cl->cl_f = f; cftree_update(cl); - update_cfmin(cl->cl_parent); } + update_cfmin(cl->cl_parent); } } -- cgit v0.10.2 From 928497f0209027ccd649480a38a499fab9c3f6f6 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Tue, 31 Aug 2010 05:54:00 +0000 Subject: xfrm_user: avoid a warning with some compiler Attached is a small patch to remove a warning ("warning: ISO C90 forbids mixed declarations and code" with gcc 4.3.2). Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index b14ed4b..8bae6b2 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1801,7 +1801,7 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, struct xfrm_user_expire *ue = nlmsg_data(nlh); struct xfrm_usersa_info *p = &ue->state; struct xfrm_mark m; - u32 mark = xfrm_mark_get(attrs, &m);; + u32 mark = xfrm_mark_get(attrs, &m); x = xfrm_state_lookup(net, mark, &p->id.daddr, p->id.spi, p->id.proto, p->family); -- cgit v0.10.2 From 750e9fad8c7f44e0005ffb7195f72dd76978c2cf Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Tue, 31 Aug 2010 05:50:43 +0000 Subject: ipv4: minor fix about RPF in help of Kconfig Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 7c3a7d1..571f895 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -46,7 +46,7 @@ config IP_ADVANCED_ROUTER rp_filter on use: echo 1 > /proc/sys/net/ipv4/conf//rp_filter - and + or echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter Note that some distributions enable it in startup scripts. -- cgit v0.10.2 From de6be6c1f77798c4da38301693d33aff1cd76e84 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 30 Aug 2010 07:51:17 +0000 Subject: sky2: don't do GRO on second port There's something very important I forgot to tell you. What? Don't cross the GRO streams. Why? It would be bad. I'm fuzzy on the whole good/bad thing. What do you mean, "bad"? Try to imagine all the Internet as you know it stopping instantaneously and every bit in every packet swapping at the speed of light. Total packet reordering. Right. That's bad. Okay. All right. Important safety tip. Thanks, Hubert The simplest way to stop this is just avoid doing GRO on the second port. Very few Marvell boards support two ports per ring, and GRO is just an optimization. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 194e5cf..a6ff113 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2520,24 +2520,27 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) } } -static inline void sky2_skb_rx(const struct sky2_port *sky2, +static inline void sky2_skb_rx(struct napi_struct *napi, + const struct sky2_port *sky2, u32 status, struct sk_buff *skb) { #ifdef SKY2_VLAN_TAG_USED - u16 vlan_tag = be16_to_cpu(sky2->rx_tag); if (sky2->vlgrp && (status & GMR_FS_VLAN)) { - if (skb->ip_summed == CHECKSUM_NONE) + u16 vlan_tag = be16_to_cpu(sky2->rx_tag); + + if (skb->ip_summed == CHECKSUM_NONE || + sky2->netdev != napi->dev) vlan_hwaccel_receive_skb(skb, sky2->vlgrp, vlan_tag); else - vlan_gro_receive(&sky2->hw->napi, sky2->vlgrp, - vlan_tag, skb); + vlan_gro_receive(napi, sky2->vlgrp, vlan_tag, skb); return; } #endif - if (skb->ip_summed == CHECKSUM_NONE) + if (skb->ip_summed == CHECKSUM_NONE || + sky2->netdev != napi->dev) netif_receive_skb(skb); else - napi_gro_receive(&sky2->hw->napi, skb); + napi_gro_receive(napi, skb); } static inline void sky2_rx_done(struct sky2_hw *hw, unsigned port, @@ -2638,7 +2641,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) skb->protocol = eth_type_trans(skb, dev); - sky2_skb_rx(sky2, status, skb); + sky2_skb_rx(&hw->napi, sky2, status, skb); /* Stop after net poll weight */ if (++work_done >= to_do) -- cgit v0.10.2 From a9d8fb4d09ec8823045f44ebcde53a563fce2feb Mon Sep 17 00:00:00 2001 From: Erik Gilling Date: Fri, 27 Aug 2010 12:57:39 -0700 Subject: [ARM] tegra: Add ZRELADDR default for ARCH_TEGRA fixes the warning: .config:369:warning: symbol value '' invalid for ZRELADDR and the prompt for ZRELADDR on make Signed-off-by: Erik Gilling diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index a7ed21f..16bc8eb 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1601,6 +1601,7 @@ config ZRELADDR ARCH_ORION5X ||\ ARCH_SPEAR3XX ||\ ARCH_SPEAR6XX ||\ + ARCH_TEGRA ||\ ARCH_U8500 ||\ ARCH_VERSATILE ||\ ARCH_W90X900 -- cgit v0.10.2 From 93f68f1ef787d97ab688f78a01f446e85bb9a496 Mon Sep 17 00:00:00 2001 From: Nathan Fontenot Date: Wed, 18 Aug 2010 09:58:46 +0000 Subject: powerpc/pseries: Correct rtas_data_buf locking in dlpar code The dlpar code can cause a deadlock to occur when making the RTAS configure-connector call. This occurs because we make kmalloc calls, which can block, while parsing the rtas_data_buf and holding the rtas_data_buf_lock. This an cause issues if someone else attempts to grab the rtas_data_bug_lock. This patch alleviates this issue by copying the contents of the rtas_data_buf to a local buffer before parsing. This allows us to only hold the rtas_data_buf_lock around the RTAS configure-connector calls. Signed-off-by: Nathan Fontenot Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 227c1c3..72d8054 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -129,20 +129,35 @@ struct device_node *dlpar_configure_connector(u32 drc_index) struct property *property; struct property *last_property = NULL; struct cc_workarea *ccwa; + char *data_buf; int cc_token; - int rc; + int rc = -1; cc_token = rtas_token("ibm,configure-connector"); if (cc_token == RTAS_UNKNOWN_SERVICE) return NULL; - spin_lock(&rtas_data_buf_lock); - ccwa = (struct cc_workarea *)&rtas_data_buf[0]; + data_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL); + if (!data_buf) + return NULL; + + ccwa = (struct cc_workarea *)&data_buf[0]; ccwa->drc_index = drc_index; ccwa->zero = 0; - rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL); - while (rc) { + do { + /* Since we release the rtas_data_buf lock between configure + * connector calls we want to re-populate the rtas_data_buffer + * with the contents of the previous call. + */ + spin_lock(&rtas_data_buf_lock); + + memcpy(rtas_data_buf, data_buf, RTAS_DATA_BUF_SIZE); + rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL); + memcpy(data_buf, rtas_data_buf, RTAS_DATA_BUF_SIZE); + + spin_unlock(&rtas_data_buf_lock); + switch (rc) { case NEXT_SIBLING: dn = dlpar_parse_cc_node(ccwa); @@ -197,18 +212,19 @@ struct device_node *dlpar_configure_connector(u32 drc_index) "returned from configure-connector\n", rc); goto cc_error; } + } while (rc); - rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL); +cc_error: + kfree(data_buf); + + if (rc) { + if (first_dn) + dlpar_free_cc_nodes(first_dn); + + return NULL; } - spin_unlock(&rtas_data_buf_lock); return first_dn; - -cc_error: - if (first_dn) - dlpar_free_cc_nodes(first_dn); - spin_unlock(&rtas_data_buf_lock); - return NULL; } static struct device_node *derive_parent(const char *path) -- cgit v0.10.2 From 24cd804d1dc60a74c53da983094df3516500c276 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 30 Aug 2010 14:15:33 +0000 Subject: 3c59x: Remove incorrect locking; correct documented lock hierarchy vortex_ioctl() was grabbing vortex_private::lock around its call to generic_mii_ioctl(). This is no longer necessary since there are more specific locks which the mdio_{read,write}() functions will obtain. Worse, those functions do not save and restore IRQ flags when locking the MII state, so interrupts will be enabled when generic_mii_ioctl() returns. Since there is currently no need for any function to call mdio_{read,write}() while holding another spinlock, do not change them to save and restore IRQ flags but remove the specification of ordering between vortex_private::lock and vortex_private::mii_lock. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index c685a55..a045559 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -647,7 +647,7 @@ struct vortex_private { u16 io_size; /* Size of PCI region (for release_region) */ /* Serialises access to hardware other than MII and variables below. - * The lock hierarchy is rtnl_lock > lock > mii_lock > window_lock. */ + * The lock hierarchy is rtnl_lock > {lock, mii_lock} > window_lock. */ spinlock_t lock; spinlock_t mii_lock; /* Serialises access to MII */ @@ -2984,7 +2984,6 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { int err; struct vortex_private *vp = netdev_priv(dev); - unsigned long flags; pci_power_t state = 0; if(VORTEX_PCI(vp)) @@ -2994,9 +2993,7 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) if(state != 0) pci_set_power_state(VORTEX_PCI(vp), PCI_D0); - spin_lock_irqsave(&vp->lock, flags); err = generic_mii_ioctl(&vp->mii, if_mii(rq), cmd, NULL); - spin_unlock_irqrestore(&vp->lock, flags); if(state != 0) pci_set_power_state(VORTEX_PCI(vp), state); -- cgit v0.10.2 From 0b3b4fea0a50cc669acc8634806c2ecd6474f68c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 1 Sep 2010 11:24:42 -0400 Subject: drm/radeon/kms: remove useless clock code This code was originally for forcing some clocks on certain asics. However, this code was later moved to asic specific functions for all of the affected asics. The only users of the original code at this point were r600, rv770, and evergreen and the code was not relevant for those asics. So, remove it. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 957d506..fe31b0d 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -2054,11 +2054,6 @@ int evergreen_resume(struct radeon_device *rdev) */ /* post card */ atom_asic_init(rdev->mode_info.atom_context); - /* Initialize clocks */ - r = radeon_clocks_init(rdev); - if (r) { - return r; - } r = evergreen_startup(rdev); if (r) { @@ -2164,9 +2159,6 @@ int evergreen_init(struct radeon_device *rdev) radeon_surface_init(rdev); /* Initialize clocks */ radeon_get_clock_info(rdev->ddev); - r = radeon_clocks_init(rdev); - if (r) - return r; /* Fence driver */ r = radeon_fence_driver_init(rdev); if (r) @@ -2236,7 +2228,6 @@ void evergreen_fini(struct radeon_device *rdev) evergreen_pcie_gart_fini(rdev); radeon_gem_fini(rdev); radeon_fence_driver_fini(rdev); - radeon_clocks_fini(rdev); radeon_agp_fini(rdev); radeon_bo_fini(rdev); radeon_atombios_fini(rdev); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index aee8376..04f134d 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2489,11 +2489,6 @@ int r600_resume(struct radeon_device *rdev) */ /* post card */ atom_asic_init(rdev->mode_info.atom_context); - /* Initialize clocks */ - r = radeon_clocks_init(rdev); - if (r) { - return r; - } r = r600_startup(rdev); if (r) { @@ -2586,9 +2581,6 @@ int r600_init(struct radeon_device *rdev) radeon_surface_init(rdev); /* Initialize clocks */ radeon_get_clock_info(rdev->ddev); - r = radeon_clocks_init(rdev); - if (r) - return r; /* Fence driver */ r = radeon_fence_driver_init(rdev); if (r) @@ -2663,7 +2655,6 @@ void r600_fini(struct radeon_device *rdev) radeon_agp_fini(rdev); radeon_gem_fini(rdev); radeon_fence_driver_fini(rdev); - radeon_clocks_fini(rdev); radeon_bo_fini(rdev); radeon_atombios_fini(rdev); kfree(rdev->bios); diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index e90d9e3..a168d64 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1339,8 +1339,6 @@ extern bool radeon_card_posted(struct radeon_device *rdev); extern void radeon_update_bandwidth_info(struct radeon_device *rdev); extern void radeon_update_display_priority(struct radeon_device *rdev); extern bool radeon_boot_test_post_card(struct radeon_device *rdev); -extern int radeon_clocks_init(struct radeon_device *rdev); -extern void radeon_clocks_fini(struct radeon_device *rdev); extern void radeon_scratch_init(struct radeon_device *rdev); extern void radeon_surface_init(struct radeon_device *rdev); extern int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data); diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index a21bf88..25e1dd1 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -858,21 +858,3 @@ int radeon_asic_init(struct radeon_device *rdev) return 0; } -/* - * Wrapper around modesetting bits. Move to radeon_clocks.c? - */ -int radeon_clocks_init(struct radeon_device *rdev) -{ - int r; - - r = radeon_static_clocks_init(rdev->ddev); - if (r) { - return r; - } - DRM_INFO("Clocks initialized !\n"); - return 0; -} - -void radeon_clocks_fini(struct radeon_device *rdev) -{ -} diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c index 690d8907..5249af8 100644 --- a/drivers/gpu/drm/radeon/radeon_clocks.c +++ b/drivers/gpu/drm/radeon/radeon_clocks.c @@ -905,53 +905,3 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) } } -static void radeon_apply_clock_quirks(struct radeon_device *rdev) -{ - uint32_t tmp; - - /* XXX make sure engine is idle */ - - if (rdev->family < CHIP_RS600) { - tmp = RREG32_PLL(RADEON_SCLK_CNTL); - if (ASIC_IS_R300(rdev) || ASIC_IS_RV100(rdev)) - tmp |= RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_VIP; - if ((rdev->family == CHIP_RV250) - || (rdev->family == CHIP_RV280)) - tmp |= - RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_DISP2; - if ((rdev->family == CHIP_RV350) - || (rdev->family == CHIP_RV380)) - tmp |= R300_SCLK_FORCE_VAP; - if (rdev->family == CHIP_R420) - tmp |= R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX; - WREG32_PLL(RADEON_SCLK_CNTL, tmp); - } else if (rdev->family < CHIP_R600) { - tmp = RREG32_PLL(AVIVO_CP_DYN_CNTL); - tmp |= AVIVO_CP_FORCEON; - WREG32_PLL(AVIVO_CP_DYN_CNTL, tmp); - - tmp = RREG32_PLL(AVIVO_E2_DYN_CNTL); - tmp |= AVIVO_E2_FORCEON; - WREG32_PLL(AVIVO_E2_DYN_CNTL, tmp); - - tmp = RREG32_PLL(AVIVO_IDCT_DYN_CNTL); - tmp |= AVIVO_IDCT_FORCEON; - WREG32_PLL(AVIVO_IDCT_DYN_CNTL, tmp); - } -} - -int radeon_static_clocks_init(struct drm_device *dev) -{ - struct radeon_device *rdev = dev->dev_private; - - /* XXX make sure engine is idle */ - - if (radeon_dynclks != -1) { - if (radeon_dynclks) { - if (rdev->asic->set_clock_gating) - radeon_set_clock_gating(rdev, 1); - } - } - radeon_apply_clock_quirks(rdev); - return 0; -} diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 8f93e2b..efbe975 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -600,7 +600,6 @@ extern bool radeon_get_atom_connector_info_from_supported_devices_table(struct d void radeon_enc_destroy(struct drm_encoder *encoder); void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj); void radeon_combios_asic_init(struct drm_device *dev); -extern int radeon_static_clocks_init(struct drm_device *dev); bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index a84e386..bfa59db 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -1074,11 +1074,6 @@ int rv770_resume(struct radeon_device *rdev) */ /* post card */ atom_asic_init(rdev->mode_info.atom_context); - /* Initialize clocks */ - r = radeon_clocks_init(rdev); - if (r) { - return r; - } r = rv770_startup(rdev); if (r) { @@ -1169,9 +1164,6 @@ int rv770_init(struct radeon_device *rdev) radeon_surface_init(rdev); /* Initialize clocks */ radeon_get_clock_info(rdev->ddev); - r = radeon_clocks_init(rdev); - if (r) - return r; /* Fence driver */ r = radeon_fence_driver_init(rdev); if (r) @@ -1249,7 +1241,6 @@ void rv770_fini(struct radeon_device *rdev) rv770_vram_scratch_fini(rdev); radeon_gem_fini(rdev); radeon_fence_driver_fini(rdev); - radeon_clocks_fini(rdev); radeon_agp_fini(rdev); radeon_bo_fini(rdev); radeon_atombios_fini(rdev); -- cgit v0.10.2 From 0d9958b18e10d7426d94cc3dd024920a40db3ee2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 1 Sep 2010 12:03:37 -0400 Subject: drm/radeon/kms: force legacy pll algo for RV515 LVDS There has been periodic evidence that LVDS, on at least some panels, prefers the dividers selected by the legacy pll algo. This patch forces the use of the legacy pll algo on RV515 LVDS panels. The old behavior (new pll algo) can be selected by setting the new_pll module parameter to 1. Signed-off-by: Alex Deucher Cc: stable@kernel.org Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 577239a..977f5c2 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -534,6 +534,20 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, pll->algo = PLL_ALGO_LEGACY; pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; } + /* There is some evidence (often anecdotal) that RV515 LVDS + * (on some boards at least) prefers the legacy algo. I'm not + * sure whether this should handled generically or on a + * case-by-case quirk basis. Both algos should work fine in the + * majority of cases. + */ + if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) && + (rdev->family == CHIP_RV515)) { + /* allow the user to overrride just in case */ + if (radeon_new_pll == 1) + pll->algo = PLL_ALGO_NEW; + else + pll->algo = PLL_ALGO_LEGACY; + } } else { if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; -- cgit v0.10.2 From cf4c12f9a2289e3679722590e1226ae8deb14385 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 1 Sep 2010 17:15:06 -0400 Subject: drm/radeon/kms: fix tv module parameter The tv parameter was added to disable the tv-out connector, however, it caused a crash if it was set to 0 due to drm_connector_init not getting called. If tv=0, don't attempt to add the connector. Might fix: https://bugzilla.kernel.org/show_bug.cgi?id=17241 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 1a5ee39..a9dd784 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -1051,10 +1051,16 @@ radeon_add_atom_connector(struct drm_device *dev, uint32_t subpixel_order = SubPixelNone; bool shared_ddc = false; - /* fixme - tv/cv/din */ if (connector_type == DRM_MODE_CONNECTOR_Unknown) return; + /* if the user selected tv=0 don't try and add the connector */ + if (((connector_type == DRM_MODE_CONNECTOR_SVIDEO) || + (connector_type == DRM_MODE_CONNECTOR_Composite) || + (connector_type == DRM_MODE_CONNECTOR_9PinDIN)) && + (radeon_tv == 0)) + return; + /* see if we already added it */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { radeon_connector = to_radeon_connector(connector); @@ -1209,19 +1215,17 @@ radeon_add_atom_connector(struct drm_device *dev, case DRM_MODE_CONNECTOR_SVIDEO: case DRM_MODE_CONNECTOR_Composite: case DRM_MODE_CONNECTOR_9PinDIN: - if (radeon_tv == 1) { - drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); - drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); - radeon_connector->dac_load_detect = true; - drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.load_detect_property, - 1); - drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.tv_std_property, - radeon_atombios_get_tv_info(rdev)); - /* no HPD on analog connectors */ - radeon_connector->hpd.hpd = RADEON_HPD_NONE; - } + drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); + radeon_connector->dac_load_detect = true; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.load_detect_property, + 1); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.tv_std_property, + radeon_atombios_get_tv_info(rdev)); + /* no HPD on analog connectors */ + radeon_connector->hpd.hpd = RADEON_HPD_NONE; break; case DRM_MODE_CONNECTOR_LVDS: radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); @@ -1272,10 +1276,16 @@ radeon_add_legacy_connector(struct drm_device *dev, struct radeon_connector *radeon_connector; uint32_t subpixel_order = SubPixelNone; - /* fixme - tv/cv/din */ if (connector_type == DRM_MODE_CONNECTOR_Unknown) return; + /* if the user selected tv=0 don't try and add the connector */ + if (((connector_type == DRM_MODE_CONNECTOR_SVIDEO) || + (connector_type == DRM_MODE_CONNECTOR_Composite) || + (connector_type == DRM_MODE_CONNECTOR_9PinDIN)) && + (radeon_tv == 0)) + return; + /* see if we already added it */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { radeon_connector = to_radeon_connector(connector); @@ -1347,26 +1357,24 @@ radeon_add_legacy_connector(struct drm_device *dev, case DRM_MODE_CONNECTOR_SVIDEO: case DRM_MODE_CONNECTOR_Composite: case DRM_MODE_CONNECTOR_9PinDIN: - if (radeon_tv == 1) { - drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); - drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); - radeon_connector->dac_load_detect = true; - /* RS400,RC410,RS480 chipset seems to report a lot - * of false positive on load detect, we haven't yet - * found a way to make load detect reliable on those - * chipset, thus just disable it for TV. - */ - if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480) - radeon_connector->dac_load_detect = false; - drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.load_detect_property, - radeon_connector->dac_load_detect); - drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.tv_std_property, - radeon_combios_get_tv_info(rdev)); - /* no HPD on analog connectors */ - radeon_connector->hpd.hpd = RADEON_HPD_NONE; - } + drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); + radeon_connector->dac_load_detect = true; + /* RS400,RC410,RS480 chipset seems to report a lot + * of false positive on load detect, we haven't yet + * found a way to make load detect reliable on those + * chipset, thus just disable it for TV. + */ + if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480) + radeon_connector->dac_load_detect = false; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.load_detect_property, + radeon_connector->dac_load_detect); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.tv_std_property, + radeon_combios_get_tv_info(rdev)); + /* no HPD on analog connectors */ + radeon_connector->hpd.hpd = RADEON_HPD_NONE; break; case DRM_MODE_CONNECTOR_LVDS: drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); -- cgit v0.10.2 From 95347871865ca5093c7e87a223274f7c3b5eccda Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 1 Sep 2010 17:20:42 -0400 Subject: drm/radeon/kms: properly set crtc high base on r7xx Signed-off-by: Alex Deucher Cc: stable@kernel.org Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 977f5c2..71b3150 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1070,11 +1070,11 @@ static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y, if (rdev->family >= CHIP_RV770) { if (radeon_crtc->crtc_id) { - WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0); - WREG32(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0); + WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); + WREG32(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); } else { - WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0); - WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0); + WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); + WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); } } WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, -- cgit v0.10.2 From 87f94b4e91dc042620c527f3c30c37e5127ef757 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 1 Sep 2010 18:06:39 -0700 Subject: bridge: Clear INET control block of SKBs passed into ip_fragment(). In a similar vain to commit 17762060c25590bfddd68cc1131f28ec720f405f ("bridge: Clear IPCB before possible entry into IP stack") Any time we call into the IP stack we have to make sure the state there is as expected by the ipv4 code. With help from Eric Dumazet and Herbert Xu. Reported-by: Bandan Das Signed-off-by: David S. Miller diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 5ed00bd..137f232 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -761,9 +761,11 @@ static int br_nf_dev_queue_xmit(struct sk_buff *skb) { if (skb->nfct != NULL && skb->protocol == htons(ETH_P_IP) && skb->len + nf_bridge_mtu_reduction(skb) > skb->dev->mtu && - !skb_is_gso(skb)) + !skb_is_gso(skb)) { + /* BUG: Should really parse the IP options here. */ + memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); return ip_fragment(skb, br_dev_queue_push_xmit); - else + } else return br_dev_queue_push_xmit(skb); } #else -- cgit v0.10.2 From 3d3be4333fdf6faa080947b331a6a19bce1a4f57 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 1 Sep 2010 00:50:51 +0000 Subject: gro: fix different skb headrooms Packets entering GRO might have different headrooms, even for a given flow (because of implementation details in drivers, like copybreak). We cant force drivers to deliver packets with a fixed headroom. 1) fix skb_segment() skb_segment() makes the false assumption headrooms of fragments are same than the head. When CHECKSUM_PARTIAL is used, this can give csum_start errors, and crash later in skb_copy_and_csum_dev() 2) allocate a minimal skb for head of frag_list skb_gro_receive() uses netdev_alloc_skb(headroom + skb_gro_offset(p)) to allocate a fresh skb. This adds NET_SKB_PAD to a padding already provided by netdevice, depending on various things, like copybreak. Use alloc_skb() to allocate an exact padding, to reduce cache line needs: NET_SKB_PAD + NET_IP_ALIGN bugzilla : https://bugzilla.kernel.org/show_bug.cgi?id=16626 Many thanks to Plamen Petrov, testing many debugging patches ! With help of Jarek Poplawski. Reported-by: Plamen Petrov Signed-off-by: Eric Dumazet CC: Jarek Poplawski Signed-off-by: David S. Miller diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 3a2513f..26396ff 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2573,6 +2573,10 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) __copy_skb_header(nskb, skb); nskb->mac_len = skb->mac_len; + /* nskb and skb might have different headroom */ + if (nskb->ip_summed == CHECKSUM_PARTIAL) + nskb->csum_start += skb_headroom(nskb) - headroom; + skb_reset_mac_header(nskb); skb_set_network_header(nskb, skb->mac_len); nskb->transport_header = (nskb->network_header + @@ -2702,8 +2706,8 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) } else if (skb_gro_len(p) != pinfo->gso_size) return -E2BIG; - headroom = skb_headroom(p); - nskb = netdev_alloc_skb(p->dev, headroom + skb_gro_offset(p)); + headroom = NET_SKB_PAD + NET_IP_ALIGN; + nskb = alloc_skb(headroom + skb_gro_offset(p), GFP_ATOMIC); if (unlikely(!nskb)) return -ENOMEM; -- cgit v0.10.2 From ea39302b87b8d944d567ef29c0647c09da5743fa Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 27 Aug 2010 16:04:29 -0400 Subject: drm/radeon/kms/evergreen: work around bad data in some i2c tables The 7th entry in a lot of evergreen i2c gpio tables is partially zeroed. Fix the entry. Should fix the missing ddc entry in: https://bugs.freedesktop.org/show_bug.cgi?id=29255 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 61141981..ebae14c 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -85,6 +85,19 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev for (i = 0; i < num_indices; i++) { gpio = &i2c_info->asGPIO_Info[i]; + /* some evergreen boards have bad data for this entry */ + if (ASIC_IS_DCE4(rdev)) { + if ((i == 7) && + (gpio->usClkMaskRegisterIndex == 0x1936) && + (gpio->sucI2cId.ucAccess == 0)) { + gpio->sucI2cId.ucAccess = 0x97; + gpio->ucDataMaskShift = 8; + gpio->ucDataEnShift = 8; + gpio->ucDataY_Shift = 8; + gpio->ucDataA_Shift = 8; + } + } + if (gpio->sucI2cId.ucAccess == id) { i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; @@ -147,6 +160,20 @@ void radeon_atombios_i2c_init(struct radeon_device *rdev) for (i = 0; i < num_indices; i++) { gpio = &i2c_info->asGPIO_Info[i]; i2c.valid = false; + + /* some evergreen boards have bad data for this entry */ + if (ASIC_IS_DCE4(rdev)) { + if ((i == 7) && + (gpio->usClkMaskRegisterIndex == 0x1936) && + (gpio->sucI2cId.ucAccess == 0)) { + gpio->sucI2cId.ucAccess = 0x97; + gpio->ucDataMaskShift = 8; + gpio->ucDataEnShift = 8; + gpio->ucDataY_Shift = 8; + gpio->ucDataA_Shift = 8; + } + } + i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; -- cgit v0.10.2 From 9bc08a45fb117c696e4940cfa1208cb1cc7a2f25 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Thu, 2 Sep 2010 15:14:38 +1000 Subject: xfs: improve buffer cache hash scalability When doing large parallel file creates on a 16p machines, large amounts of time is being spent in _xfs_buf_find(). A system wide profile with perf top shows this: 1134740.00 19.3% _xfs_buf_find 733142.00 12.5% __ticket_spin_lock The problem is that the hash contains 45,000 buffers, and the hash table width is only 256 buffers. That means we've got around 200 buffers per chain, and searching it is quite expensive. The hash table size needs to increase. Secondly, every time we do a lookup, we promote the buffer we find to the head of the hash chain. This is causing cachelines to be dirtied and causes invalidation of cachelines across all CPUs that may have walked the hash chain recently. hence every walk of the hash chain is effectively a cold cache walk. Remove the promotion to avoid this invalidation. The results are: 1045043.00 21.2% __ticket_spin_lock 326184.00 6.6% _xfs_buf_find A 70% drop in the CPU usage when looking up buffers. Unfortunately that does not result in an increase in performance underthis workload as contention on the inode_lock soaks up most of the reduction in CPU usage. Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index ea79072..d72cf2b 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -440,12 +440,7 @@ _xfs_buf_find( ASSERT(btp == bp->b_target); if (bp->b_file_offset == range_base && bp->b_buffer_length == range_length) { - /* - * If we look at something, bring it to the - * front of the list for next time. - */ atomic_inc(&bp->b_hold); - list_move(&bp->b_hash_list, &hash->bh_list); goto found; } } @@ -1443,8 +1438,7 @@ xfs_alloc_bufhash( { unsigned int i; - btp->bt_hashshift = external ? 3 : 8; /* 8 or 256 buckets */ - btp->bt_hashmask = (1 << btp->bt_hashshift) - 1; + btp->bt_hashshift = external ? 3 : 12; /* 8 or 4096 buckets */ btp->bt_hash = kmem_zalloc_large((1 << btp->bt_hashshift) * sizeof(xfs_bufhash_t)); for (i = 0; i < (1 << btp->bt_hashshift); i++) { diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h index d072e5f..2a05614 100644 --- a/fs/xfs/linux-2.6/xfs_buf.h +++ b/fs/xfs/linux-2.6/xfs_buf.h @@ -137,7 +137,6 @@ typedef struct xfs_buftarg { size_t bt_smask; /* per device buffer hash table */ - uint bt_hashmask; uint bt_hashshift; xfs_bufhash_t *bt_hash; -- cgit v0.10.2 From 23963e54ce187ca6e907c83176c15508b0f6e60d Mon Sep 17 00:00:00 2001 From: Arkadiusz Mi?kiewicz Date: Thu, 26 Aug 2010 10:19:43 +0000 Subject: xfs: Disallow 32bit project quota id Currently on-disk structure is able to keep only 16bit project quota id, so disallow 32bit ones. This fixes a problem where parts of kernel structures holding project quota id are 32bit while parts (on-disk) are 16bit variables which causes project quota member files to be inaccessible for some operations (like mv/rm). Signed-off-by: Arkadiusz Mi?kiewicz Reviewed-by: Christoph Hellwig Signed-off-by: Alex Elder diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 237f5ff..4fec427 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c @@ -907,6 +907,13 @@ xfs_ioctl_setattr( return XFS_ERROR(EIO); /* + * Disallow 32bit project ids because on-disk structure + * is 16bit only. + */ + if ((mask & FSX_PROJID) && (fa->fsx_projid > (__uint16_t)-1)) + return XFS_ERROR(EINVAL); + + /* * If disk quotas is on, we make sure that the dquots do exist on disk, * before we start any other transactions. Trying to do this later * is messy. We don't care to take a readlock to look at the ids -- cgit v0.10.2 From 5e4e7573e1ec286120109e73bf54cff465488725 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 2 Sep 2010 09:39:09 -0700 Subject: Revert "sky2: don't do GRO on second port" This reverts commit de6be6c1f77798c4da38301693d33aff1cd76e84. After some discussion with Jarek Poplawski and Eric Dumazet, we've decided that this change is incorrect. Signed-off-by: David S. Miller diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index a6ff113..194e5cf 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2520,27 +2520,24 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) } } -static inline void sky2_skb_rx(struct napi_struct *napi, - const struct sky2_port *sky2, +static inline void sky2_skb_rx(const struct sky2_port *sky2, u32 status, struct sk_buff *skb) { #ifdef SKY2_VLAN_TAG_USED + u16 vlan_tag = be16_to_cpu(sky2->rx_tag); if (sky2->vlgrp && (status & GMR_FS_VLAN)) { - u16 vlan_tag = be16_to_cpu(sky2->rx_tag); - - if (skb->ip_summed == CHECKSUM_NONE || - sky2->netdev != napi->dev) + if (skb->ip_summed == CHECKSUM_NONE) vlan_hwaccel_receive_skb(skb, sky2->vlgrp, vlan_tag); else - vlan_gro_receive(napi, sky2->vlgrp, vlan_tag, skb); + vlan_gro_receive(&sky2->hw->napi, sky2->vlgrp, + vlan_tag, skb); return; } #endif - if (skb->ip_summed == CHECKSUM_NONE || - sky2->netdev != napi->dev) + if (skb->ip_summed == CHECKSUM_NONE) netif_receive_skb(skb); else - napi_gro_receive(napi, skb); + napi_gro_receive(&sky2->hw->napi, skb); } static inline void sky2_rx_done(struct sky2_hw *hw, unsigned port, @@ -2641,7 +2638,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) skb->protocol = eth_type_trans(skb, dev); - sky2_skb_rx(&hw->napi, sky2, status, skb); + sky2_skb_rx(sky2, status, skb); /* Stop after net poll weight */ if (++work_done >= to_do) -- cgit v0.10.2 From 7bcbf81a2296a8f71342445560dcbe16100b567c Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Wed, 1 Sep 2010 23:07:10 +0000 Subject: ipvs: avoid oops for passive FTP Fix Passive FTP problem in ip_vs_ftp: - Do not oops in nf_nat_set_seq_adjust (adjust_tcp_sequence) when iptable_nat module is not loaded Signed-off-by: Julian Anastasov Signed-off-by: Simon Horman Signed-off-by: David S. Miller diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c index f228a17..33b329b 100644 --- a/net/netfilter/ipvs/ip_vs_ftp.c +++ b/net/netfilter/ipvs/ip_vs_ftp.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -359,7 +360,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, buf_len = strlen(buf); ct = nf_ct_get(skb, &ctinfo); - if (ct && !nf_ct_is_untracked(ct)) { + if (ct && !nf_ct_is_untracked(ct) && nfct_nat(ct)) { /* If mangling fails this function will return 0 * which will cause the packet to be dropped. * Mangling can only fail under memory pressure, -- cgit v0.10.2 From 0b5d404e349c0236b11466c0a4785520c0be6982 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Thu, 2 Sep 2010 13:22:11 -0700 Subject: pkt_sched: Fix lockdep warning on est_tree_lock in gen_estimator This patch fixes a lockdep warning: [ 516.287584] ========================================================= [ 516.288386] [ INFO: possible irq lock inversion dependency detected ] [ 516.288386] 2.6.35b #7 [ 516.288386] --------------------------------------------------------- [ 516.288386] swapper/0 just changed the state of lock: [ 516.288386] (&qdisc_tx_lock){+.-...}, at: [] est_timer+0x62/0x1b4 [ 516.288386] but this lock took another, SOFTIRQ-unsafe lock in the past: [ 516.288386] (est_tree_lock){+.+...} [ 516.288386] [ 516.288386] and interrupts could create inverse lock ordering between them. ... So, est_tree_lock needs BH protection because it's taken by qdisc_tx_lock, which is used both in BH and process contexts. (Full warning with this patch at netdev, 02 Sep 2010.) Fixes commit: ae638c47dc040b8def16d05dc6acdd527628f231 ("pkt_sched: gen_estimator: add a new lock") Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index 9fbe7f7..6743146 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c @@ -232,7 +232,7 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats, est->last_packets = bstats->packets; est->avpps = rate_est->pps<<10; - spin_lock(&est_tree_lock); + spin_lock_bh(&est_tree_lock); if (!elist[idx].timer.function) { INIT_LIST_HEAD(&elist[idx].list); setup_timer(&elist[idx].timer, est_timer, idx); @@ -243,7 +243,7 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats, list_add_rcu(&est->list, &elist[idx].list); gen_add_node(est); - spin_unlock(&est_tree_lock); + spin_unlock_bh(&est_tree_lock); return 0; } @@ -270,7 +270,7 @@ void gen_kill_estimator(struct gnet_stats_basic_packed *bstats, { struct gen_estimator *e; - spin_lock(&est_tree_lock); + spin_lock_bh(&est_tree_lock); while ((e = gen_find_node(bstats, rate_est))) { rb_erase(&e->node, &est_root); @@ -281,7 +281,7 @@ void gen_kill_estimator(struct gnet_stats_basic_packed *bstats, list_del_rcu(&e->list); call_rcu(&e->e_rcu, __gen_kill_estimator); } - spin_unlock(&est_tree_lock); + spin_unlock_bh(&est_tree_lock); } EXPORT_SYMBOL(gen_kill_estimator); @@ -320,9 +320,9 @@ bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats, ASSERT_RTNL(); - spin_lock(&est_tree_lock); + spin_lock_bh(&est_tree_lock); res = gen_find_node(bstats, rate_est) != NULL; - spin_unlock(&est_tree_lock); + spin_unlock_bh(&est_tree_lock); return res; } -- cgit v0.10.2 From 3ba6462355c1c69dde58739a871d13bbb993e2e3 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Sat, 28 Aug 2010 17:56:33 +0200 Subject: drm/nouveau: Take fence spinlock before reading the last sequence. It fixes a race between the TTM delayed work queue and the GEM IOCTLs (fdo bug 29583) uncovered by the BKL removal. Signed-off-by: Francisco Jerez Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 6b208ff..87ac21e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -64,16 +64,17 @@ nouveau_fence_update(struct nouveau_channel *chan) struct nouveau_fence *fence; uint32_t sequence; + spin_lock(&chan->fence.lock); + if (USE_REFCNT) sequence = nvchan_rd32(chan, 0x48); else sequence = atomic_read(&chan->fence.last_sequence_irq); if (chan->fence.sequence_ack == sequence) - return; + goto out; chan->fence.sequence_ack = sequence; - spin_lock(&chan->fence.lock); list_for_each_safe(entry, tmp, &chan->fence.pending) { fence = list_entry(entry, struct nouveau_fence, entry); @@ -85,6 +86,7 @@ nouveau_fence_update(struct nouveau_channel *chan) if (sequence == chan->fence.sequence_ack) break; } +out: spin_unlock(&chan->fence.lock); } -- cgit v0.10.2 From 374c3af880ef260f36dfc968d9725494666dff31 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Sun, 29 Aug 2010 12:21:16 +0200 Subject: drm/nouveau: Don't take struct_mutex around the pushbuf IOCTL. We don't need it and it can lead to lock order inversions with respect to drm_global_mutex, potentially causing dead locks. Signed-off-by: Francisco Jerez Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 93711df..10cace9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -245,7 +245,7 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence) list_del(&nvbo->entry); nvbo->reserved_by = NULL; ttm_bo_unreserve(&nvbo->bo); - drm_gem_object_unreference(nvbo->gem); + drm_gem_object_unreference_unlocked(nvbo->gem); } } @@ -300,7 +300,7 @@ retry: validate_fini(op, NULL); if (ret == -EAGAIN) ret = ttm_bo_wait_unreserved(&nvbo->bo, false); - drm_gem_object_unreference(gem); + drm_gem_object_unreference_unlocked(gem); if (ret) { NV_ERROR(dev, "fail reserve\n"); return ret; @@ -616,8 +616,6 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, return PTR_ERR(bo); } - mutex_lock(&dev->struct_mutex); - /* Mark push buffers as being used on PFIFO, the validation code * will then make sure that if the pushbuf bo moves, that they * happen on the kernel channel, which will in turn cause a sync @@ -731,7 +729,6 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, out: validate_fini(&op, fence); nouveau_fence_unref((void**)&fence); - mutex_unlock(&dev->struct_mutex); kfree(bo); kfree(push); -- cgit v0.10.2 From 615661f3948a066fd22a36fe8ea0c528b75ee373 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Sun, 22 Aug 2010 20:54:08 +0200 Subject: drm/nv50: initialize ramht_refs list for faked 0 channel We need it for PFIFO_INTR_CACHE_ERROR interrupt handling, because nouveau_fifo_swmthd looks for matching gpuobj in ramht_refs list. It fixes kernel panic in nouveau_gpuobj_ref_find. Signed-off-by: Marcin Slusarz Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c index c95bf9b..91ef93c 100644 --- a/drivers/gpu/drm/nouveau/nv50_instmem.c +++ b/drivers/gpu/drm/nouveau/nv50_instmem.c @@ -139,6 +139,8 @@ nv50_instmem_init(struct drm_device *dev) chan->file_priv = (struct drm_file *)-2; dev_priv->fifos[0] = dev_priv->fifos[127] = chan; + INIT_LIST_HEAD(&chan->ramht_refs); + /* Channel's PRAMIN object + heap */ ret = nouveau_gpuobj_new_fake(dev, 0, c_offset, c_size, 0, NULL, &chan->ramin); -- cgit v0.10.2 From 72656c46f50b8dfe50e15793692982e636e3df20 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Fri, 3 Sep 2010 12:19:33 +1000 Subject: xfs: prevent 32bit overflow in space reservation If we attempt to preallocate more than 2^32 blocks of space in a single syscall, the transaction block reservation will overflow leading to a hangs in the superblock block accounting code. This is trivially reproduced with xfs_io. Fix the problem by capping the allocation reservation to the maximum number of blocks a single xfs_bmapi() call can allocate (2^21 blocks). Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 66d585c..4c7c7bf 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -2299,15 +2299,22 @@ xfs_alloc_file_space( e = allocatesize_fsb; } + /* + * The transaction reservation is limited to a 32-bit block + * count, hence we need to limit the number of blocks we are + * trying to reserve to avoid an overflow. We can't allocate + * more than @nimaps extents, and an extent is limited on disk + * to MAXEXTLEN (21 bits), so use that to enforce the limit. + */ + resblks = min_t(xfs_fileoff_t, (e - s), (MAXEXTLEN * nimaps)); if (unlikely(rt)) { - resrtextents = qblocks = (uint)(e - s); + resrtextents = qblocks = resblks; resrtextents /= mp->m_sb.sb_rextsize; resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0); quota_flag = XFS_QMOPT_RES_RTBLKS; } else { resrtextents = 0; - resblks = qblocks = \ - XFS_DIOSTRAT_SPACE_RES(mp, (uint)(e - s)); + resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resblks); quota_flag = XFS_QMOPT_RES_REGBLKS; } -- cgit v0.10.2 From 9af25465081480a75824fd7a16a37a5cfebeede9 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 30 Aug 2010 02:44:03 +0000 Subject: xfs: Make fiemap work with sparse files In xfs_vn_fiemap, we set bvm_count to fi_extent_max + 1 and want to return fi_extent_max extents, but actually it won't work for a sparse file. The reason is that in xfs_getbmap we will calculate holes and set it in 'out', while out is malloced by bmv_count(fi_extent_max+1) which didn't consider holes. So in the worst case, if 'out' vector looks like [hole, extent, hole, extent, hole, ... hole, extent, hole], we will only return half of fi_extent_max extents. This patch add a new parameter BMV_IF_NO_HOLES for bvm_iflags. So with this flags, we don't use our 'out' in xfs_getbmap for a hole. The solution is a bit ugly by just don't increasing index of 'out' vector. I felt that it is not easy to skip it at the very beginning since we have the complicated check and some function like xfs_getbmapx_fix_eof_hole to adjust 'out'. Cc: Dave Chinner Signed-off-by: Tao Ma Signed-off-by: Alex Elder diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 68be25d..b1fc2a6 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -664,7 +664,7 @@ xfs_vn_fiemap( fieinfo->fi_extents_max + 1; bm.bmv_count = min_t(__s32, bm.bmv_count, (PAGE_SIZE * 16 / sizeof(struct getbmapx))); - bm.bmv_iflags = BMV_IF_PREALLOC; + bm.bmv_iflags = BMV_IF_PREALLOC | BMV_IF_NO_HOLES; if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) bm.bmv_iflags |= BMV_IF_ATTRFORK; if (!(fieinfo->fi_flags & FIEMAP_FLAG_SYNC)) diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 23f14e5..f90dadd 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -5533,12 +5533,24 @@ xfs_getbmap( map[i].br_startblock)) goto out_free_map; - nexleft--; bmv->bmv_offset = out[cur_ext].bmv_offset + out[cur_ext].bmv_length; bmv->bmv_length = max_t(__int64_t, 0, bmvend - bmv->bmv_offset); + + /* + * In case we don't want to return the hole, + * don't increase cur_ext so that we can reuse + * it in the next loop. + */ + if ((iflags & BMV_IF_NO_HOLES) && + map[i].br_startblock == HOLESTARTBLOCK) { + memset(&out[cur_ext], 0, sizeof(out[cur_ext])); + continue; + } + + nexleft--; bmv->bmv_entries++; cur_ext++; } diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h index 7cf7220..87c2e9d 100644 --- a/fs/xfs/xfs_fs.h +++ b/fs/xfs/xfs_fs.h @@ -114,8 +114,10 @@ struct getbmapx { #define BMV_IF_NO_DMAPI_READ 0x2 /* Do not generate DMAPI read event */ #define BMV_IF_PREALLOC 0x4 /* rtn status BMV_OF_PREALLOC if req */ #define BMV_IF_DELALLOC 0x8 /* rtn status BMV_OF_DELALLOC if req */ +#define BMV_IF_NO_HOLES 0x10 /* Do not return holes */ #define BMV_IF_VALID \ - (BMV_IF_ATTRFORK|BMV_IF_NO_DMAPI_READ|BMV_IF_PREALLOC|BMV_IF_DELALLOC) + (BMV_IF_ATTRFORK|BMV_IF_NO_DMAPI_READ|BMV_IF_PREALLOC| \ + BMV_IF_DELALLOC|BMV_IF_NO_HOLES) /* bmv_oflags values - returned for each non-header segment */ #define BMV_OF_PREALLOC 0x1 /* segment = unwritten pre-allocation */ -- cgit v0.10.2 From 57f9bdac2510cd7fda58e4a111d250861eb1ebeb Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 25 Aug 2010 09:12:29 +0200 Subject: sysfs: checking for NULL instead of ERR_PTR d_path() returns an ERR_PTR and it doesn't return NULL. Signed-off-by: Dan Carpenter Cc: stable Reviewed-by: "Eric W. Biederman" Signed-off-by: Greg Kroah-Hartman diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 1b27b56..da3fefe 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -340,7 +340,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file) char *p; p = d_path(&file->f_path, last_sysfs_file, sizeof(last_sysfs_file)); - if (p) + if (!IS_ERR(p)) memmove(last_sysfs_file, p, strlen(p) + 1); /* need attr_sd for attr and ops, its parent for kobj */ -- cgit v0.10.2 From 9fc2b2d0cf743008d8f6be6293278f4ef61f09f3 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Sun, 22 Aug 2010 17:37:24 +0200 Subject: vt: Fix console corruption on driver hand-over. After 02f0777a0d6560eb995aade34a1b82f95c0452da "vc_origin" is no longer reset to the screen buffer before calling the con_init() hook of the new console driver. If the old driver wasn't using a fixed scanout buffer (e.g. the case of vgacon) "vc_origin" may be a pointer to a VRAM location, and its contents aren't guaranteed to be preserved after calling con_deinit() on the old driver and con_init() on the new driver, i.e. the subsequent console resize may fill the framebuffer with garbage. It can be reproduced in the transition from vgacon to the nouveau framebuffer driver: in that case the legacy VGA aperture "vc_origin" points to becomes unreadable after fbcon_init(). This patch reverts the mentioned commit. To avoid the problem it intended to fix, stop using "vc_scr_end" in vc_do_resize() to calculate how many rows we have to copy (actually the code looks simpler this way without the help of "vc_scr_end"). Signed-off-by: Francisco Jerez Cc: qiaochong Cc: Greg Kroah-Hartman Cc: Andrew Morton Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 50590c7..281aada 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -906,22 +906,16 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, * bottom of buffer */ old_origin += (old_rows - new_rows) * old_row_size; - end = vc->vc_scr_end; } else { /* * Cursor is in no man's land, copy 1/2 screenful * from the top and bottom of cursor position */ old_origin += (vc->vc_y - new_rows/2) * old_row_size; - end = old_origin + (old_row_size * new_rows); } - } else - /* - * Cursor near the top, copy contents from the top of buffer - */ - end = (old_rows > new_rows) ? old_origin + - (old_row_size * new_rows) : - vc->vc_scr_end; + } + + end = old_origin + old_row_size * min(old_rows, new_rows); update_attr(vc); @@ -3075,8 +3069,7 @@ static int bind_con_driver(const struct consw *csw, int first, int last, old_was_color = vc->vc_can_do_color; vc->vc_sw->con_deinit(vc); - if (!vc->vc_origin) - vc->vc_origin = (unsigned long)vc->vc_screenbuf; + vc->vc_origin = (unsigned long)vc->vc_screenbuf; visual_init(vc, i, 0); set_origin(vc); update_attr(vc); -- cgit v0.10.2 From d86b3001a1a6f9b8be15e5e060338de085d2bbbc Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 31 Aug 2010 17:08:52 +0200 Subject: MAINTAINERS: orphan isicom I do not maintain isicom anymore... Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman diff --git a/MAINTAINERS b/MAINTAINERS index c36f5d7..c5afc93d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3923,8 +3923,7 @@ F: Documentation/sound/oss/MultiSound F: sound/oss/msnd* MULTITECH MULTIPORT CARD (ISICOM) -M: Jiri Slaby -S: Maintained +S: Orphan F: drivers/char/isicom.c F: include/linux/isicom.h -- cgit v0.10.2 From 71cad0554956de87c3fc413b1eac9313887eb14f Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Tue, 31 Aug 2010 14:19:09 +0200 Subject: serial: fix port type conflict between NS16550A & U6_16550A Bug seen by Dr. David Alan Gilbert with sparse Signed-off-by: Philippe Langlais Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/include/linux/serial.h b/include/linux/serial.h index 1ebc694..ef91406 100644 --- a/include/linux/serial.h +++ b/include/linux/serial.h @@ -77,8 +77,7 @@ struct serial_struct { #define PORT_16654 11 #define PORT_16850 12 #define PORT_RSA 13 /* RSA-DV II/S card */ -#define PORT_U6_16550A 14 -#define PORT_MAX 14 +#define PORT_MAX 13 #define SERIAL_IO_PORT 0 #define SERIAL_IO_HUB6 1 diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 64458a9..563e234 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -44,7 +44,8 @@ #define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */ #define PORT_OCTEON 17 /* Cavium OCTEON internal UART */ #define PORT_AR7 18 /* Texas Instruments AR7 internal UART */ -#define PORT_MAX_8250 18 /* max port ID */ +#define PORT_U6_16550A 19 /* ST-Ericsson U6xxx internal UART */ +#define PORT_MAX_8250 19 /* max port ID */ /* * ARM specific type numbers. These are not currently guaranteed -- cgit v0.10.2 From 336746918299f2ca16b31490655b4ff7c8824c87 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Sat, 28 Aug 2010 16:32:55 -0400 Subject: serial: bfin_sport_uart: restore transmit frame sync fix The large cleanup/rewrite of resources in commit ccf68e59e93181df9353c0cc accidentally reverted an earlier fix in commit a19e8b205915b2925aca75b. So restore it here. Signed-off-by: Sonic Zhang Signed-off-by: Mike Frysinger Cc: stable [.34 and newer] Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c index e57fb3d..5318dd3 100644 --- a/drivers/serial/bfin_sport_uart.c +++ b/drivers/serial/bfin_sport_uart.c @@ -121,7 +121,7 @@ static int sport_uart_setup(struct sport_uart_port *up, int size, int baud_rate) unsigned int sclk = get_sclk(); /* Set TCR1 and TCR2, TFSR is not enabled for uart */ - SPORT_PUT_TCR1(up, (ITFS | TLSBIT | ITCLK)); + SPORT_PUT_TCR1(up, (LATFS | ITFS | TFSR | TLSBIT | ITCLK)); SPORT_PUT_TCR2(up, size + 1); pr_debug("%s TCR1:%x, TCR2:%x\n", __func__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up)); -- cgit v0.10.2 From 6eb68d6f3bf1707d5d816ea9242b7d38f25b942e Mon Sep 17 00:00:00 2001 From: Nathael Pajani Date: Thu, 2 Sep 2010 16:06:16 +0200 Subject: tty: fix tty_line must not be equal to number of allocated tty pointers in tty driver I found a bug "by chance" in drivers/char/tty_io.c I mean "by chance" because I was just reading the code of the tty_find_polling_driver() to make a new tty_find_by_name() function. In tty_find_polling_driver() the driver actually test "tty_line <= p->num" while num refers to the number of struct tty_struct pointers allocated for the p->ttys (p is a tty_driver), and tty_line is scanned in a tty name, which can be for example ttyS2. Then tty_line equals 2. And if p->num is 2, we have only p->ttys[0] and p->ttys[1], but no p->ttys[2]. This is actually unharmful, for tty_find_polling_driver() is used only in drivers/serial/kgdboc.c, and there's a test over there to find a console with a matching index, which will never happen. This is still a bug anyway. Signed-off-by: Nathael Pajani Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 949067a..613c852 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -355,7 +355,7 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line) if (*stp == '\0') stp = NULL; - if (tty_line >= 0 && tty_line <= p->num && p->ops && + if (tty_line >= 0 && tty_line < p->num && p->ops && p->ops->poll_init && !p->ops->poll_init(p, tty_line, stp)) { res = tty_driver_kref_get(p); *line = tty_line; -- cgit v0.10.2 From 0f1312b260499b34bb92fc9bd8ca1560dda2c4da Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Fri, 13 Aug 2010 21:29:30 +0200 Subject: USB: s3c-hsotg: Remove DEBUG define DEBUG is defined unconditionally, remove it as this clutters the message log. Signed-off-by: Maurus Cuelenaere Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 521ebed..a229744 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -12,8 +12,6 @@ * published by the Free Software Foundation. */ -#define DEBUG - #include #include #include -- cgit v0.10.2 From 08a3b3b1c2e622e378d9086aee9e2e42ce37591d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 14 Aug 2010 11:06:19 +0200 Subject: USB: ehci-ppc-of: problems in unwind The iounmap(ehci->ohci_hcctrl_reg); should be the first thing we do because the ioremap() was the last thing we did. Also if we hit any of the goto statements in the original code then it would have led to a NULL dereference of "ehci". This bug was introduced in: 796bcae7361c "USB: powerpc: Workaround for the PPC440EPX USBH_23 errata [take 3]" I modified the few lines in front a little so that my code didn't obscure the return success code path. Signed-off-by: Dan Carpenter Reviewed-by: Grant Likely Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index 335ee69..ba52be4 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c @@ -192,17 +192,19 @@ ehci_hcd_ppc_of_probe(struct platform_device *op, const struct of_device_id *mat } rv = usb_add_hcd(hcd, irq, 0); - if (rv == 0) - return 0; + if (rv) + goto err_ehci; + + return 0; +err_ehci: + if (ehci->has_amcc_usb23) + iounmap(ehci->ohci_hcctrl_reg); iounmap(hcd->regs); err_ioremap: irq_dispose_mapping(irq); err_irq: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - - if (ehci->has_amcc_usb23) - iounmap(ehci->ohci_hcctrl_reg); err_rmr: usb_put_hcd(hcd); -- cgit v0.10.2 From 793f03aa7bda8f492e12ada3de711b4ad7f4d8d0 Mon Sep 17 00:00:00 2001 From: Henrik Kretzschmar Date: Fri, 20 Aug 2010 19:57:50 +0200 Subject: USB: rndis: section mismatch fix This patch removes the following section mismatch warning, by moving the function rndis_init() from .init.text to .text. WARNING: vmlinux.o(.text+0x1aeca5a): Section mismatch in reference from the function rndis_bind_config() to the function .init.text:rndis_init() The function rndis_bind_config() references the function __init rndis_init(). This is often because rndis_bind_config lacks a __init annotation or the annotation of rndis_init is wrong. Signed-off-by: Henrik Kretzschmar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 020fa5a..ee337f7 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -1148,7 +1148,7 @@ static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS]; #endif /* CONFIG_USB_GADGET_DEBUG_FILES */ -int __init rndis_init (void) +int rndis_init(void) { u8 i; diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h index c236aaa..907c330 100644 --- a/drivers/usb/gadget/rndis.h +++ b/drivers/usb/gadget/rndis.h @@ -262,7 +262,7 @@ int rndis_signal_disconnect (int configNr); int rndis_state (int configNr); extern void rndis_set_host_mac (int configNr, const u8 *addr); -int __devinit rndis_init (void); +int rndis_init(void); void rndis_exit (void); #endif /* _LINUX_RNDIS_H */ -- cgit v0.10.2 From 037d3656adbd7e8cb848f01cf5dec423ed76bbe7 Mon Sep 17 00:00:00 2001 From: Maxim Osipov Date: Sat, 21 Aug 2010 14:54:06 +0400 Subject: USB: Fix kernel oops with g_ether and Windows Please find attached patch for https://bugzilla.kernel.org/show_bug.cgi?id=16023 problem. Signed-off-by: Maxim Osipov Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index ee337f7..972d5dd 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -293,9 +293,13 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_VENDOR_DESCRIPTION: pr_debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__); - length = strlen (rndis_per_dev_params [configNr].vendorDescr); - memcpy (outbuf, - rndis_per_dev_params [configNr].vendorDescr, length); + if ( rndis_per_dev_params [configNr].vendorDescr ) { + length = strlen (rndis_per_dev_params [configNr].vendorDescr); + memcpy (outbuf, + rndis_per_dev_params [configNr].vendorDescr, length); + } else { + outbuf[0] = 0; + } retval = 0; break; -- cgit v0.10.2 From c7aa8f44b4d1dc73591894a2dd6909213612d299 Mon Sep 17 00:00:00 2001 From: Dirk De Schepper Date: Tue, 24 Aug 2010 20:38:35 +0100 Subject: USB: option: fix incorrect novatel entries Unfortunately some of the hardware PID belonging to auto-install CDROM (AICD) of Novatel modems found their way into the option module. This causes the AICD to be treated as a modem in stead of a disk. Since the modem ports do not appear until after the AICD is ejected, this essentially disables the modem. After a couple of minutes the AICD should auto-eject, but it is just too long a wait. The frequency of the failure seems to depend on both the hardware and the linux distribution. Here is a patch that fixes this up, and also adds a couple of new PID, offering some explanations and removing some incomplete and unnecessary comments. Signed-off-by: Dirk De Schepper Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index adcbdb9..c46911a 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -164,6 +164,14 @@ static void option_instat_callback(struct urb *urb); #define YISO_VENDOR_ID 0x0EAB #define YISO_PRODUCT_U893 0xC893 +/* + * NOVATEL WIRELESS PRODUCTS + * + * Note from Novatel Wireless: + * If your Novatel modem does not work on linux, don't + * change the option module, but check our website. If + * that does not help, contact ddeschepper@nvtl.com +*/ /* MERLIN EVDO PRODUCTS */ #define NOVATELWIRELESS_PRODUCT_V640 0x1100 #define NOVATELWIRELESS_PRODUCT_V620 0x1110 @@ -185,24 +193,39 @@ static void option_instat_callback(struct urb *urb); #define NOVATELWIRELESS_PRODUCT_EU730 0x2400 #define NOVATELWIRELESS_PRODUCT_EU740 0x2410 #define NOVATELWIRELESS_PRODUCT_EU870D 0x2420 - /* OVATION PRODUCTS */ #define NOVATELWIRELESS_PRODUCT_MC727 0x4100 #define NOVATELWIRELESS_PRODUCT_MC950D 0x4400 -#define NOVATELWIRELESS_PRODUCT_U727 0x5010 -#define NOVATELWIRELESS_PRODUCT_MC727_NEW 0x5100 -#define NOVATELWIRELESS_PRODUCT_MC760 0x6000 +/* + * Note from Novatel Wireless: + * All PID in the 5xxx range are currently reserved for + * auto-install CDROMs, and should not be added to this + * module. + * + * #define NOVATELWIRELESS_PRODUCT_U727 0x5010 + * #define NOVATELWIRELESS_PRODUCT_MC727_NEW 0x5100 +*/ #define NOVATELWIRELESS_PRODUCT_OVMC760 0x6002 - -/* FUTURE NOVATEL PRODUCTS */ -#define NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED 0X6001 -#define NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED 0X7000 -#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED 0X7001 -#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED 0X8000 -#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED 0X8001 -#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0X9000 -#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0X9001 -#define NOVATELWIRELESS_PRODUCT_GLOBAL 0XA001 +#define NOVATELWIRELESS_PRODUCT_MC780 0x6010 +#define NOVATELWIRELESS_PRODUCT_EVDO_FULLSPEED 0x6000 +#define NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED 0x6001 +#define NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED 0x7000 +#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED 0x7001 +#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED3 0x7003 +#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED4 0x7004 +#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED5 0x7005 +#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED6 0x7006 +#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED7 0x7007 +#define NOVATELWIRELESS_PRODUCT_MC996D 0x7030 +#define NOVATELWIRELESS_PRODUCT_MF3470 0x7041 +#define NOVATELWIRELESS_PRODUCT_MC547 0x7042 +#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED 0x8000 +#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED 0x8001 +#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0x9000 +#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001 +#define NOVATELWIRELESS_PRODUCT_G1 0xA001 +#define NOVATELWIRELESS_PRODUCT_G1_M 0xA002 +#define NOVATELWIRELESS_PRODUCT_G2 0xA010 /* AMOI PRODUCTS */ #define AMOI_VENDOR_ID 0x1614 @@ -490,36 +513,44 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC) }, - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, /* Novatel Merlin EX720/V740/X720 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V720) }, /* Novatel Merlin V720/S720/PC720 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U730) }, /* Novatel U730/U740 (VF version) */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U740) }, /* Novatel U740 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U870) }, /* Novatel U870 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_XU870) }, /* Novatel Merlin XU870 HSDPA/3G */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_X950D) }, /* Novatel X950D */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EV620) }, /* Novatel EV620/ES620 CDMA/EV-DO */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_ES720) }, /* Novatel ES620/ES720/U720/USB720 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E725) }, /* Novatel E725/E726 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_ES620) }, /* Novatel Merlin ES620 SM Bus */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU730) }, /* Novatel EU730 and Vodafone EU740 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU740) }, /* Novatel non-Vodafone EU740 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) }, /* Novatel EU850D/EU860D/EU870D */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) }, /* Novatel MC930D/MC950D */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727_NEW) }, /* Novatel MC727/U727/USB727 refresh */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U727) }, /* Novatel MC727/U727/USB727 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC760) }, /* Novatel MC760/U760/USB760 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_OVMC760) }, /* Novatel Ovation MC760 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) }, /* Novatel HSPA product */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, /* Novatel EVDO Embedded product */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) }, /* Novatel HSPA Embedded product */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED) }, /* Novatel EVDO product */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED) }, /* Novatel HSPA product */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED) }, /* Novatel EVDO Embedded product */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED) }, /* Novatel HSPA Embedded product */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_GLOBAL) }, /* Novatel Global product */ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V720) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U730) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U740) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U870) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_XU870) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_X950D) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EV620) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_ES720) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E725) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_ES620) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU730) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU740) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_OVMC760) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC780) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_FULLSPEED) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED3) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED4) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED5) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED6) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED7) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC996D) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MF3470) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC547) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1_M) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) }, -- cgit v0.10.2 From 541e05ec3add5ab5bcf238d60161b53480280b20 Mon Sep 17 00:00:00 2001 From: Craig Shelley Date: Mon, 23 Aug 2010 20:50:57 +0100 Subject: USB: CP210x Add new device ID New device ID added for Balluff RFID reader. Signed-off-by: Craig Shelley Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 80bf833..103f9d2 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -109,6 +109,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ { USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */ { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */ + { USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */ @@ -122,14 +123,14 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1555, 0x0004) }, /* Owen AC4 USB-RS485 Converter */ { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */ { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ - { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */ - { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ - { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ - { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ { USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */ { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */ { USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */ { USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */ + { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */ + { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ + { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ + { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ { } /* Terminating Entry */ }; -- cgit v0.10.2 From 0bf7a81c5d447c21db434be35363c44c0a30f598 Mon Sep 17 00:00:00 2001 From: Jason Detring Date: Thu, 26 Aug 2010 15:08:54 -0500 Subject: USB: cp210x: Add B&G H3000 link cable ID This is the cable between an H3000 navigation unit and a multi-function display. http://www.bandg.com/en/Products/H3000/Spares-and-Accessories/Cables/H3000-CPU-USB-Cable-Pack/ Signed-off-by: Jason Detring Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 103f9d2..8ed6ff6 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -88,6 +88,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8149) }, /* West Mountain Radio Computerized Battery Analyzer */ { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ + { USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */ { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ { USB_DEVICE(0x10C4, 0x818B) }, /* AVIT Research USB to TTL */ { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */ -- cgit v0.10.2 From 5b22a32e76defeb573991b301a27d299472c5714 Mon Sep 17 00:00:00 2001 From: A E Lawrence Date: Sun, 29 Aug 2010 21:51:52 +0100 Subject: USB: cp210x usb driver: add USB_DEVICE for Pirelli DP-L10 mobile. The Pirelli DP-L10 mobile is sold under various brand names. One, already supported by cp210x, is the T-COM TC300. Here is the lsusb for that version: ------------------------------------------------------------------- Bus 001 Device 002: ID 0489:e000 Foxconn / Hon Hai T-Com TC 300 Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 1.10 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x0489 Foxconn / Hon Hai idProduct 0xe000 T-Com TC 300 bcdDevice 1.00 iManufacturer 1 Silicon Labs iProduct 2 TC 300 iSerial 3 0001 [snip] --------------------------------------------------------------------------- However the native Pirelli DP-L10 is not supported: ------------------------------------------------------------------ Bus 001 Device 003: ID 0489:e003 Foxconn / Hon Hai Pirelli DP-L10 Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 1.10 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x0489 Foxconn / Hon Hai idProduct 0xe003 Pirelli DP-L10 bcdDevice 1.00 iManufacturer 1 Silicon Labs iProduct 2 DP-L10 iSerial 3 0001 [snip] ------------------------------------------------------------------------- All that is required is an extra USB_DEVICE entry: { USB_DEVICE(0x0489, 0xE003) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM +Mobile */ The patch adds that entry. Tested under 2.6.36-rc2 from git. Signed-off-by: A E Lawrence Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 8ed6ff6..4f1744c 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -56,6 +56,7 @@ static int debug; static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */ { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ + { USB_DEVICE(0x0489, 0xE003) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ { USB_DEVICE(0x0745, 0x1000) }, /* CipherLab USB CCD Barcode Scanner 1000 */ { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ { USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */ -- cgit v0.10.2 From 0791971ba8fbc44e4f476079f856335ed45e6324 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Sat, 28 Aug 2010 03:06:29 -0300 Subject: usb: allow drivers to use allocated bandwidth until unbound When using the remove sysfs file, the device configuration is set to -1 (unconfigured). This eventually unbind drivers with the bandwidth_mutex held. Some drivers may call functions that hold said mutex, like usb_reset_device. This is the case for rtl8187, for example. This will lead to the same process holding the mutex twice, which deadlocks. Besides, according to Alan Stern: "The deadlock problem probably could be handled somehow, but there's a separate issue: Until the usb_disable_device call finishes unbinding the drivers, the drivers are free to continue using their allocated bandwidth. We musn't change the bandwidth allocations until after the unbinding is done. So this patch is indeed necessary." Unbinding the driver before holding the bandwidth_mutex solves the problem. If any operation after that fails, drivers are not bound again. But that would be a problem anyway that the user may solve resetting the device configuration to one that works, just like he would need to do in most other failure cases. Signed-off-by: Thadeu Lima de Souza Cascardo Cc: Alan Stern Cc: Sarah Sharp Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index fd4c36e..844683e 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1724,6 +1724,15 @@ free_interfaces: if (ret) goto free_interfaces; + /* if it's already configured, clear out old state first. + * getting rid of old interfaces means unbinding their drivers. + */ + if (dev->state != USB_STATE_ADDRESS) + usb_disable_device(dev, 1); /* Skip ep0 */ + + /* Get rid of pending async Set-Config requests for this device */ + cancel_async_set_config(dev); + /* Make sure we have bandwidth (and available HCD resources) for this * configuration. Remove endpoints from the schedule if we're dropping * this configuration to set configuration 0. After this point, the @@ -1733,20 +1742,11 @@ free_interfaces: mutex_lock(&hcd->bandwidth_mutex); ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL); if (ret < 0) { - usb_autosuspend_device(dev); mutex_unlock(&hcd->bandwidth_mutex); + usb_autosuspend_device(dev); goto free_interfaces; } - /* if it's already configured, clear out old state first. - * getting rid of old interfaces means unbinding their drivers. - */ - if (dev->state != USB_STATE_ADDRESS) - usb_disable_device(dev, 1); /* Skip ep0 */ - - /* Get rid of pending async Set-Config requests for this device */ - cancel_async_set_config(dev); - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION, 0, configuration, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); @@ -1761,8 +1761,8 @@ free_interfaces: if (!cp) { usb_set_device_state(dev, USB_STATE_ADDRESS); usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); - usb_autosuspend_device(dev); mutex_unlock(&hcd->bandwidth_mutex); + usb_autosuspend_device(dev); goto free_interfaces; } mutex_unlock(&hcd->bandwidth_mutex); -- cgit v0.10.2 From 3c35b002da0c749ec15cf25cfe58f06aa230ae9c Mon Sep 17 00:00:00 2001 From: Bill Pemberton Date: Wed, 25 Aug 2010 18:21:23 -0400 Subject: USB: ssu100: turn off debug flag Remove the hard coding of the debug flag to 1. Signed-off-by: Bill Pemberton Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 68c18fd..e986002 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -46,7 +46,7 @@ #define FULLPWRBIT 0x00000080 #define NEXT_BOARD_POWER_BIT 0x00000004 -static int debug = 1; +static int debug; /* Version Information */ #define DRIVER_VERSION "v0.1" -- cgit v0.10.2 From caf3a636a9f809fdca5fa746e6687096457accb1 Mon Sep 17 00:00:00 2001 From: Dave Ludlow Date: Tue, 31 Aug 2010 14:26:17 -0400 Subject: usb: serial: mos7840: Add USB ID to support the B&B Electronics USOPTL4-2P. Add the USB ID needed to support B&B Electronic's 2-port, optically-isolated, powered, USB to RS485 converter. Signed-off-by: Dave Ludlow Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 585b7e6..9a5ea9d 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -129,6 +129,7 @@ #define BANDB_DEVICE_ID_USOPTL4_2 0xAC42 #define BANDB_DEVICE_ID_USOPTL4_4 0xAC44 #define BANDB_DEVICE_ID_USOPTL2_4 0xAC24 +#define BANDB_DEVICE_ID_USOPTL4_2P 0xBC02 /* This driver also supports * ATEN UC2324 device using Moschip MCS7840 @@ -192,6 +193,7 @@ static const struct usb_device_id moschip_port_id_table[] = { {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4P)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, {} /* terminating entry */ @@ -209,6 +211,7 @@ static const struct usb_device_id moschip_id_table_combined[] __devinitconst = { {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4P)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, {} /* terminating entry */ -- cgit v0.10.2 From 4035e45632c2a8bb4edae83c20447051bd9a9604 Mon Sep 17 00:00:00 2001 From: Toby Gray Date: Wed, 1 Sep 2010 16:01:19 +0100 Subject: USB: cdc-acm: Adding second ACM channel support for various Nokia and one Samsung phones S60 phones from Nokia and Samsung expose two ACM channels. The first is a modem with a standard AT-command interface, which is picked up correctly by CDC-ACM. The second ACM port is marked as having a vendor-specific protocol. This means that the ACM driver will not claim the second channel by default. This adds support for the second ACM channel for the following devices: Nokia E63 Nokia E75 Nokia 6760 Slide Nokia E52 Nokia E55 Nokia E72 Nokia X6 Nokia N97 Mini Nokia 5800 Xpressmusic Nokia E90 Samsung GTi8510 (INNOV8) Signed-off-by: Toby Gray Cc: Oliver Neukum Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 1833b3a..a3d6c4d 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1481,6 +1481,11 @@ static int acm_reset_resume(struct usb_interface *intf) USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, \ USB_CDC_ACM_PROTO_VENDOR) +#define SAMSUNG_PCSUITE_ACM_INFO(x) \ + USB_DEVICE_AND_INTERFACE_INFO(0x04e7, x, \ + USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, \ + USB_CDC_ACM_PROTO_VENDOR) + /* * USB driver structure. */ @@ -1591,6 +1596,17 @@ static const struct usb_device_id acm_ids[] = { { NOKIA_PCSUITE_ACM_INFO(0x0108), }, /* Nokia 5320 XpressMusic 2G */ { NOKIA_PCSUITE_ACM_INFO(0x01f5), }, /* Nokia N97, RM-505 */ { NOKIA_PCSUITE_ACM_INFO(0x02e3), }, /* Nokia 5230, RM-588 */ + { NOKIA_PCSUITE_ACM_INFO(0x0178), }, /* Nokia E63 */ + { NOKIA_PCSUITE_ACM_INFO(0x010e), }, /* Nokia E75 */ + { NOKIA_PCSUITE_ACM_INFO(0x02d9), }, /* Nokia 6760 Slide */ + { NOKIA_PCSUITE_ACM_INFO(0x01d0), }, /* Nokia E52 */ + { NOKIA_PCSUITE_ACM_INFO(0x0223), }, /* Nokia E72 */ + { NOKIA_PCSUITE_ACM_INFO(0x0275), }, /* Nokia X6 */ + { NOKIA_PCSUITE_ACM_INFO(0x026c), }, /* Nokia N97 Mini */ + { NOKIA_PCSUITE_ACM_INFO(0x0154), }, /* Nokia 5800 XpressMusic */ + { NOKIA_PCSUITE_ACM_INFO(0x04ce), }, /* Nokia E90 */ + { NOKIA_PCSUITE_ACM_INFO(0x01d4), }, /* Nokia E55 */ + { SAMSUNG_PCSUITE_ACM_INFO(0x6651), }, /* Samsung GTi8510 (INNOV8) */ /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ -- cgit v0.10.2 From 870408c8291015872a7a0b583673a9e56b3e73f4 Mon Sep 17 00:00:00 2001 From: Dave Ludlow Date: Wed, 1 Sep 2010 12:33:30 -0400 Subject: usb: serial: mos7840: Add USB IDs to support more B&B USB/RS485 converters. Add the USB IDs needed to support the B&B USOPTL4-4P, USO9ML2-2P, and USO9ML2-4P. This patch expands and corrects a typo in the patch sent on 08-31-2010. Signed-off-by: Dave Ludlow Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 9a5ea9d..1c9b6e9 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -119,17 +119,20 @@ * by making a change here, in moschip_port_id_table, and in * moschip_id_table_combined */ -#define USB_VENDOR_ID_BANDB 0x0856 -#define BANDB_DEVICE_ID_USO9ML2_2 0xAC22 -#define BANDB_DEVICE_ID_USO9ML2_4 0xAC24 -#define BANDB_DEVICE_ID_US9ML2_2 0xAC29 -#define BANDB_DEVICE_ID_US9ML2_4 0xAC30 -#define BANDB_DEVICE_ID_USPTL4_2 0xAC31 -#define BANDB_DEVICE_ID_USPTL4_4 0xAC32 -#define BANDB_DEVICE_ID_USOPTL4_2 0xAC42 -#define BANDB_DEVICE_ID_USOPTL4_4 0xAC44 -#define BANDB_DEVICE_ID_USOPTL2_4 0xAC24 -#define BANDB_DEVICE_ID_USOPTL4_2P 0xBC02 +#define USB_VENDOR_ID_BANDB 0x0856 +#define BANDB_DEVICE_ID_USO9ML2_2 0xAC22 +#define BANDB_DEVICE_ID_USO9ML2_2P 0xBC00 +#define BANDB_DEVICE_ID_USO9ML2_4 0xAC24 +#define BANDB_DEVICE_ID_USO9ML2_4P 0xBC01 +#define BANDB_DEVICE_ID_US9ML2_2 0xAC29 +#define BANDB_DEVICE_ID_US9ML2_4 0xAC30 +#define BANDB_DEVICE_ID_USPTL4_2 0xAC31 +#define BANDB_DEVICE_ID_USPTL4_4 0xAC32 +#define BANDB_DEVICE_ID_USOPTL4_2 0xAC42 +#define BANDB_DEVICE_ID_USOPTL4_2P 0xBC02 +#define BANDB_DEVICE_ID_USOPTL4_4 0xAC44 +#define BANDB_DEVICE_ID_USOPTL4_4P 0xBC03 +#define BANDB_DEVICE_ID_USOPTL2_4 0xAC24 /* This driver also supports * ATEN UC2324 device using Moschip MCS7840 @@ -185,15 +188,18 @@ static const struct usb_device_id moschip_port_id_table[] = { {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)}, - {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4P)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, {} /* terminating entry */ @@ -203,15 +209,18 @@ static const struct usb_device_id moschip_id_table_combined[] __devinitconst = { {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)}, - {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4P)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, {} /* terminating entry */ -- cgit v0.10.2 From 902ffc3c707c1d459ea57428a619a807cbe412f9 Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Wed, 1 Sep 2010 18:37:12 +0100 Subject: USB: cxacru: Use a bulk/int URB to access the command endpoint The command endpoint is either a bulk or interrupt endpoint, but using the wrong type of transfer causes an error if CONFIG_USB_DEBUG is enabled after commit f661c6f8c67bd55e93348f160d590ff9edf08904, which checks for this mismatch. Detect which type of endpoint it is and use a bulk/int URB as appropriate. There are other function calls specifying a bulk pipe, but usb_clear_halt doesn't use the pipe type (only the endpoint) and usb_bulk_msg auto-detects interrupt transfers. Signed-off-by: Simon Arlott Cc: stable [.34 and newer] Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 593fc5e..5af23cc 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -1127,6 +1127,7 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, { struct cxacru_data *instance; struct usb_device *usb_dev = interface_to_usbdev(intf); + struct usb_host_endpoint *cmd_ep = usb_dev->ep_in[CXACRU_EP_CMD]; int ret; /* instance init */ @@ -1171,15 +1172,34 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, goto fail; } - usb_fill_int_urb(instance->rcv_urb, + if (!cmd_ep) { + dbg("cxacru_bind: no command endpoint"); + ret = -ENODEV; + goto fail; + } + + if ((cmd_ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_INT) { + usb_fill_int_urb(instance->rcv_urb, usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD), instance->rcv_buf, PAGE_SIZE, cxacru_blocking_completion, &instance->rcv_done, 1); - usb_fill_int_urb(instance->snd_urb, + usb_fill_int_urb(instance->snd_urb, usb_dev, usb_sndintpipe(usb_dev, CXACRU_EP_CMD), instance->snd_buf, PAGE_SIZE, cxacru_blocking_completion, &instance->snd_done, 4); + } else { + usb_fill_bulk_urb(instance->rcv_urb, + usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_CMD), + instance->rcv_buf, PAGE_SIZE, + cxacru_blocking_completion, &instance->rcv_done); + + usb_fill_bulk_urb(instance->snd_urb, + usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_CMD), + instance->snd_buf, PAGE_SIZE, + cxacru_blocking_completion, &instance->snd_done); + } mutex_init(&instance->cm_serialize); -- cgit v0.10.2 From 5b239f0aebd4dd6f85b13decf5e18e86e35d57f0 Mon Sep 17 00:00:00 2001 From: Philippe Corbes Date: Tue, 31 Aug 2010 19:31:32 +0200 Subject: USB: cdc-acm: Add pseudo modem without AT command capabilities cdc-acm.c : Manage pseudo-modem without AT commands capabilities Enable to drive electronic simple gadgets based on microcontrolers. The Interface descriptor is like this: bInterfaceClass 2 Communications bInterfaceSubClass 2 Abstract (modem) bInterfaceProtocol 0 None Signed-off-by: Philippe Corbes Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index a3d6c4d..597defc 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1615,6 +1615,10 @@ static const struct usb_device_id acm_ids[] = { .driver_info = NOT_A_MODEM, }, + /* control interfaces without any protocol set */ + { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, + USB_CDC_PROTO_NONE) }, + /* control interfaces with various AT-command sets */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_ACM_PROTO_AT_V25TER) }, -- cgit v0.10.2 From 577045c0a76e34294f902a7d5d60e90b04d094d0 Mon Sep 17 00:00:00 2001 From: Toby Gray Date: Thu, 2 Sep 2010 10:46:20 +0100 Subject: USB: cdc-acm: Fixing crash when ACM probing interfaces with no endpoint descriptors. Certain USB devices, such as the Nokia X6 mobile phone, don't expose any endpoint descriptors on some of their interfaces. If the ACM driver is forced to probe all interfaces on a device the a NULL pointer dereference will occur when the ACM driver attempts to use the endpoint of the alternative settings. One way to get the ACM driver to probe all the interfaces is by using the /sys/bus/usb/drivers/cdc_acm/new_id interface. This patch checks that the endpoint pointer for the current alternate settings is non-NULL before using it. Signed-off-by: Toby Gray Cc: Oliver Neukum Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 597defc..bc62fae 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -965,7 +965,8 @@ static int acm_probe(struct usb_interface *intf, } if (!buflen) { - if (intf->cur_altsetting->endpoint->extralen && + if (intf->cur_altsetting->endpoint && + intf->cur_altsetting->endpoint->extralen && intf->cur_altsetting->endpoint->extra) { dev_dbg(&intf->dev, "Seeking extra descriptors on endpoint\n"); -- cgit v0.10.2 From 657373883417b2618023fd4135d251ba06a2c30a Mon Sep 17 00:00:00 2001 From: Luke Lowrey Date: Thu, 2 Sep 2010 11:39:49 +0100 Subject: USB: ftdi_sio: Added custom PIDs for ChamSys products Added the 0xDAF8 to 0xDAFF PID range for ChamSys limited USB interface/wing products Signed-off-by: Luke Lowrey Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index c792c96..97cc87d 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -753,6 +753,14 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, SEGWAY_RMP200_PID) }, { USB_DEVICE(IONICS_VID, IONICS_PLUGCOMPUTER_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_24_MASTER_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_PC_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_USB_DMX_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MIDI_TIMECODE_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MINI_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MAXI_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MEDIA_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_WING_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 2e95857..15a4583 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -135,6 +135,18 @@ #define FTDI_NDI_AURORA_SCU_PID 0xDA74 /* NDI Aurora SCU */ /* + * ChamSys Limited (www.chamsys.co.uk) USB wing/interface product IDs + */ +#define FTDI_CHAMSYS_24_MASTER_WING_PID 0xDAF8 +#define FTDI_CHAMSYS_PC_WING_PID 0xDAF9 +#define FTDI_CHAMSYS_USB_DMX_PID 0xDAFA +#define FTDI_CHAMSYS_MIDI_TIMECODE_PID 0xDAFB +#define FTDI_CHAMSYS_MINI_WING_PID 0xDAFC +#define FTDI_CHAMSYS_MAXI_WING_PID 0xDAFD +#define FTDI_CHAMSYS_MEDIA_WING_PID 0xDAFE +#define FTDI_CHAMSYS_WING_PID 0xDAFF + +/* * Westrex International devices submitted by Cory Lee */ #define FTDI_WESTREX_MODEL_777_PID 0xDC00 /* Model 777 */ -- cgit v0.10.2 From b681b5886bb5d1f5b6750a0ed7c62846da7ccea4 Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Tue, 3 Aug 2010 19:15:31 +0000 Subject: staging: hv: Fix missing functions for net_device_ops Fix missing functions for net_device_ops. It's a bug when porting the drivers from 2.6.27 to 2.6.32. In 2.6.27, the default functions for Ethernet, like eth_change_mtu(), were assigned by ether_setup(). But in 2.6.32, these function pointers moved to net_device_ops structure and no longer be assigned in ether_setup(). So we need to set these functions in our driver code. It will ensure the MTU won't be set beyond 1500. Otherwise, this can cause an error on the server side, because the HyperV linux driver doesn't support jumbo frame yet. Signed-off-by: Haiyang Zhang Signed-off-by: Hank Janssen Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 56e1157..64a0114 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -327,6 +327,9 @@ static const struct net_device_ops device_ops = { .ndo_stop = netvsc_close, .ndo_start_xmit = netvsc_start_xmit, .ndo_set_multicast_list = netvsc_set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, }; static int netvsc_probe(struct device *device) -- cgit v0.10.2 From 0c47a70a9a8a6d1ec37a53d2f9cb82f8b8ef8aa2 Mon Sep 17 00:00:00 2001 From: Hank Janssen Date: Thu, 5 Aug 2010 19:29:44 +0000 Subject: staging: hv: Fixed bounce kmap problem by using correct index Fixed bounce offset kmap problem by using correct index. The symptom of the problem is that in some NAS appliances this problem represents Itself by a unresponsive VM under a load with many clients writing small files. Signed-off-by:Hank Janssen Signed-off-by:Haiyang Zhang Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 075b61b..3b9ccb0 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -495,7 +495,7 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl, /* ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE); */ - if (j == 0) + if (bounce_addr == 0) bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0); while (srclen) { @@ -556,7 +556,7 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl, destlen = orig_sgl[i].length; /* ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE); */ - if (j == 0) + if (bounce_addr == 0) bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0); while (destlen) { -- cgit v0.10.2 From e5fa721d1c2a54261a37eb59686e18dee34b6af6 Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Thu, 5 Aug 2010 19:30:01 +0000 Subject: staging: hv: Fixed the value of the 64bit-hole inside ring buffer Fixed the value of the 64bit-hole inside ring buffer, this caused a problem on Hyper-V when running checked Windows builds. Checked builds of Windows are used internally and given to external system integrators at times. They are builds that for example that all elements in a structure follow the definition of that Structure. The bug this fixed was for a field that we did not fill in at all (Because we do Not use it on the Linux side), and the checked build of windows gives errors on it internally to the Windows logs. This fixes that error. Signed-off-by:Hank Janssen Signed-off-by:Haiyang Zhang Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/hv/ring_buffer.c b/drivers/staging/hv/ring_buffer.c index 17bc762..d78c569 100644 --- a/drivers/staging/hv/ring_buffer.c +++ b/drivers/staging/hv/ring_buffer.c @@ -193,8 +193,7 @@ Description: static inline u64 GetRingBufferIndices(struct hv_ring_buffer_info *RingInfo) { - return ((u64)RingInfo->RingBuffer->WriteIndex << 32) - || RingInfo->RingBuffer->ReadIndex; + return (u64)RingInfo->RingBuffer->WriteIndex << 32; } -- cgit v0.10.2 From 15dd1c9f53b31cdc84b8072a88c23fa09527c596 Mon Sep 17 00:00:00 2001 From: Hank Janssen Date: Thu, 5 Aug 2010 19:30:31 +0000 Subject: staging: hv: Increased storvsc ringbuffer and max_io_requests Increased storvsc ringbuffer and max_io_requests. This now more closely mimics the numbers on Hyper-V. And will allow more IO requests to take place for the SCSI driver. Max_IO is set to double from what it was before, Hyper-V allows it and we have had appliance builder requests to see if it was a problem to increase the number. Ringbuffer size for storvsc is now increased because I have seen A few buffer problems on extremely busy systems. They were Set pretty low before. And since max_io_requests is increased I Really needed to increase the buffer as well. Signed-off-by:Hank Janssen Signed-off-by:Haiyang Zhang Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/hv/storvsc_api.h b/drivers/staging/hv/storvsc_api.h index 0063bde..8505a1c 100644 --- a/drivers/staging/hv/storvsc_api.h +++ b/drivers/staging/hv/storvsc_api.h @@ -28,10 +28,10 @@ #include "vmbus_api.h" /* Defines */ -#define STORVSC_RING_BUFFER_SIZE (10*PAGE_SIZE) +#define STORVSC_RING_BUFFER_SIZE (20*PAGE_SIZE) #define BLKVSC_RING_BUFFER_SIZE (20*PAGE_SIZE) -#define STORVSC_MAX_IO_REQUESTS 64 +#define STORVSC_MAX_IO_REQUESTS 128 /* * In Hyper-V, each port/path/target maps to 1 scsi host adapter. In -- cgit v0.10.2 From 77c5ceaff31645ea049c6706b99e699eae81fb88 Mon Sep 17 00:00:00 2001 From: Hank Janssen Date: Wed, 1 Sep 2010 11:10:41 -0700 Subject: staging: hv: Fixed lockup problem with bounce_buffer scatter list Fixed lockup problem with bounce_buffer scatter list which caused crashes in heavy loads. And minor code indentation cleanup in effected area. Removed whitespace and noted minor indentation changes in description as pointed out by Joe Perches. (Thanks for reviewing Joe) Signed-off-by: Hank Janssen Signed-off-by: Haiyang Zhang Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 3b9ccb0..62882a4 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -615,6 +615,7 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd, unsigned int request_size = 0; int i; struct scatterlist *sgl; + unsigned int sg_count = 0; DPRINT_DBG(STORVSC_DRV, "scmnd %p dir %d, use_sg %d buf %p len %d " "queue depth %d tagged %d", scmnd, scmnd->sc_data_direction, @@ -697,6 +698,7 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd, request->DataBuffer.Length = scsi_bufflen(scmnd); if (scsi_sg_count(scmnd)) { sgl = (struct scatterlist *)scsi_sglist(scmnd); + sg_count = scsi_sg_count(scmnd); /* check if we need to bounce the sgl */ if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1) { @@ -731,15 +733,16 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd, scsi_sg_count(scmnd)); sgl = cmd_request->bounce_sgl; + sg_count = cmd_request->bounce_sgl_count; } request->DataBuffer.Offset = sgl[0].offset; - for (i = 0; i < scsi_sg_count(scmnd); i++) { + for (i = 0; i < sg_count; i++) { DPRINT_DBG(STORVSC_DRV, "sgl[%d] len %d offset %d\n", i, sgl[i].length, sgl[i].offset); request->DataBuffer.PfnArray[i] = - page_to_pfn(sg_page((&sgl[i]))); + page_to_pfn(sg_page((&sgl[i]))); } } else if (scsi_sglist(scmnd)) { /* ASSERT(scsi_bufflen(scmnd) <= PAGE_SIZE); */ -- cgit v0.10.2 From f8d261d39a24f9f612cb8b2d5ad68654727543cd Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 30 Aug 2010 08:57:49 +0200 Subject: staging: spectra needs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On one of my m68k test builds I get: drivers/staging/spectra/ffsport.c: In function ‘ioctl_read_page_data’: drivers/staging/spectra/ffsport.c:196: error: implicit declaration of function ‘kmalloc’ drivers/staging/spectra/ffsport.c:196: warning: assignment makes pointer from integer without a cast drivers/staging/spectra/ffsport.c:212: error: implicit declaration of function ‘kfree’ drivers/staging/spectra/ffsport.c: In function ‘ioctl_write_page_data’: drivers/staging/spectra/ffsport.c:229: warning: assignment makes pointer from integer without a cast drivers/staging/spectra/ffsport.c: In function ‘SBD_setup_device’: drivers/staging/spectra/ffsport.c:637: warning: assignment makes pointer from integer without a cast Signed-off-by: Geert Uytterhoeven Acked-by: Pekka Enberg Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/spectra/ffsport.c b/drivers/staging/spectra/ffsport.c index 44a7fbe..fa21a0f 100644 --- a/drivers/staging/spectra/ffsport.c +++ b/drivers/staging/spectra/ffsport.c @@ -28,6 +28,7 @@ #include #include #include +#include /**** Helper functions used for Div, Remainder operation on u64 ****/ -- cgit v0.10.2 From 10022a0675a8f8722068d956a798f1fddb02e71c Mon Sep 17 00:00:00 2001 From: Andreas Bombe Date: Sat, 14 Aug 2010 03:24:22 +0200 Subject: staging: comedi das08_cs.c: Fix io_req_t conversion Commit 90abdc3b9 converted all PCMCIA users away from io_req_t. In das08_cs.c the converted IO lines mask setting was added but the old line using the now inexistent p_dev->io was not removed. Signed-off-by: Andreas Bombe Signed-off-by: Dominik Brodowski Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index c6aa52f..48d9fb1 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -222,7 +222,6 @@ static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev, p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(io->flags); - p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; p_dev->resource[0]->start = io->win[0].base; p_dev->resource[0]->end = io->win[0].len; if (io->nwin > 1) { -- cgit v0.10.2 From 9e693e4375689cb1cd1529aba011de0044f74ef5 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 29 Aug 2010 02:13:11 +0100 Subject: Staging: rt2870sta: Add more device IDs from vendor drivers Taken from DPO_RT3070_LinuxSTA_V2.3.0.4_20100604.tar.bz2 and 2010_0709_RT2870_Linux_STA_v2.4.0.1.tar.bz2, with duplicates removed. Signed-off-by: Ben Hutchings Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rt2860/usb_main_dev.c b/drivers/staging/rt2860/usb_main_dev.c index a0fe31d..ebf9074 100644 --- a/drivers/staging/rt2860/usb_main_dev.c +++ b/drivers/staging/rt2860/usb_main_dev.c @@ -44,6 +44,7 @@ struct usb_device_id rtusb_usb_id[] = { {USB_DEVICE(0x07B8, 0x2870)}, /* AboCom */ {USB_DEVICE(0x07B8, 0x2770)}, /* AboCom */ {USB_DEVICE(0x0DF6, 0x0039)}, /* Sitecom 2770 */ + {USB_DEVICE(0x0DF6, 0x003F)}, /* Sitecom 2770 */ {USB_DEVICE(0x083A, 0x7512)}, /* Arcadyan 2770 */ {USB_DEVICE(0x0789, 0x0162)}, /* Logitec 2870 */ {USB_DEVICE(0x0789, 0x0163)}, /* Logitec 2870 */ @@ -95,7 +96,8 @@ struct usb_device_id rtusb_usb_id[] = { {USB_DEVICE(0x050d, 0x815c)}, {USB_DEVICE(0x1482, 0x3C09)}, /* Abocom */ {USB_DEVICE(0x14B2, 0x3C09)}, /* Alpha */ - {USB_DEVICE(0x04E8, 0x2018)}, /* samsung */ + {USB_DEVICE(0x04E8, 0x2018)}, /* samsung linkstick2 */ + {USB_DEVICE(0x1690, 0x0740)}, /* Askey */ {USB_DEVICE(0x5A57, 0x0280)}, /* Zinwell */ {USB_DEVICE(0x5A57, 0x0282)}, /* Zinwell */ {USB_DEVICE(0x7392, 0x7718)}, @@ -105,21 +107,34 @@ struct usb_device_id rtusb_usb_id[] = { {USB_DEVICE(0x1737, 0x0071)}, /* Linksys WUSB600N */ {USB_DEVICE(0x0411, 0x00e8)}, /* Buffalo WLI-UC-G300N */ {USB_DEVICE(0x050d, 0x815c)}, /* Belkin F5D8053 */ + {USB_DEVICE(0x100D, 0x9031)}, /* Motorola 2770 */ #endif /* RT2870 // */ #ifdef RT3070 {USB_DEVICE(0x148F, 0x3070)}, /* Ralink 3070 */ {USB_DEVICE(0x148F, 0x3071)}, /* Ralink 3071 */ {USB_DEVICE(0x148F, 0x3072)}, /* Ralink 3072 */ {USB_DEVICE(0x0DB0, 0x3820)}, /* Ralink 3070 */ + {USB_DEVICE(0x0DB0, 0x871C)}, /* Ralink 3070 */ + {USB_DEVICE(0x0DB0, 0x822C)}, /* Ralink 3070 */ + {USB_DEVICE(0x0DB0, 0x871B)}, /* Ralink 3070 */ + {USB_DEVICE(0x0DB0, 0x822B)}, /* Ralink 3070 */ {USB_DEVICE(0x0DF6, 0x003E)}, /* Sitecom 3070 */ {USB_DEVICE(0x0DF6, 0x0042)}, /* Sitecom 3072 */ + {USB_DEVICE(0x0DF6, 0x0048)}, /* Sitecom 3070 */ + {USB_DEVICE(0x0DF6, 0x0047)}, /* Sitecom 3071 */ {USB_DEVICE(0x14B2, 0x3C12)}, /* AL 3070 */ {USB_DEVICE(0x18C5, 0x0012)}, /* Corega 3070 */ {USB_DEVICE(0x083A, 0x7511)}, /* Arcadyan 3070 */ + {USB_DEVICE(0x083A, 0xA701)}, /* SMC 3070 */ + {USB_DEVICE(0x083A, 0xA702)}, /* SMC 3072 */ {USB_DEVICE(0x1740, 0x9703)}, /* EnGenius 3070 */ {USB_DEVICE(0x1740, 0x9705)}, /* EnGenius 3071 */ {USB_DEVICE(0x1740, 0x9706)}, /* EnGenius 3072 */ + {USB_DEVICE(0x1740, 0x9707)}, /* EnGenius 3070 */ + {USB_DEVICE(0x1740, 0x9708)}, /* EnGenius 3071 */ + {USB_DEVICE(0x1740, 0x9709)}, /* EnGenius 3072 */ {USB_DEVICE(0x13D3, 0x3273)}, /* AzureWave 3070 */ + {USB_DEVICE(0x13D3, 0x3305)}, /* AzureWave 3070*/ {USB_DEVICE(0x1044, 0x800D)}, /* Gigabyte GN-WB32L 3070 */ {USB_DEVICE(0x2019, 0xAB25)}, /* Planex Communications, Inc. RT3070 */ {USB_DEVICE(0x07B8, 0x3070)}, /* AboCom 3070 */ @@ -132,14 +147,36 @@ struct usb_device_id rtusb_usb_id[] = { {USB_DEVICE(0x07D1, 0x3C0D)}, /* D-Link 3070 */ {USB_DEVICE(0x07D1, 0x3C0E)}, /* D-Link 3070 */ {USB_DEVICE(0x07D1, 0x3C0F)}, /* D-Link 3070 */ + {USB_DEVICE(0x07D1, 0x3C16)}, /* D-Link 3070 */ + {USB_DEVICE(0x07D1, 0x3C17)}, /* D-Link 8070 */ {USB_DEVICE(0x1D4D, 0x000C)}, /* Pegatron Corporation 3070 */ {USB_DEVICE(0x1D4D, 0x000E)}, /* Pegatron Corporation 3070 */ {USB_DEVICE(0x5A57, 0x5257)}, /* Zinwell 3070 */ {USB_DEVICE(0x5A57, 0x0283)}, /* Zinwell 3072 */ {USB_DEVICE(0x04BB, 0x0945)}, /* I-O DATA 3072 */ + {USB_DEVICE(0x04BB, 0x0947)}, /* I-O DATA 3070 */ + {USB_DEVICE(0x04BB, 0x0948)}, /* I-O DATA 3072 */ {USB_DEVICE(0x203D, 0x1480)}, /* Encore 3070 */ + {USB_DEVICE(0x20B8, 0x8888)}, /* PARA INDUSTRIAL 3070 */ + {USB_DEVICE(0x0B05, 0x1784)}, /* Asus 3072 */ + {USB_DEVICE(0x203D, 0x14A9)}, /* Encore 3070*/ + {USB_DEVICE(0x0DB0, 0x899A)}, /* MSI 3070*/ + {USB_DEVICE(0x0DB0, 0x3870)}, /* MSI 3070*/ + {USB_DEVICE(0x0DB0, 0x870A)}, /* MSI 3070*/ + {USB_DEVICE(0x0DB0, 0x6899)}, /* MSI 3070 */ + {USB_DEVICE(0x0DB0, 0x3822)}, /* MSI 3070 */ + {USB_DEVICE(0x0DB0, 0x3871)}, /* MSI 3070 */ + {USB_DEVICE(0x0DB0, 0x871A)}, /* MSI 3070 */ + {USB_DEVICE(0x0DB0, 0x822A)}, /* MSI 3070 */ + {USB_DEVICE(0x0DB0, 0x3821)}, /* Ralink 3070 */ + {USB_DEVICE(0x0DB0, 0x821A)}, /* Ralink 3070 */ + {USB_DEVICE(0x083A, 0xA703)}, /* IO-MAGIC */ + {USB_DEVICE(0x13D3, 0x3307)}, /* Azurewave */ + {USB_DEVICE(0x13D3, 0x3321)}, /* Azurewave */ + {USB_DEVICE(0x07FA, 0x7712)}, /* Edimax */ + {USB_DEVICE(0x0789, 0x0166)}, /* Edimax */ + {USB_DEVICE(0x148F, 0x2070)}, /* Edimax */ #endif /* RT3070 // */ - {USB_DEVICE(0x0DF6, 0x003F)}, /* Sitecom WL-608 */ {USB_DEVICE(0x1737, 0x0077)}, /* Linksys WUSB54GC-EU v3 */ {USB_DEVICE(0x2001, 0x3C09)}, /* D-Link */ {USB_DEVICE(0x2001, 0x3C0A)}, /* D-Link 3072 */ -- cgit v0.10.2 From 273ad8dcef345cac55a5db910137c10953f81480 Mon Sep 17 00:00:00 2001 From: Shahar Havivi Date: Sat, 28 Aug 2010 10:09:05 +0300 Subject: Staging: zram: free device memory when init fails Signed-off-by: Shahar Havivi Cc: Nitin Gupta Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index 77d4d71..722c840 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c @@ -769,6 +769,7 @@ static int __init zram_init(void) free_devices: while (dev_id) destroy_device(&devices[--dev_id]); + kfree(devices); unregister: unregister_blkdev(zram_major, "zram"); out: -- cgit v0.10.2 From 11ac33a5f29a8e96ec76097ec1b3de3a4045f4b6 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Tue, 24 Aug 2010 12:12:26 -0400 Subject: Staging: spectra: depend on X86_MRST lld_nand fails to build on arches without virt_to_bus. Since this driver is specifically for hardware enablment on Moorestown, this patch adds Moorestown MID support as a dependency. Signed-off-by: Jeff Mahoney Cc: David Woodhouse Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/spectra/Kconfig b/drivers/staging/spectra/Kconfig index 5e2ffef..d231ae2 100644 --- a/drivers/staging/spectra/Kconfig +++ b/drivers/staging/spectra/Kconfig @@ -2,6 +2,7 @@ menuconfig SPECTRA tristate "Denali Spectra Flash Translation Layer" depends on BLOCK + depends on X86_MRST default n ---help--- Enable the FTL pseudo-filesystem used with the NAND Flash -- cgit v0.10.2 From 95c46ed9c99f9a3fc4954fc1b7cc1509a359efbb Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 24 Aug 2010 14:09:40 -0700 Subject: Staging: octeon: depends on NETDEVICES OCTEON_ETHERNET should depend on NETDEVICES. Fixes this kconfig warning: warning: (NET_DSA && NET && EXPERIMENTAL && NETDEVICES && !S390 || ... || OCTEON_ETHERNET && STAGING && !STAGING_EXCLUDE_BUILD && CPU_CAVIUM_OCTEON) selects PHYLIB which has unmet direct dependencies (!S390 && NETDEVICES) Reported-by: Arnaud Lacombe Signed-off-by: Randy Dunlap Cc: support@caviumnetworks.com Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/octeon/Kconfig b/drivers/staging/octeon/Kconfig index 638ad6b..9493128 100644 --- a/drivers/staging/octeon/Kconfig +++ b/drivers/staging/octeon/Kconfig @@ -1,6 +1,6 @@ config OCTEON_ETHERNET tristate "Cavium Networks Octeon Ethernet support" - depends on CPU_CAVIUM_OCTEON + depends on CPU_CAVIUM_OCTEON && NETDEVICES select PHYLIB select MDIO_OCTEON help -- cgit v0.10.2 From aff3ea4e5d4b0280d1c631fcce048e7f009bc3e5 Mon Sep 17 00:00:00 2001 From: Karl Relton Date: Wed, 11 Aug 2010 18:16:08 +0100 Subject: Staging: wlan-ng: Explicitly set some fields in cfg80211 interface The cfg80211 api has introduced a few new fields. Rather than assume what cfg80211 api does by default, set these explicitly. Signed-off-by: Karl Relton Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 368c30a..4af83d5 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -219,6 +219,7 @@ int prism2_get_key(struct wiphy *wiphy, struct net_device *dev, return -ENOENT; params.key_len = len; params.key = wlandev->wep_keys[key_index]; + params.seq_len = 0; callback(cookie, ¶ms); @@ -735,6 +736,8 @@ struct wiphy *wlan_create_wiphy(struct device *dev, wlandevice_t *wlandev) priv->band.n_channels = ARRAY_SIZE(prism2_channels); priv->band.bitrates = priv->rates; priv->band.n_bitrates = ARRAY_SIZE(prism2_rates); + priv->band.band = IEEE80211_BAND_2GHZ; + priv->band.ht_cap.ht_supported = false; wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; set_wiphy_dev(wiphy, dev); -- cgit v0.10.2 From 7e7b41d2ff30ed7ad4bf401d18566e6f38e42e4f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 2 Sep 2010 21:32:32 -0400 Subject: drm/radeon/kms/evergreen: fix gpu hangs in userspace accel code These VGT regs need to be programmed via the ring rather than MMIO as on previous asics (r6xx/r7xx). Signed-off-by: Alex Deucher Cc: stable@kernel.org Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index fe31b0d..b8b7f01 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -675,6 +675,43 @@ static int evergreen_cp_load_microcode(struct radeon_device *rdev) return 0; } +static int evergreen_cp_start(struct radeon_device *rdev) +{ + int r; + uint32_t cp_me; + + r = radeon_ring_lock(rdev, 7); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + return r; + } + radeon_ring_write(rdev, PACKET3(PACKET3_ME_INITIALIZE, 5)); + radeon_ring_write(rdev, 0x1); + radeon_ring_write(rdev, 0x0); + radeon_ring_write(rdev, rdev->config.evergreen.max_hw_contexts - 1); + radeon_ring_write(rdev, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); + radeon_ring_write(rdev, 0); + radeon_ring_write(rdev, 0); + radeon_ring_unlock_commit(rdev); + + cp_me = 0xff; + WREG32(CP_ME_CNTL, cp_me); + + r = radeon_ring_lock(rdev, 4); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + return r; + } + /* init some VGT regs */ + radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); + radeon_ring_write(rdev, (VGT_VERTEX_REUSE_BLOCK_CNTL - PACKET3_SET_CONTEXT_REG_START) >> 2); + radeon_ring_write(rdev, 0xe); + radeon_ring_write(rdev, 0x10); + radeon_ring_unlock_commit(rdev); + + return 0; +} + int evergreen_cp_resume(struct radeon_device *rdev) { u32 tmp; @@ -719,7 +756,7 @@ int evergreen_cp_resume(struct radeon_device *rdev) rdev->cp.rptr = RREG32(CP_RB_RPTR); rdev->cp.wptr = RREG32(CP_RB_WPTR); - r600_cp_start(rdev); + evergreen_cp_start(rdev); rdev->cp.ready = true; r = radeon_ring_test(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 04f134d..afc18d8 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2119,10 +2119,7 @@ int r600_cp_start(struct radeon_device *rdev) } radeon_ring_write(rdev, PACKET3(PACKET3_ME_INITIALIZE, 5)); radeon_ring_write(rdev, 0x1); - if (rdev->family >= CHIP_CEDAR) { - radeon_ring_write(rdev, 0x0); - radeon_ring_write(rdev, rdev->config.evergreen.max_hw_contexts - 1); - } else if (rdev->family >= CHIP_RV770) { + if (rdev->family >= CHIP_RV770) { radeon_ring_write(rdev, 0x0); radeon_ring_write(rdev, rdev->config.rv770.max_hw_contexts - 1); } else { -- cgit v0.10.2 From 54bfe496cec7586f76f713a277435dd3ac6fd4c4 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 3 Sep 2010 15:52:53 -0400 Subject: drm/radeon/kms: fix tv-out on avivo asics digital underscan support regressed tv-out. fixes: https://bugs.freedesktop.org/show_bug.cgi?id=29985 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 71b3150..464a81a 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -332,6 +332,11 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc, args.usV_SyncWidth = cpu_to_le16(mode->crtc_vsync_end - mode->crtc_vsync_start); + args.ucOverscanRight = radeon_crtc->h_border; + args.ucOverscanLeft = radeon_crtc->h_border; + args.ucOverscanBottom = radeon_crtc->v_border; + args.ucOverscanTop = radeon_crtc->v_border; + if (mode->flags & DRM_MODE_FLAG_NVSYNC) misc |= ATOM_VSYNC_POLARITY; if (mode->flags & DRM_MODE_FLAG_NHSYNC) @@ -1211,8 +1216,18 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; + struct drm_encoder *encoder; + bool is_tvcv = false; - /* TODO color tiling */ + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + /* find tv std */ + if (encoder->crtc == crtc) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + if (radeon_encoder->active_device & + (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) + is_tvcv = true; + } + } atombios_disable_ss(crtc); /* always set DCPLL */ @@ -1221,9 +1236,14 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, atombios_crtc_set_pll(crtc, adjusted_mode); atombios_enable_ss(crtc); - if (ASIC_IS_AVIVO(rdev)) + if (ASIC_IS_DCE4(rdev)) atombios_set_crtc_dtd_timing(crtc, adjusted_mode); - else { + else if (ASIC_IS_AVIVO(rdev)) { + if (is_tvcv) + atombios_crtc_set_timing(crtc, adjusted_mode); + else + atombios_set_crtc_dtd_timing(crtc, adjusted_mode); + } else { atombios_crtc_set_timing(crtc, adjusted_mode); if (radeon_crtc->crtc_id == 0) atombios_set_crtc_dtd_timing(crtc, adjusted_mode); -- cgit v0.10.2 From e58f637bb96d5a0ae0919b9998b891d1ba7e47c9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 20 Aug 2010 09:13:36 +0100 Subject: drm/kms: Add a module parameter to disable polling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Polling for a VGA device on an old system can be quite expensive, causing latencies on the order of 600ms. As we hold the mode mutex for this time and also need the same mutex to move the cursor, we trigger a user-visible stall. The real solution would involve improving the granulatity of the locking and so perhaps performing some of the probing not under the lock or some other updates can be done under different locks. Also reducing the cost of probing for a non-existent monitor would be worthwhile. However, exposing a parameter to disable polling is a simple workaround in the meantime. In order to accommodate users turning polling on and off at runtime, the polling is potentially re-enabled on every probe. This is coupled to the user calling xrandr, which seems to be a vaild time to reset the polling timeout since the information on the connection has just been updated. (The presumption being that all connections are probed in a single xrandr pass, which is currently valid.) References: Bug 29536 - 2.6.35 causes ~600ms latency every 10s https://bugs.freedesktop.org/show_bug.cgi?id=29536 Bug 16265 - Why is kslowd accumulating so much CPU time? https://bugzilla.kernel.org/show_bug.cgi?id=16265 Signed-off-by: Chris Wilson Reported-and-tested-by: Bruno Prémont Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 7e31d43..06fc0bc 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -34,6 +34,9 @@ #include "drm_crtc_helper.h" #include "drm_fb_helper.h" +static bool drm_kms_helper_poll = true; +module_param_named(poll, drm_kms_helper_poll, bool, 0600); + static void drm_mode_validate_flag(struct drm_connector *connector, int flags) { @@ -99,8 +102,10 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, connector->status = connector_status_disconnected; if (connector->funcs->force) connector->funcs->force(connector); - } else + } else { connector->status = connector->funcs->detect(connector); + drm_helper_hpd_irq_event(dev); + } if (connector->status == connector_status_disconnected) { DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n", @@ -840,6 +845,9 @@ static void output_poll_execute(struct work_struct *work) enum drm_connector_status old_status, status; bool repoll = false, changed = false; + if (!drm_kms_helper_poll) + return; + mutex_lock(&dev->mode_config.mutex); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { @@ -890,6 +898,9 @@ void drm_kms_helper_poll_enable(struct drm_device *dev) bool poll = false; struct drm_connector *connector; + if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll) + return; + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { if (connector->polled) poll = true; @@ -919,8 +930,10 @@ void drm_helper_hpd_irq_event(struct drm_device *dev) { if (!dev->mode_config.poll_enabled) return; + /* kill timer and schedule immediate execution, this doesn't block */ cancel_delayed_work(&dev->mode_config.output_poll_work); - queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, 0); + if (drm_kms_helper_poll) + queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, 0); } EXPORT_SYMBOL(drm_helper_hpd_irq_event); -- cgit v0.10.2 From c7ef35a960369bcad733b92868e4befe03ba9234 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 5 Sep 2010 16:55:25 +0100 Subject: drm: Do not force 1024x768 modes on unknown connectors Only fallback to a set of default modes on a connector iff that connector is known to be connected. The issue occurs that with limited hardware which cannot probe a connector and so reports the connector status as unknown will then attempt to retrieve the modes for it during drm_helper_probe_single_connector_modes(). Should that fail, the helper then generates a default set which fools the fb_helper and causes havoc with the console and beyond. Signed-off-by: Chris Wilson Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 06fc0bc..d2ab01e 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -115,11 +115,10 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, } count = (*connector_funcs->get_modes)(connector); - if (!count) { + if (count == 0 && connector->status == connector_status_connected) count = drm_add_modes_noedid(connector, 1024, 768); - if (!count) - return 0; - } + if (count == 0) + goto prune; drm_mode_connector_list_update(connector); -- cgit v0.10.2 From e167976ee7f5fe4b80f7e8f55e087f6c67cf9562 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 24 Aug 2010 16:35:52 -0700 Subject: drivers/gpu/drm/i915/intel_overlay.c needs seq_file.h drivers/gpu/drm/i915/intel_overlay.c: In function 'intel_overlay_print_error_state': drivers/gpu/drm/i915/intel_overlay.c:1467: error: implicit declaration of function 'seq_printf' Addresses https://bugzilla.kernel.org/show_bug.cgi?id=16811 Reported-by: Martin Ziegler Cc: Chris Wilson Cc: Daniel Vetter Cc: Eric Anholt Cc: Dave Airlie Cc: Andre Muller Signed-off-by: Andrew Morton Signed-off-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 4f00390..1d306a4 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -25,6 +25,8 @@ * * Derived from Xorg ddx, xf86-video-intel, src/i830_video.c */ + +#include #include "drmP.h" #include "drm.h" #include "i915_drm.h" -- cgit v0.10.2 From 1dfd9754cd55e424f247d9a2e855ad384e3e90ef Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 6 Sep 2010 14:44:14 +0100 Subject: Revert "drm/i915: Unreference object not handle on creation" This reverts commit 86f100b136626e91f4f66f3776303475e2e58998. The kref API requires the handlecount to be initialised to one on object creation (so that kref_get() doesn't complain upon first use) so the dalliance in the drivers is required in order to sink the initial floating reference. Signed-off-by: Chris Wilson Cc: stable@kernel.org diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index df5a713..68526f4 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -135,12 +135,15 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data, return -ENOMEM; ret = drm_gem_handle_create(file_priv, obj, &handle); - drm_gem_object_unreference_unlocked(obj); - if (ret) + if (ret) { + drm_gem_object_unreference_unlocked(obj); return ret; + } - args->handle = handle; + /* Sink the floating reference from kref_init(handlecount) */ + drm_gem_object_handle_unreference_unlocked(obj); + args->handle = handle; return 0; } -- cgit v0.10.2 From c74696b9c890074c1e1ee3d7496fc71eb3680ced Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Thu, 2 Sep 2010 14:46:34 -0400 Subject: i915: revert some checks added by commit 32aad86f This fixes blur-like screen corruption on the following card: VGA compatible controller [0300]: Intel Corporation 82G33/G31 Express Integrated Graphics Controller [8086:29c2] (rev 10) intel_sdvo_mode_set() should not return prematurely just because some features are not supported. https://bugzilla.kernel.org/show_bug.cgi?id=17151 Signed-off-by: Pavel Roskin Reported-by: Jonathan Corbet Reviewed-by: Chris Wilson [ickle: Relax a couple more checks for failing LVDS modesetting] Signed-off-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 093e914..62d22ae 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1061,8 +1061,9 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, mode)) return false; - if (!intel_sdvo_set_input_timings_for_mode(intel_sdvo, mode, adjusted_mode)) - return false; + (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo, + mode, + adjusted_mode); } else if (intel_sdvo->is_lvds) { drm_mode_set_crtcinfo(intel_sdvo->sdvo_lvds_fixed_mode, 0); @@ -1070,8 +1071,9 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, intel_sdvo->sdvo_lvds_fixed_mode)) return false; - if (!intel_sdvo_set_input_timings_for_mode(intel_sdvo, mode, adjusted_mode)) - return false; + (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo, + mode, + adjusted_mode); } /* Make the CRTC code factor in the SDVO pixel multiplier. The @@ -1108,10 +1110,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, in_out.in0 = intel_sdvo->attached_output; in_out.in1 = 0; - if (!intel_sdvo_set_value(intel_sdvo, - SDVO_CMD_SET_IN_OUT_MAP, - &in_out, sizeof(in_out))) - return; + intel_sdvo_set_value(intel_sdvo, + SDVO_CMD_SET_IN_OUT_MAP, + &in_out, sizeof(in_out)); if (intel_sdvo->is_hdmi) { if (!intel_sdvo_set_avi_infoframe(intel_sdvo, mode)) @@ -1122,11 +1123,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, /* We have tried to get input timing in mode_fixup, and filled into adjusted_mode */ - if (intel_sdvo->is_tv || intel_sdvo->is_lvds) { - intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); + intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); + if (intel_sdvo->is_tv || intel_sdvo->is_lvds) input_dtd.part2.sdvo_flags = intel_sdvo->sdvo_flags; - } else - intel_sdvo_get_dtd_from_mode(&input_dtd, mode); /* If it's a TV, we already set the output timing in mode_fixup. * Otherwise, the output timing is equal to the input timing. @@ -1137,8 +1136,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, intel_sdvo->attached_output)) return; - if (!intel_sdvo_set_output_timing(intel_sdvo, &input_dtd)) - return; + (void) intel_sdvo_set_output_timing(intel_sdvo, &input_dtd); } /* Set the input timing to the screen. Assume always input 0. */ @@ -1165,8 +1163,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, intel_sdvo_set_input_timing(encoder, &input_dtd); } #else - if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd)) - return; + (void) intel_sdvo_set_input_timing(intel_sdvo, &input_dtd); #endif sdvo_pixel_multiply = intel_sdvo_get_pixel_multiplier(mode); -- cgit v0.10.2 From 4f233eff6f32745f8894eb513bc59851213c7833 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Sat, 4 Sep 2010 19:24:04 +0300 Subject: i915: Fix spurious TV detection after 9d0498a2bf + 9559fcdbff Partial revert of 9d0498a2bf. Signed-off-by: Pekka Enberg Tested-by: Hugh Dickins Tested-by: Sven Joachim Signed-off-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index d2029ef..c671f60 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1231,7 +1231,6 @@ intel_tv_detect_type (struct intel_tv *intel_tv) struct drm_encoder *encoder = &intel_tv->base.enc; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); unsigned long irqflags; u32 tv_ctl, save_tv_ctl; u32 tv_dac, save_tv_dac; @@ -1268,11 +1267,15 @@ intel_tv_detect_type (struct intel_tv *intel_tv) DAC_C_0_7_V); I915_WRITE(TV_CTL, tv_ctl); I915_WRITE(TV_DAC, tv_dac); - intel_wait_for_vblank(dev, intel_crtc->pipe); + POSTING_READ(TV_DAC); + msleep(20); + tv_dac = I915_READ(TV_DAC); I915_WRITE(TV_DAC, save_tv_dac); I915_WRITE(TV_CTL, save_tv_ctl); - intel_wait_for_vblank(dev, intel_crtc->pipe); + POSTING_READ(TV_CTL); + msleep(20); + /* * A B C * 0 1 1 Composite -- cgit v0.10.2 From 300387c0b57d75e5218e2881d6ad2720657a8bcf Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 5 Sep 2010 20:25:43 +0100 Subject: drm/i915: Clear the vblank status bit before polling for the next vblank The vblank status bit is a sticky bit that must be cleared with a write of '1' prior to polling for the next vblank. Signed-off-by: Chris Wilson Tested-by: Sitsofe Wheeler jbarnes: I'd still rather see a lock, but I think you're right that we don't generally wait in code that needs not to miss an interrupt. Reviewed-by: Jesse Barnes diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 11a3394..3fc767b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -990,6 +990,22 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe) struct drm_i915_private *dev_priv = dev->dev_private; int pipestat_reg = (pipe == 0 ? PIPEASTAT : PIPEBSTAT); + /* Clear existing vblank status. Note this will clear any other + * sticky status fields as well. + * + * This races with i915_driver_irq_handler() with the result + * that either function could miss a vblank event. Here it is not + * fatal, as we will either wait upon the next vblank interrupt or + * timeout. Generally speaking intel_wait_for_vblank() is only + * called during modeset at which time the GPU should be idle and + * should *not* be performing page flips and thus not waiting on + * vblanks... + * Currently, the result of us stealing a vblank from the irq + * handler is that a single frame will be skipped during swapbuffers. + */ + I915_WRITE(pipestat_reg, + I915_READ(pipestat_reg) | PIPE_VBLANK_INTERRUPT_STATUS); + /* Wait for vblank interrupt bit to set */ if (wait_for((I915_READ(pipestat_reg) & PIPE_VBLANK_INTERRUPT_STATUS), -- cgit v0.10.2 From 9f82d23846146990d475f6753be733e55788d88d Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 30 Aug 2010 21:25:23 +0200 Subject: drm/i915: overlay on gen2 can't address above 1G So set the coherent dma mask accordingly. This dma mask is only used for physical objects, so it won't really matter allocation-wise. Now this never really surfaced because sane 32bit kernels only have 1G of lowmem. But some eager testers (distros?) still carry around the patch to adjust lowmem via a kconfig option. And the kernel seems to favour high allocations on boot-up, hence the overlay blowing up reliably. Because the patch is tiny and nicely shows how broken gen2 is it's imho worth to merge despite the fact that mucking around with the lowmem/ highmem division is (no longer) supported. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=28318 Cc: stable@kernel.org Signed-off-by: Daniel Vetter Signed-off-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index a7ec93e..7796f45 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -2082,6 +2082,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto free_priv; } + /* overlay on gen2 is broken and can't address above 1G */ + if (IS_GEN2(dev)) + dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(30)); + dev_priv->regs = ioremap(base, size); if (!dev_priv->regs) { DRM_ERROR("failed to map registers\n"); -- cgit v0.10.2 From df51e7aa2cf204e3a65657a1d60b96cfda133e9b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 4 Sep 2010 14:57:27 +0100 Subject: agp/intel: Promote warning about failure to setup flush to error. Make sure we always detect when we fail to correctly allocate the Isoch Flush Page and print an error to warn the user about the likely memory corruption that will result in invalid rendering or worse. Signed-off-by: Chris Wilson Cc: stable@kernel.org diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index d22ffb8..ce536e6 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1068,11 +1068,11 @@ static void intel_i9xx_setup_flush(void) intel_i915_setup_chipset_flush(); } - if (intel_private.ifp_resource.start) { + if (intel_private.ifp_resource.start) intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE); - if (!intel_private.i9xx_flush_page) - dev_info(&intel_private.pcidev->dev, "can't ioremap flush page - no chipset flushing"); - } + if (!intel_private.i9xx_flush_page) + dev_err(&intel_private.pcidev->dev, + "can't ioremap flush page - no chipset flushing\n"); } static int intel_i9xx_configure(void) -- cgit v0.10.2 From 9927a403ca8c97798129953fa9cbb5dc259c7cb9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 19 Jun 2010 15:12:51 +0200 Subject: i915: return -EFAULT if copy_to_user fails copy_to_user returns the number of bytes remaining to be copied, but we want to return a negative error code here. These are returned to userspace. Signed-off-by: Dan Carpenter Signed-off-by: Chris Wilson Cc: stable@kernel.org diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 7796f45..051c4db 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -620,8 +620,10 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, ret = copy_from_user(cliprects, batch->cliprects, batch->num_cliprects * sizeof(struct drm_clip_rect)); - if (ret != 0) + if (ret != 0) { + ret = -EFAULT; goto fail_free; + } } mutex_lock(&dev->struct_mutex); @@ -662,8 +664,10 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, return -ENOMEM; ret = copy_from_user(batch_data, cmdbuf->buf, cmdbuf->sz); - if (ret != 0) + if (ret != 0) { + ret = -EFAULT; goto fail_batch_free; + } if (cmdbuf->num_cliprects) { cliprects = kcalloc(cmdbuf->num_cliprects, @@ -676,8 +680,10 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, ret = copy_from_user(cliprects, cmdbuf->cliprects, cmdbuf->num_cliprects * sizeof(struct drm_clip_rect)); - if (ret != 0) + if (ret != 0) { + ret = -EFAULT; goto fail_clip_free; + } } mutex_lock(&dev->struct_mutex); -- cgit v0.10.2 From c877cdce93a44eea96f6cf7fc04be7d0372db2be Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 23 Jun 2010 19:03:01 +0200 Subject: i915: return -EFAULT if copy_to_user fails copy_to_user() returns the number of bytes remaining to be copied and I'm pretty sure we want to return a negative error code here. Signed-off-by: Dan Carpenter Signed-off-by: Chris Wilson Cc: stable@kernel.org diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 68526f4..748c263 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3588,6 +3588,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, if (ret != 0) { DRM_ERROR("copy %d cliprects failed: %d\n", args->num_cliprects, ret); + ret = -EFAULT; goto pre_mutex_err; } } -- cgit v0.10.2 From c96c3a8cb7fadcb33d9a5ebe35fcee8b7d0a7946 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 11 Aug 2010 09:59:24 +0100 Subject: drm/i915: Include a generation number in the device info To simplify the IS_GEN[234] macros and to enable switching. Signed-off-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 00befce..5363985 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -61,91 +61,86 @@ extern int intel_agp_enabled; .driver_data = (unsigned long) info } static const struct intel_device_info intel_i830_info = { - .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1, + .gen = 2, .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1, }; static const struct intel_device_info intel_845g_info = { - .is_i8xx = 1, + .gen = 2, .is_i8xx = 1, }; static const struct intel_device_info intel_i85x_info = { - .is_i8xx = 1, .is_i85x = 1, .is_mobile = 1, + .gen = 2, .is_i8xx = 1, .is_i85x = 1, .is_mobile = 1, .cursor_needs_physical = 1, }; static const struct intel_device_info intel_i865g_info = { - .is_i8xx = 1, + .gen = 2, .is_i8xx = 1, }; static const struct intel_device_info intel_i915g_info = { - .is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1, + .gen = 3, .is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1, }; static const struct intel_device_info intel_i915gm_info = { - .is_i9xx = 1, .is_mobile = 1, + .gen = 3, .is_i9xx = 1, .is_mobile = 1, .cursor_needs_physical = 1, }; static const struct intel_device_info intel_i945g_info = { - .is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1, + .gen = 3, .is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1, }; static const struct intel_device_info intel_i945gm_info = { - .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1, + .gen = 3, .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1, .has_hotplug = 1, .cursor_needs_physical = 1, }; static const struct intel_device_info intel_i965g_info = { - .is_broadwater = 1, .is_i965g = 1, .is_i9xx = 1, .has_hotplug = 1, + .gen = 4, .is_broadwater = 1, .is_i965g = 1, .is_i9xx = 1, + .has_hotplug = 1, }; static const struct intel_device_info intel_i965gm_info = { - .is_crestline = 1, .is_i965g = 1, .is_i965gm = 1, .is_i9xx = 1, - .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1, - .has_hotplug = 1, + .gen = 4, .is_crestline = 1, .is_i965g = 1, .is_i965gm = 1, .is_i9xx = 1, + .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1, }; static const struct intel_device_info intel_g33_info = { - .is_g33 = 1, .is_i9xx = 1, .need_gfx_hws = 1, - .has_hotplug = 1, + .gen = 3, .is_g33 = 1, .is_i9xx = 1, + .need_gfx_hws = 1, .has_hotplug = 1, }; static const struct intel_device_info intel_g45_info = { - .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1, - .has_pipe_cxsr = 1, - .has_hotplug = 1, + .gen = 4, .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1, + .has_pipe_cxsr = 1, .has_hotplug = 1, }; static const struct intel_device_info intel_gm45_info = { - .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, + .gen = 4, .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, - .has_pipe_cxsr = 1, - .has_hotplug = 1, + .has_pipe_cxsr = 1, .has_hotplug = 1, }; static const struct intel_device_info intel_pineview_info = { - .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1, - .need_gfx_hws = 1, - .has_hotplug = 1, + .gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1, + .need_gfx_hws = 1, .has_hotplug = 1, }; static const struct intel_device_info intel_ironlake_d_info = { - .is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1, - .has_pipe_cxsr = 1, - .has_hotplug = 1, + .gen = 5, .is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1, + .need_gfx_hws = 1, .has_pipe_cxsr = 1, .has_hotplug = 1, }; static const struct intel_device_info intel_ironlake_m_info = { - .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1, - .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, - .has_hotplug = 1, + .gen = 5, .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1, + .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1, }; static const struct intel_device_info intel_sandybridge_d_info = { - .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1, - .has_hotplug = 1, .is_gen6 = 1, + .gen = 6, .is_i965g = 1, .is_i9xx = 1, + .need_gfx_hws = 1, .has_hotplug = 1, }; static const struct intel_device_info intel_sandybridge_m_info = { - .is_i965g = 1, .is_mobile = 1, .is_i9xx = 1, .need_gfx_hws = 1, - .has_hotplug = 1, .is_gen6 = 1, + .gen = 6, .is_i965g = 1, .is_mobile = 1, .is_i9xx = 1, + .need_gfx_hws = 1, .has_hotplug = 1, }; static const struct pci_device_id pciidlist[] = { /* aka */ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 047cd7c..af4a263 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -191,6 +191,7 @@ struct drm_i915_display_funcs { }; struct intel_device_info { + u8 gen; u8 is_mobile : 1; u8 is_i8xx : 1; u8 is_i85x : 1; @@ -206,7 +207,6 @@ struct intel_device_info { u8 is_broadwater : 1; u8 is_crestline : 1; u8 is_ironlake : 1; - u8 is_gen6 : 1; u8 has_fbc : 1; u8 has_rc6 : 1; u8 has_pipe_cxsr : 1; @@ -1162,7 +1162,6 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove #define IS_845G(dev) ((dev)->pci_device == 0x2562) #define IS_I85X(dev) (INTEL_INFO(dev)->is_i85x) #define IS_I865G(dev) ((dev)->pci_device == 0x2572) -#define IS_GEN2(dev) (INTEL_INFO(dev)->is_i8xx) #define IS_I915G(dev) (INTEL_INFO(dev)->is_i915g) #define IS_I915GM(dev) ((dev)->pci_device == 0x2592) #define IS_I945G(dev) ((dev)->pci_device == 0x2772) @@ -1181,27 +1180,13 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove #define IS_IRONLAKE_M(dev) ((dev)->pci_device == 0x0046) #define IS_IRONLAKE(dev) (INTEL_INFO(dev)->is_ironlake) #define IS_I9XX(dev) (INTEL_INFO(dev)->is_i9xx) -#define IS_GEN6(dev) (INTEL_INFO(dev)->is_gen6) #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) -#define IS_GEN3(dev) (IS_I915G(dev) || \ - IS_I915GM(dev) || \ - IS_I945G(dev) || \ - IS_I945GM(dev) || \ - IS_G33(dev) || \ - IS_PINEVIEW(dev)) -#define IS_GEN4(dev) ((dev)->pci_device == 0x2972 || \ - (dev)->pci_device == 0x2982 || \ - (dev)->pci_device == 0x2992 || \ - (dev)->pci_device == 0x29A2 || \ - (dev)->pci_device == 0x2A02 || \ - (dev)->pci_device == 0x2A12 || \ - (dev)->pci_device == 0x2E02 || \ - (dev)->pci_device == 0x2E12 || \ - (dev)->pci_device == 0x2E22 || \ - (dev)->pci_device == 0x2E32 || \ - (dev)->pci_device == 0x2A42 || \ - (dev)->pci_device == 0x2E42) +#define IS_GEN2(dev) (INTEL_INFO(dev)->gen == 2) +#define IS_GEN3(dev) (INTEL_INFO(dev)->gen == 3) +#define IS_GEN4(dev) (INTEL_INFO(dev)->gen == 4) +#define IS_GEN5(dev) (INTEL_INFO(dev)->gen == 5) +#define IS_GEN6(dev) (INTEL_INFO(dev)->gen == 6) #define HAS_BSD(dev) (IS_IRONLAKE(dev) || IS_G4X(dev)) #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) -- cgit v0.10.2 From 52e68630d13f9668f8f4dd6978fa41039bacfaf6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 8 Aug 2010 10:15:59 +0100 Subject: drm/i915: Fix offset page-flips on i965+ i965 uses the Display Registers to compute the offset from the display base so the new base does not need adjusting when flipping. The older chipsets use a fence to access the display and so do perceive the surface as linear and have a single base register which is reprogrammed using the flip. Signed-off-by: Chris Wilson Cc: Jesse Barnes Reported-by: Marty Jack Reviewed-by: Jesse Barnes diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3fc767b..334665c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5042,9 +5042,9 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_unpin_work *work; unsigned long flags, offset; - int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC; - int ret, pipesrc; - u32 flip_mask; + int pipe = intel_crtc->pipe; + u32 pf, pipesrc; + int ret; work = kzalloc(sizeof *work, GFP_KERNEL); if (work == NULL) @@ -5093,12 +5093,14 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, atomic_inc(&obj_priv->pending_flip); work->pending_flip_obj = obj; - if (intel_crtc->plane) - flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; - else - flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; - if (IS_GEN3(dev) || IS_GEN2(dev)) { + u32 flip_mask; + + if (intel_crtc->plane) + flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; + else + flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; + BEGIN_LP_RING(2); OUT_RING(MI_WAIT_FOR_EVENT | flip_mask); OUT_RING(0); @@ -5106,29 +5108,56 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, } /* Offset into the new buffer for cases of shared fbs between CRTCs */ - offset = obj_priv->gtt_offset; - offset += (crtc->y * fb->pitch) + (crtc->x * (fb->bits_per_pixel) / 8); + offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8; BEGIN_LP_RING(4); - if (IS_I965G(dev)) { + switch(INTEL_INFO(dev)->gen) { + case 2: OUT_RING(MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); OUT_RING(fb->pitch); - OUT_RING(offset | obj_priv->tiling_mode); - pipesrc = I915_READ(pipesrc_reg); - OUT_RING(pipesrc & 0x0fff0fff); - } else if (IS_GEN3(dev)) { + OUT_RING(obj_priv->gtt_offset + offset); + OUT_RING(MI_NOOP); + break; + + case 3: OUT_RING(MI_DISPLAY_FLIP_I915 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); OUT_RING(fb->pitch); - OUT_RING(offset); + OUT_RING(obj_priv->gtt_offset + offset); OUT_RING(MI_NOOP); - } else { + break; + + case 4: + case 5: + /* i965+ uses the linear or tiled offsets from the + * Display Registers (which do not change across a page-flip) + * so we need only reprogram the base address. + */ OUT_RING(MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); OUT_RING(fb->pitch); - OUT_RING(offset); - OUT_RING(MI_NOOP); + OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode); + + /* XXX Enabling the panel-fitter across page-flip is so far + * untested on non-native modes, so ignore it for now. + * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE; + */ + pf = 0; + pipesrc = I915_READ(pipe == 0 ? PIPEASRC : PIPEBSRC) & 0x0fff0fff; + OUT_RING(pf | pipesrc); + break; + + case 6: + OUT_RING(MI_DISPLAY_FLIP | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); + OUT_RING(fb->pitch | obj_priv->tiling_mode); + OUT_RING(obj_priv->gtt_offset); + + pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE; + pipesrc = I915_READ(pipe == 0 ? PIPEASRC : PIPEBSRC) & 0x0fff0fff; + OUT_RING(pf | pipesrc); + break; } ADVANCE_LP_RING(); -- cgit v0.10.2 From 4e6cfefc729be2aa20647415317577ed98d4f7bf Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 8 Aug 2010 13:20:19 +0100 Subject: drm/i915: Re-use set_base_atomic to share setting of the display registers Lets try to avoid repeating old bugs. Signed-off-by: Chris Wilson Reviewed-by: Jesse Barnes diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 334665c..cbb5093 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1502,7 +1502,7 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, dspcntr &= ~DISPPLANE_TILED; } - if (IS_IRONLAKE(dev)) + if (HAS_PCH_SPLIT(dev)) /* must disable */ dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; @@ -1511,20 +1511,19 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, Start = obj_priv->gtt_offset; Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8); - DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); + DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", + Start, Offset, x, y, fb->pitch); I915_WRITE(dspstride, fb->pitch); if (IS_I965G(dev)) { - I915_WRITE(dspbase, Offset); - I915_READ(dspbase); I915_WRITE(dspsurf, Start); - I915_READ(dspsurf); I915_WRITE(dsptileoff, (y << 16) | x); + I915_WRITE(dspbase, Offset); } else { I915_WRITE(dspbase, Start + Offset); - I915_READ(dspbase); } + POSTING_READ(dspbase); - if ((IS_I965G(dev) || plane == 0)) + if (IS_I965G(dev) || plane == 0) intel_update_fbc(crtc, &crtc->mode); intel_wait_for_vblank(dev, intel_crtc->pipe); @@ -1538,7 +1537,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb) { struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_master_private *master_priv; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_framebuffer *intel_fb; @@ -1546,13 +1544,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_gem_object *obj; int pipe = intel_crtc->pipe; int plane = intel_crtc->plane; - unsigned long Start, Offset; - int dspbase = (plane == 0 ? DSPAADDR : DSPBADDR); - int dspsurf = (plane == 0 ? DSPASURF : DSPBSURF); - int dspstride = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE; - int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF); - int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; - u32 dspcntr; int ret; /* no fb bound */ @@ -1588,71 +1579,18 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, return ret; } - dspcntr = I915_READ(dspcntr_reg); - /* Mask out pixel format bits in case we change it */ - dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; - switch (crtc->fb->bits_per_pixel) { - case 8: - dspcntr |= DISPPLANE_8BPP; - break; - case 16: - if (crtc->fb->depth == 15) - dspcntr |= DISPPLANE_15_16BPP; - else - dspcntr |= DISPPLANE_16BPP; - break; - case 24: - case 32: - if (crtc->fb->depth == 30) - dspcntr |= DISPPLANE_32BPP_30BIT_NO_ALPHA; - else - dspcntr |= DISPPLANE_32BPP_NO_ALPHA; - break; - default: - DRM_ERROR("Unknown color depth\n"); + ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y); + if (ret) { i915_gem_object_unpin(obj); mutex_unlock(&dev->struct_mutex); - return -EINVAL; - } - if (IS_I965G(dev)) { - if (obj_priv->tiling_mode != I915_TILING_NONE) - dspcntr |= DISPPLANE_TILED; - else - dspcntr &= ~DISPPLANE_TILED; - } - - if (HAS_PCH_SPLIT(dev)) - /* must disable */ - dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; - - I915_WRITE(dspcntr_reg, dspcntr); - - Start = obj_priv->gtt_offset; - Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); - - DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", - Start, Offset, x, y, crtc->fb->pitch); - I915_WRITE(dspstride, crtc->fb->pitch); - if (IS_I965G(dev)) { - I915_WRITE(dspsurf, Start); - I915_WRITE(dsptileoff, (y << 16) | x); - I915_WRITE(dspbase, Offset); - } else { - I915_WRITE(dspbase, Start + Offset); + return ret; } - POSTING_READ(dspbase); - - if ((IS_I965G(dev) || plane == 0)) - intel_update_fbc(crtc, &crtc->mode); - - intel_wait_for_vblank(dev, pipe); if (old_fb) { intel_fb = to_intel_framebuffer(old_fb); obj_priv = to_intel_bo(intel_fb->obj); i915_gem_object_unpin(intel_fb->obj); } - intel_increase_pllclock(crtc, true); mutex_unlock(&dev->struct_mutex); -- cgit v0.10.2 From 0ad6ef2c587dea59212c4e2ab3ec3b0067500a2a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 9 Aug 2010 17:21:44 +0100 Subject: drm/i915/dp: Boost timeout for enabling transcoder to 100ms Adam Hill reported that his Arrandale system required a much longer, up to 200x500us, wait for the panel to initialise or else modesetting would fail. References: https://bugs.freedesktop.org/show_bug.cgi?id=29141 Signed-off-by: Chris Wilson Reported-and-tested-by: Adam Hill diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index cbb5093..83c8545 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2069,7 +2069,7 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) I915_WRITE(transconf_reg, temp | TRANS_ENABLE); I915_READ(transconf_reg); - if (wait_for(I915_READ(transconf_reg) & TRANS_STATE_ENABLE, 10, 0)) + if (wait_for(I915_READ(transconf_reg) & TRANS_STATE_ENABLE, 100, 1)) DRM_ERROR("failed to enable transcoder\n"); } -- cgit v0.10.2 From b66d842467311ac3434aa19c5c41deaab8295bd0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 12 Aug 2010 15:26:41 +0100 Subject: drm/i915/sdvo: Restore guess of the DDC bus in absence of VBIOS If the VBIOS tells us the mapping of the SDVO device onto the DDC bus, use it. However, if there is no VBIOS available that mapping is uninitialised and we should fallback to our earlier guess. Fix regression introduced in b1083333 (which in turn is a fix for the regression caused by the introduction of this guess, 14571b4). References: Bug 29499 - [945GM] Screen disconnected because of missing VBIOS https://bugs.freedesktop.org/show_bug.cgi?id=29499 Bug 15109 - i945GM fails to detect EDID on DVI port https://bugzilla.kernel.org/show_bug.cgi?id=15109 Signed-off-by: Chris Wilson Reported-and-tested-by: Paul Neumann Cc: Adam Jackson Cc: Zhenyu Wang Cc: stable@kernel.org diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 62d22ae..e3b7a7e 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1929,6 +1929,41 @@ static const struct drm_encoder_funcs intel_sdvo_enc_funcs = { .destroy = intel_sdvo_enc_destroy, }; +static void +intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo) +{ + uint16_t mask = 0; + unsigned int num_bits; + + /* Make a mask of outputs less than or equal to our own priority in the + * list. + */ + switch (sdvo->controlled_output) { + case SDVO_OUTPUT_LVDS1: + mask |= SDVO_OUTPUT_LVDS1; + case SDVO_OUTPUT_LVDS0: + mask |= SDVO_OUTPUT_LVDS0; + case SDVO_OUTPUT_TMDS1: + mask |= SDVO_OUTPUT_TMDS1; + case SDVO_OUTPUT_TMDS0: + mask |= SDVO_OUTPUT_TMDS0; + case SDVO_OUTPUT_RGB1: + mask |= SDVO_OUTPUT_RGB1; + case SDVO_OUTPUT_RGB0: + mask |= SDVO_OUTPUT_RGB0; + break; + } + + /* Count bits to find what number we are in the priority list. */ + mask &= sdvo->caps.output_flags; + num_bits = hweight16(mask); + /* If more than 3 outputs, default to DDC bus 3 for now. */ + if (num_bits > 3) + num_bits = 3; + + /* Corresponds to SDVO_CONTROL_BUS_DDCx */ + sdvo->ddc_bus = 1 << num_bits; +} /** * Choose the appropriate DDC bus for control bus switch command for this @@ -1948,7 +1983,10 @@ intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv, else mapping = &(dev_priv->sdvo_mappings[1]); - sdvo->ddc_bus = 1 << ((mapping->ddc_pin & 0xf0) >> 4); + if (mapping->initialized) + sdvo->ddc_bus = 1 << ((mapping->ddc_pin & 0xf0) >> 4); + else + intel_sdvo_guess_ddc_bus(sdvo); } static bool -- cgit v0.10.2 From 4f7f7b7eb94bd37c449f06932459bbed78826f8d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 18 Aug 2010 18:12:56 +0100 Subject: drm/i915/dp: Really try 5 times before giving up. Only stop trying if the aux channel sucessfully reports that the transmission was completed, otherwise try again. On the 5th failure, bail and report that something is amiss. This fixes a sporadic failure in reading the EDID for my external panel over DP. Signed-off-by: Chris Wilson Cc: stable@kernel.org diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 9caccd0..51d1429 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -239,7 +239,6 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, uint32_t ch_data = ch_ctl + 4; int i; int recv_bytes; - uint32_t ctl; uint32_t status; uint32_t aux_clock_divider; int try, precharge; @@ -263,41 +262,43 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, else precharge = 5; + if (I915_READ(ch_ctl) & DP_AUX_CH_CTL_SEND_BUSY) { + DRM_ERROR("dp_aux_ch not started status 0x%08x\n", + I915_READ(ch_ctl)); + return -EBUSY; + } + /* Must try at least 3 times according to DP spec */ for (try = 0; try < 5; try++) { /* Load the send data into the aux channel data registers */ - for (i = 0; i < send_bytes; i += 4) { - uint32_t d = pack_aux(send + i, send_bytes - i); - - I915_WRITE(ch_data + i, d); - } - - ctl = (DP_AUX_CH_CTL_SEND_BUSY | - DP_AUX_CH_CTL_TIME_OUT_400us | - (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | - (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | - (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) | - DP_AUX_CH_CTL_DONE | - DP_AUX_CH_CTL_TIME_OUT_ERROR | - DP_AUX_CH_CTL_RECEIVE_ERROR); + for (i = 0; i < send_bytes; i += 4) + I915_WRITE(ch_data + i, + pack_aux(send + i, send_bytes - i)); /* Send the command and wait for it to complete */ - I915_WRITE(ch_ctl, ctl); - (void) I915_READ(ch_ctl); + I915_WRITE(ch_ctl, + DP_AUX_CH_CTL_SEND_BUSY | + DP_AUX_CH_CTL_TIME_OUT_400us | + (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | + (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | + (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) | + DP_AUX_CH_CTL_DONE | + DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR); for (;;) { - udelay(100); status = I915_READ(ch_ctl); if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) break; + udelay(100); } /* Clear done status and any errors */ - I915_WRITE(ch_ctl, (status | - DP_AUX_CH_CTL_DONE | - DP_AUX_CH_CTL_TIME_OUT_ERROR | - DP_AUX_CH_CTL_RECEIVE_ERROR)); - (void) I915_READ(ch_ctl); - if ((status & DP_AUX_CH_CTL_TIME_OUT_ERROR) == 0) + I915_WRITE(ch_ctl, + status | + DP_AUX_CH_CTL_DONE | + DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR); + if (status & DP_AUX_CH_CTL_DONE) break; } @@ -324,15 +325,12 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, /* Unload any bytes sent back from the other side */ recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT); - if (recv_bytes > recv_size) recv_bytes = recv_size; - for (i = 0; i < recv_bytes; i += 4) { - uint32_t d = I915_READ(ch_data + i); - - unpack_aux(d, recv + i, recv_bytes - i); - } + for (i = 0; i < recv_bytes; i += 4) + unpack_aux(I915_READ(ch_data + i), + recv + i, recv_bytes - i); return recv_bytes; } -- cgit v0.10.2 From a25c25c2a2aa55e609099a9f74453c518aec29a6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 20 Aug 2010 14:36:45 +0100 Subject: drm/i915: Allocate the PCI resource for the MCHBAR We were failing when trying to allocate the resource for MMIO of the MCHBAR because we forgot to specify what type of resource we wanted. Signed-off-by: Chris Wilson Cc: Jesse Barnes Cc: stable@kernel.org Reviewed-by: Jesse Barnes diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 051c4db..9d67b48 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -891,7 +891,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev) int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915; u32 temp_lo, temp_hi = 0; u64 mchbar_addr; - int ret = 0; + int ret; if (IS_I965G(dev)) pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi); @@ -901,22 +901,23 @@ intel_alloc_mchbar_resource(struct drm_device *dev) /* If ACPI doesn't have it, assume we need to allocate it ourselves */ #ifdef CONFIG_PNP if (mchbar_addr && - pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) { - ret = 0; - goto out; - } + pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) + return 0; #endif /* Get some space for it */ - ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus, &dev_priv->mch_res, + dev_priv->mch_res.name = "i915 MCHBAR"; + dev_priv->mch_res.flags = IORESOURCE_MEM; + ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus, + &dev_priv->mch_res, MCHBAR_SIZE, MCHBAR_SIZE, PCIBIOS_MIN_MEM, - 0, pcibios_align_resource, + 0, pcibios_align_resource, dev_priv->bridge_dev); if (ret) { DRM_DEBUG_DRIVER("failed bus alloc: %d\n", ret); dev_priv->mch_res.start = 0; - goto out; + return ret; } if (IS_I965G(dev)) @@ -925,8 +926,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev) pci_write_config_dword(dev_priv->bridge_dev, reg, lower_32_bits(dev_priv->mch_res.start)); -out: - return ret; + return 0; } /* Setup MCHBAR if possible, return true if we should disable it again */ -- cgit v0.10.2 From 8e647a279ca30029f19eca646de08a6338eab924 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 22 Aug 2010 10:54:23 +0100 Subject: drm/i915: Tightly scope intel_encoder to prevent invalid use We reset intel_encoder for every matching encoder whilst iterating over the encoders attached to this crtc when changing mode. As such in a cloned configuration intel_encoder may not correspond to the correct is_edp encoder. By scoping intel_encoder to the loop, not only is the compiler able to spot this mistake, we also improve readiability for ourselves. [It might not be a mistake, within this function it is unclear as to whether it is permissable for eDP to be cloned...] Signed-off-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 83c8545..0b90443 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3508,10 +3508,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, u32 dpll = 0, fp = 0, fp2 = 0, dspcntr, pipeconf; bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false; bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; - bool is_edp = false; + struct intel_encoder *has_edp_encoder = NULL; struct drm_mode_config *mode_config = &dev->mode_config; struct drm_encoder *encoder; - struct intel_encoder *intel_encoder = NULL; const intel_limit_t *limit; int ret; struct fdi_m_n m_n = {0}; @@ -3532,12 +3531,12 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, drm_vblank_pre_modeset(dev, pipe); list_for_each_entry(encoder, &mode_config->encoder_list, head) { + struct intel_encoder *intel_encoder; - if (!encoder || encoder->crtc != crtc) + if (encoder->crtc != crtc) continue; intel_encoder = enc_to_intel_encoder(encoder); - switch (intel_encoder->type) { case INTEL_OUTPUT_LVDS: is_lvds = true; @@ -3561,7 +3560,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, is_dp = true; break; case INTEL_OUTPUT_EDP: - is_edp = true; + has_edp_encoder = intel_encoder; break; } @@ -3639,10 +3638,10 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, int lane = 0, link_bw, bpp; /* eDP doesn't require FDI link, so just set DP M/N according to current link config */ - if (is_edp) { + if (has_edp_encoder) { target_clock = mode->clock; - intel_edp_link_config(intel_encoder, - &lane, &link_bw); + intel_edp_link_config(has_edp_encoder, + &lane, &link_bw); } else { /* DP over FDI requires target mode clock instead of link clock */ @@ -3663,7 +3662,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, temp |= PIPE_8BPC; else temp |= PIPE_6BPC; - } else if (is_edp || (is_dp && intel_pch_has_edp(crtc))) { + } else if (has_edp_encoder || (is_dp && intel_pch_has_edp(crtc))) { switch (dev_priv->edp_bpp/3) { case 8: temp |= PIPE_8BPC; @@ -3736,7 +3735,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, udelay(200); - if (is_edp) { + if (has_edp_encoder) { if (dev_priv->lvds_use_ssc) { temp |= DREF_SSC1_ENABLE; I915_WRITE(PCH_DREF_CONTROL, temp); @@ -3885,7 +3884,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, dpll_reg = pch_dpll_reg; } - if (!is_edp) { + if (!has_edp_encoder) { I915_WRITE(fp_reg, fp); I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); I915_READ(dpll_reg); @@ -3980,7 +3979,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, } } - if (!is_edp) { + if (!has_edp_encoder) { I915_WRITE(fp_reg, fp); I915_WRITE(dpll_reg, dpll); I915_READ(dpll_reg); @@ -4059,7 +4058,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, I915_WRITE(link_m1_reg, m_n.link_m); I915_WRITE(link_n1_reg, m_n.link_n); - if (is_edp) { + if (has_edp_encoder) { ironlake_set_pll_edp(crtc, adjusted_mode->clock); } else { /* enable FDI RX PLL too */ -- cgit v0.10.2 From 4e5359cd053bfb7d8dabe4a63624a5726848ffbc Mon Sep 17 00:00:00 2001 From: Simon Farnsworth Date: Wed, 1 Sep 2010 17:47:52 +0100 Subject: drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt When we miss the flip prepare interrupt, we never get into the software state needed to restart userspace, resulting in a freeze of a full-screen OpenGL application (such as a compositor). Work around this by checking DSPxSURF/DSPxBASE to see if the page flip has actually happened. If it has, do the work we would have done when the flip prepare interrupt comes in. Also, add debugfs information to tell us what's going on (based on the patch from Chris Wilson attached to bugs.fdo bug #29798). Signed-off-by: Simon Farnsworth Signed-off-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 92d5605..5e43d70 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -31,6 +31,7 @@ #include #include "drmP.h" #include "drm.h" +#include "intel_drv.h" #include "i915_drm.h" #include "i915_drv.h" @@ -121,6 +122,54 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) return 0; } +static int i915_gem_pageflip_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + unsigned long flags; + struct intel_crtc *crtc; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { + const char *pipe = crtc->pipe ? "B" : "A"; + const char *plane = crtc->plane ? "B" : "A"; + struct intel_unpin_work *work; + + spin_lock_irqsave(&dev->event_lock, flags); + work = crtc->unpin_work; + if (work == NULL) { + seq_printf(m, "No flip due on pipe %s (plane %s)\n", + pipe, plane); + } else { + if (!work->pending) { + seq_printf(m, "Flip queued on pipe %s (plane %s)\n", + pipe, plane); + } else { + seq_printf(m, "Flip pending (waiting for vsync) on pipe %s (plane %s)\n", + pipe, plane); + } + if (work->enable_stall_check) + seq_printf(m, "Stall check enabled, "); + else + seq_printf(m, "Stall check waiting for page flip ioctl, "); + seq_printf(m, "%d prepares\n", work->pending); + + if (work->old_fb_obj) { + struct drm_i915_gem_object *obj_priv = to_intel_bo(work->old_fb_obj); + if(obj_priv) + seq_printf(m, "Old framebuffer gtt_offset 0x%08x\n", obj_priv->gtt_offset ); + } + if (work->pending_flip_obj) { + struct drm_i915_gem_object *obj_priv = to_intel_bo(work->pending_flip_obj); + if(obj_priv) + seq_printf(m, "New framebuffer gtt_offset 0x%08x\n", obj_priv->gtt_offset ); + } + } + spin_unlock_irqrestore(&dev->event_lock, flags); + } + + return 0; +} + static int i915_gem_request_info(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; @@ -777,6 +826,7 @@ static struct drm_info_list i915_debugfs_list[] = { {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST}, {"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST}, {"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST}, + {"i915_gem_pageflip", i915_gem_pageflip_info, 0}, {"i915_gem_request", i915_gem_request_info, 0}, {"i915_gem_seqno", i915_gem_seqno_info, 0}, {"i915_gem_fence_regs", i915_gem_fence_regs_info, 0}, diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 16861b8..59457e8 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -887,6 +887,49 @@ static void i915_handle_error(struct drm_device *dev, bool wedged) queue_work(dev_priv->wq, &dev_priv->error_work); } +static void i915_pageflip_stall_check(struct drm_device *dev, int pipe) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_i915_gem_object *obj_priv; + struct intel_unpin_work *work; + unsigned long flags; + bool stall_detected; + + /* Ignore early vblank irqs */ + if (intel_crtc == NULL) + return; + + spin_lock_irqsave(&dev->event_lock, flags); + work = intel_crtc->unpin_work; + + if (work == NULL || work->pending || !work->enable_stall_check) { + /* Either the pending flip IRQ arrived, or we're too early. Don't check */ + spin_unlock_irqrestore(&dev->event_lock, flags); + return; + } + + /* Potential stall - if we see that the flip has happened, assume a missed interrupt */ + obj_priv = to_intel_bo(work->pending_flip_obj); + if(IS_I965G(dev)) { + int dspsurf = intel_crtc->plane == 0 ? DSPASURF : DSPBSURF; + stall_detected = I915_READ(dspsurf) == obj_priv->gtt_offset; + } else { + int dspaddr = intel_crtc->plane == 0 ? DSPAADDR : DSPBADDR; + stall_detected = I915_READ(dspaddr) == (obj_priv->gtt_offset + + crtc->y * crtc->fb->pitch + + crtc->x * crtc->fb->bits_per_pixel/8); + } + + spin_unlock_irqrestore(&dev->event_lock, flags); + + if (stall_detected) { + DRM_DEBUG_DRIVER("Pageflip stall detected\n"); + intel_prepare_page_flip(dev, intel_crtc->plane); + } +} + irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; @@ -1004,15 +1047,19 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) if (pipea_stats & vblank_status) { vblank++; drm_handle_vblank(dev, 0); - if (!dev_priv->flip_pending_is_done) + if (!dev_priv->flip_pending_is_done) { + i915_pageflip_stall_check(dev, 0); intel_finish_page_flip(dev, 0); + } } if (pipeb_stats & vblank_status) { vblank++; drm_handle_vblank(dev, 1); - if (!dev_priv->flip_pending_is_done) + if (!dev_priv->flip_pending_is_done) { + i915_pageflip_stall_check(dev, 1); intel_finish_page_flip(dev, 1); + } } if ((pipea_stats & PIPE_LEGACY_BLC_EVENT_STATUS) || diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0b90443..1bd0c67 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4864,15 +4864,6 @@ static void intel_crtc_destroy(struct drm_crtc *crtc) kfree(intel_crtc); } -struct intel_unpin_work { - struct work_struct work; - struct drm_device *dev; - struct drm_gem_object *old_fb_obj; - struct drm_gem_object *pending_flip_obj; - struct drm_pending_vblank_event *event; - int pending; -}; - static void intel_unpin_work_fn(struct work_struct *__work) { struct intel_unpin_work *work = @@ -4960,7 +4951,8 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane) spin_lock_irqsave(&dev->event_lock, flags); if (intel_crtc->unpin_work) { - intel_crtc->unpin_work->pending = 1; + if ((++intel_crtc->unpin_work->pending) > 1) + DRM_ERROR("Prepared flip multiple times\n"); } else { DRM_DEBUG_DRIVER("preparing flip with no unpin work?\n"); } @@ -5044,6 +5036,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, ADVANCE_LP_RING(); } + work->enable_stall_check = true; + /* Offset into the new buffer for cases of shared fbs between CRTCs */ offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 0e92aa0..ad312ca 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -176,6 +176,16 @@ struct intel_crtc { #define enc_to_intel_encoder(x) container_of(x, struct intel_encoder, enc) #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) +struct intel_unpin_work { + struct work_struct work; + struct drm_device *dev; + struct drm_gem_object *old_fb_obj; + struct drm_gem_object *pending_flip_obj; + struct drm_pending_vblank_event *event; + int pending; + bool enable_stall_check; +}; + struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, const char *name); void intel_i2c_destroy(struct i2c_adapter *adapter); -- cgit v0.10.2 From 52be11964869c948fbbb9ec7845f9c52b0d3dc09 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 5 Sep 2010 10:01:13 +0100 Subject: drm/i915: Avoid use of uninitialised values when disabling panel-fitter We were passing garbage values into the panel-fitter control register when disabling it on Ironlake - those values (filter modes and reserved MBZ bits) would have then be re-used the next time panel-fitting was enabled. Signed-off-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1bd0c67..cf8d5e5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1865,9 +1865,6 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL; int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL; int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF; - int pf_ctl_reg = (pipe == 0) ? PFA_CTL_1 : PFB_CTL_1; - int pf_win_size = (pipe == 0) ? PFA_WIN_SZ : PFB_WIN_SZ; - int pf_win_pos = (pipe == 0) ? PFA_WIN_POS : PFB_WIN_POS; int cpu_htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; int cpu_hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; int cpu_hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; @@ -1936,15 +1933,19 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) } /* Enable panel fitting for LVDS */ - if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) - || HAS_eDP || intel_pch_has_edp(crtc)) { - if (dev_priv->pch_pf_size) { - temp = I915_READ(pf_ctl_reg); - I915_WRITE(pf_ctl_reg, temp | PF_ENABLE | PF_FILTER_MED_3x3); - I915_WRITE(pf_win_pos, dev_priv->pch_pf_pos); - I915_WRITE(pf_win_size, dev_priv->pch_pf_size); - } else - I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE); + if (dev_priv->pch_pf_size && + (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) + || HAS_eDP || intel_pch_has_edp(crtc))) { + /* Force use of hard-coded filter coefficients + * as some pre-programmed values are broken, + * e.g. x201. + */ + I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, + PF_ENABLE | PF_FILTER_MED_3x3); + I915_WRITE(pipe ? PFB_WIN_POS : PFA_WIN_POS, + dev_priv->pch_pf_pos); + I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, + dev_priv->pch_pf_size); } /* Enable CPU pipe */ @@ -2109,14 +2110,8 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) udelay(100); /* Disable PF */ - temp = I915_READ(pf_ctl_reg); - if ((temp & PF_ENABLE) != 0) { - I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE); - I915_READ(pf_ctl_reg); - } - I915_WRITE(pf_win_size, 0); - POSTING_READ(pf_win_size); - + I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, 0); + I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, 0); /* disable CPU FDI tx and PCH FDI rx */ temp = I915_READ(fdi_tx_reg); -- cgit v0.10.2 From 032d2a0d068b0368296a56469761394ef03207c3 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 6 Sep 2010 16:17:22 +0100 Subject: drm/i915: Prevent double dpms on Arguably this is a bug in drm-core in that we should not be called twice in succession with DPMS_ON, however this is still occuring and we see FDI link training failures on the second call leading to the occassional blank display. For the time being ignore the repeated call. Original patch by Dave Airlie Signed-off-by: Chris Wilson Cc: stable@kernel.org diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index cf8d5e5..40cc5da 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2370,6 +2370,9 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) int pipe = intel_crtc->pipe; bool enabled; + if (intel_crtc->dpms_mode == mode) + return; + intel_crtc->dpms_mode = mode; intel_crtc->cursor_on = mode == DRM_MODE_DPMS_ON; @@ -5164,7 +5167,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base; intel_crtc->cursor_addr = 0; - intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF; + intel_crtc->dpms_mode = -1; drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); intel_crtc->busy = false; -- cgit v0.10.2 From 8dfc2b14ebf538f28a05565f34913ecffedf5024 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Mon, 23 Aug 2010 14:37:52 +0800 Subject: agp/intel: fix physical address mask bits for sandybridge It should shift bit 39-32 into pte's bit 11-4. Reported-by:Takashi Iwai Signed-off-by: Zhenyu Wang Cc: stable@kernel.org Signed-off-by: Chris Wilson diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index ce536e6..7f35854 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1333,8 +1333,8 @@ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge, static unsigned long intel_gen6_mask_memory(struct agp_bridge_data *bridge, dma_addr_t addr, int type) { - /* Shift high bits down */ - addr |= (addr >> 28) & 0xff; + /* gen6 has bit11-4 for physical addr bit39-32 */ + addr |= (addr >> 28) & 0xff0; /* Type checking must be done elsewhere */ return addr | bridge->driver->masks[type].mask; -- cgit v0.10.2 From 93f5f7f1249e76a5e8afbdab53f90b10c41fdb61 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Fri, 27 Aug 2010 11:06:48 +0800 Subject: agp/intel: use #ifdef idiom for intel-agp.h Signed-off-by: Zhenyu Wang Cc: stable@kernel.org Signed-off-by: Chris Wilson diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index 08d4753..78124a8 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h @@ -1,6 +1,8 @@ /* * Common Intel AGPGART and GTT definitions. */ +#ifndef _INTEL_AGP_H +#define _INTEL_AGP_H /* Intel registers */ #define INTEL_APSIZE 0xb4 @@ -244,3 +246,5 @@ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB || \ IS_SNB) + +#endif -- cgit v0.10.2 From f8f235e5bbf4e61f3e0886a44afb1dc4cfe8f337 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Fri, 27 Aug 2010 11:08:57 +0800 Subject: agp/intel: Fix cache control for Sandybridge Sandybridge GTT has new cache control bits in PTE, which controls graphics page cache in LLC or LLC/MLC, so we need to extend the mask function to respect the new bits. And set cache control to always LLC only by default on Gen6. Signed-off-by: Zhenyu Wang Cc: stable@kernel.org Signed-off-by: Chris Wilson diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 710af89..74461d1 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -12,6 +12,7 @@ #include #include "agp.h" #include "intel-agp.h" +#include #include "intel-gtt.c" diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 7f35854..64b1055 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -49,6 +49,26 @@ static struct gatt_mask intel_i810_masks[] = .type = INTEL_AGP_CACHED_MEMORY} }; +#define INTEL_AGP_UNCACHED_MEMORY 0 +#define INTEL_AGP_CACHED_MEMORY_LLC 1 +#define INTEL_AGP_CACHED_MEMORY_LLC_GFDT 2 +#define INTEL_AGP_CACHED_MEMORY_LLC_MLC 3 +#define INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT 4 + +static struct gatt_mask intel_gen6_masks[] = +{ + {.mask = I810_PTE_VALID | GEN6_PTE_UNCACHED, + .type = INTEL_AGP_UNCACHED_MEMORY }, + {.mask = I810_PTE_VALID | GEN6_PTE_LLC, + .type = INTEL_AGP_CACHED_MEMORY_LLC }, + {.mask = I810_PTE_VALID | GEN6_PTE_LLC | GEN6_PTE_GFDT, + .type = INTEL_AGP_CACHED_MEMORY_LLC_GFDT }, + {.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC, + .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC }, + {.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC | GEN6_PTE_GFDT, + .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT }, +}; + static struct _intel_private { struct pci_dev *pcidev; /* device one */ u8 __iomem *registers; @@ -178,13 +198,6 @@ static void intel_agp_insert_sg_entries(struct agp_memory *mem, off_t pg_start, int mask_type) { int i, j; - u32 cache_bits = 0; - - if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) - { - cache_bits = GEN6_PTE_LLC_MLC; - } for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { writel(agp_bridge->driver->mask_memory(agp_bridge, @@ -317,6 +330,23 @@ static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge, return 0; } +static int intel_gen6_type_to_mask_type(struct agp_bridge_data *bridge, + int type) +{ + unsigned int type_mask = type & ~AGP_USER_CACHED_MEMORY_GFDT; + unsigned int gfdt = type & AGP_USER_CACHED_MEMORY_GFDT; + + if (type_mask == AGP_USER_UNCACHED_MEMORY) + return INTEL_AGP_UNCACHED_MEMORY; + else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) + return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT : + INTEL_AGP_CACHED_MEMORY_LLC_MLC; + else /* set 'normal'/'cached' to LLC by default */ + return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_GFDT : + INTEL_AGP_CACHED_MEMORY_LLC; +} + + static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, int type) { @@ -1163,7 +1193,7 @@ static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start, mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); - if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY && + if (!IS_SNB && mask_type != 0 && mask_type != AGP_PHYS_MEMORY && mask_type != INTEL_AGP_CACHED_MEMORY) goto out_err; @@ -1563,7 +1593,7 @@ static const struct agp_bridge_driver intel_gen6_driver = { .fetch_size = intel_i9xx_fetch_size, .cleanup = intel_i915_cleanup, .mask_memory = intel_gen6_mask_memory, - .masks = intel_i810_masks, + .masks = intel_gen6_masks, .agp_enable = intel_i810_agp_enable, .cache_flush = global_cache_flush, .create_gatt_table = intel_i965_create_gatt_table, @@ -1576,7 +1606,7 @@ static const struct agp_bridge_driver intel_gen6_driver = { .agp_alloc_pages = agp_generic_alloc_pages, .agp_destroy_page = agp_generic_destroy_page, .agp_destroy_pages = agp_generic_destroy_pages, - .agp_type_to_mask_type = intel_i830_type_to_mask_type, + .agp_type_to_mask_type = intel_gen6_type_to_mask_type, .chipset_flush = intel_i915_chipset_flush, #ifdef USE_PCI_DMA_API .agp_map_page = intel_agp_map_page, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 748c263..16fca1d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -34,6 +34,7 @@ #include #include #include +#include static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj); static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); diff --git a/include/linux/intel-gtt.h b/include/linux/intel-gtt.h new file mode 100644 index 0000000..1d19ab2 --- /dev/null +++ b/include/linux/intel-gtt.h @@ -0,0 +1,20 @@ +/* + * Common Intel AGPGART and GTT definitions. + */ +#ifndef _INTEL_GTT_H +#define _INTEL_GTT_H + +#include + +/* This is for Intel only GTT controls. + * + * Sandybridge: AGP_USER_CACHED_MEMORY default to LLC only + */ + +#define AGP_USER_CACHED_MEMORY_LLC_MLC (AGP_USER_TYPES + 2) +#define AGP_USER_UNCACHED_MEMORY (AGP_USER_TYPES + 4) + +/* flag for GFDT type */ +#define AGP_USER_CACHED_MEMORY_GFDT (1 << 3) + +#endif -- cgit v0.10.2 From a69ffdbfcba8eabf2ca9d384b578e6f28b339c61 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Mon, 30 Aug 2010 16:12:42 +0800 Subject: drm/i915: Enable MI_FLUSH on Sandybridge MI_FLUSH is being deprecated, but still available on Sandybridge. Make sure it's enabled as userspace still uses MI_FLUSH. Signed-off-by: Zhenyu Wang Cc: stable@kernel.org Signed-off-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 67e3ec1..d094e91 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -319,6 +319,7 @@ #define MI_MODE 0x0209c # define VS_TIMER_DISPATCH (1 << 6) +# define MI_FLUSH_ENABLE (1 << 11) #define SCPD0 0x0209c /* 915+ only */ #define IER 0x020a0 diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 51e9c9e7..cb3508f 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -220,9 +220,13 @@ static int init_render_ring(struct drm_device *dev, { drm_i915_private_t *dev_priv = dev->dev_private; int ret = init_ring_common(dev, ring); + int mode; + if (IS_I9XX(dev) && !IS_GEN3(dev)) { - I915_WRITE(MI_MODE, - (VS_TIMER_DISPATCH) << 16 | VS_TIMER_DISPATCH); + mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH; + if (IS_GEN6(dev)) + mode |= MI_FLUSH_ENABLE << 16 | MI_FLUSH_ENABLE; + I915_WRITE(MI_MODE, mode); } return ret; } -- cgit v0.10.2 From 8554048070906579ec9fa19ac381deddd2d7b155 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Tue, 7 Sep 2010 13:45:32 +0800 Subject: intel_agp,i915: Add more sandybridge graphics device ids New pci ids for GT2 and GT2+ on desktop and mobile sandybridge, and graphics device ids for server sandybridge. Also rename original ids string to reflect GT1 version. Signed-off-by: Zhenyu Wang Cc: stable@kernel.org Signed-off-by: Chris Wilson diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 74461d1..eab58db 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -816,11 +816,19 @@ static const struct intel_driver_description { "HD Graphics", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, "HD Graphics", NULL, &intel_i965_driver }, - { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG, "Sandybridge", NULL, &intel_gen6_driver }, - { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG, "Sandybridge", NULL, &intel_gen6_driver }, - { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_D0_IG, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG, + "Sandybridge", NULL, &intel_gen6_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG, + "Sandybridge", NULL, &intel_gen6_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG, + "Sandybridge", NULL, &intel_gen6_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG, + "Sandybridge", NULL, &intel_gen6_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG, "Sandybridge", NULL, &intel_gen6_driver }, { 0, 0, NULL, NULL, NULL } }; @@ -1045,6 +1053,7 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB), ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB), + ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB), { } }; diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index 78124a8..ee189c7 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h @@ -202,11 +202,16 @@ #define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062 #define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG 0x0102 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG 0x0106 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_D0_IG 0x0126 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100 /* Desktop */ +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG 0x0102 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG 0x0112 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG 0x0122 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104 /* Mobile */ +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG 0x0106 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG 0x0116 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG 0x0126 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB 0x0108 /* Server */ +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG 0x010A /* cover 915 and 945 variants */ #define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \ @@ -233,7 +238,8 @@ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB) #define IS_SNB (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB) #define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_EAGLELAKE_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \ diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 64b1055..75e0a34 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -618,8 +618,7 @@ static void intel_i830_init_gtt_entries(void) gtt_entries = 0; break; } - } else if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) { + } else if (IS_SNB) { /* * SandyBridge has new memory control reg at 0x50.w */ @@ -1389,6 +1388,7 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size) break; case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB: case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB: + case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB: *gtt_offset = MB(2); pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 5363985..216deb5 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -175,8 +175,12 @@ static const struct pci_device_id pciidlist[] = { /* aka */ INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info), INTEL_VGA_DEVICE(0x0046, &intel_ironlake_m_info), INTEL_VGA_DEVICE(0x0102, &intel_sandybridge_d_info), + INTEL_VGA_DEVICE(0x0112, &intel_sandybridge_d_info), + INTEL_VGA_DEVICE(0x0122, &intel_sandybridge_d_info), INTEL_VGA_DEVICE(0x0106, &intel_sandybridge_m_info), + INTEL_VGA_DEVICE(0x0116, &intel_sandybridge_m_info), INTEL_VGA_DEVICE(0x0126, &intel_sandybridge_m_info), + INTEL_VGA_DEVICE(0x010A, &intel_sandybridge_d_info), {0, 0, 0} }; -- cgit v0.10.2 From 7a2e8a8faab76386d8eaae9ded739ee5615be174 Mon Sep 17 00:00:00 2001 From: Valerie Aurora Date: Thu, 26 Aug 2010 11:07:22 -0700 Subject: VFS: Sanity check mount flags passed to change_mnt_propagation() Sanity check the flags passed to change_mnt_propagation(). Exactly one flag should be set. Return EINVAL otherwise. Userspace can pass in arbitrary combinations of MS_* flags to mount(). do_change_type() is called if any of MS_SHARED, MS_PRIVATE, MS_SLAVE, or MS_UNBINDABLE is set. do_change_type() clears MS_REC and then calls change_mnt_propagation() with the rest of the user-supplied flags. change_mnt_propagation() clearly assumes only one flag is set but do_change_type() does not check that this is true. For example, mount() with flags MS_SHARED | MS_RDONLY does not actually make the mount shared or read-only but does clear MNT_UNBINDABLE. Signed-off-by: Valerie Aurora Signed-off-by: Linus Torvalds diff --git a/fs/namespace.c b/fs/namespace.c index de402eb..a72eaab 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1484,13 +1484,30 @@ out_unlock: } /* + * Sanity check the flags to change_mnt_propagation. + */ + +static int flags_to_propagation_type(int flags) +{ + int type = flags & ~MS_REC; + + /* Fail if any non-propagation flags are set */ + if (type & ~(MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) + return 0; + /* Only one propagation flag should be set */ + if (!is_power_of_2(type)) + return 0; + return type; +} + +/* * recursively change the type of the mountpoint. */ static int do_change_type(struct path *path, int flag) { struct vfsmount *m, *mnt = path->mnt; int recurse = flag & MS_REC; - int type = flag & ~MS_REC; + int type; int err = 0; if (!capable(CAP_SYS_ADMIN)) @@ -1499,6 +1516,10 @@ static int do_change_type(struct path *path, int flag) if (path->dentry != path->mnt->mnt_root) return -EINVAL; + type = flags_to_propagation_type(flag); + if (!type) + return -EINVAL; + down_write(&namespace_sem); if (type == MS_SHARED) { err = invent_group_ids(mnt, recurse); -- cgit v0.10.2 From 3ab61eb9fd751336d1b3ad50ec7704bd3b62213f Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 31 Aug 2010 16:52:11 +0100 Subject: h8300: IRQ flags should be stored in an unsigned long Fix h8300's asm/atomic.h to store the IRQ flags in an unsigned long to deal with warnings of the following type: arch/h8300/include/asm/atomic.h: In function 'atomic_add_return': arch/h8300/include/asm/atomic.h:22: warning: comparison of distinct pointer types lacks a cast arch/h8300/include/asm/atomic.h:24: warning: comparison of distinct pointer types lacks a cast Signed-off-by: David Howells Signed-off-by: Linus Torvalds diff --git a/arch/h8300/include/asm/atomic.h b/arch/h8300/include/asm/atomic.h index e936804..984221a 100644 --- a/arch/h8300/include/asm/atomic.h +++ b/arch/h8300/include/asm/atomic.h @@ -18,7 +18,8 @@ static __inline__ int atomic_add_return(int i, atomic_t *v) { - int ret,flags; + unsigned long flags; + int ret; local_irq_save(flags); ret = v->counter += i; local_irq_restore(flags); @@ -30,7 +31,8 @@ static __inline__ int atomic_add_return(int i, atomic_t *v) static __inline__ int atomic_sub_return(int i, atomic_t *v) { - int ret,flags; + unsigned long flags; + int ret; local_irq_save(flags); ret = v->counter -= i; local_irq_restore(flags); @@ -42,7 +44,8 @@ static __inline__ int atomic_sub_return(int i, atomic_t *v) static __inline__ int atomic_inc_return(atomic_t *v) { - int ret,flags; + unsigned long flags; + int ret; local_irq_save(flags); v->counter++; ret = v->counter; @@ -64,7 +67,8 @@ static __inline__ int atomic_inc_return(atomic_t *v) static __inline__ int atomic_dec_return(atomic_t *v) { - int ret,flags; + unsigned long flags; + int ret; local_irq_save(flags); --v->counter; ret = v->counter; @@ -76,7 +80,8 @@ static __inline__ int atomic_dec_return(atomic_t *v) static __inline__ int atomic_dec_and_test(atomic_t *v) { - int ret,flags; + unsigned long flags; + int ret; local_irq_save(flags); --v->counter; ret = v->counter; -- cgit v0.10.2 From b857189d94e0d8a05943349618c4f84dbc57144c Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 31 Aug 2010 16:52:16 +0100 Subject: h8300: Fix die() Fix h8300's die() to take care of a number of problems: CC arch/h8300/kernel/traps.o In file included from arch/h8300/include/asm/bitops.h:10, from include/linux/bitops.h:22, from include/linux/kernel.h:17, from include/linux/sched.h:54, from arch/h8300/kernel/traps.c:18: arch/h8300/include/asm/system.h:136: warning: 'struct pt_regs' declared inside parameter list arch/h8300/include/asm/system.h:136: warning: its scope is only this definition or declaration, which is probably not what you want arch/h8300/kernel/traps.c:100: error: conflicting types for 'die' arch/h8300/include/asm/system.h:136: error: previous declaration of 'die' was here make[2]: *** [arch/h8300/kernel/traps.o] Error 1 Signed-off-by: David Howells Signed-off-by: Linus Torvalds diff --git a/arch/h8300/include/asm/system.h b/arch/h8300/include/asm/system.h index d98d976..16bf156 100644 --- a/arch/h8300/include/asm/system.h +++ b/arch/h8300/include/asm/system.h @@ -3,6 +3,8 @@ #include +struct pt_regs; + /* * switch_to(n) should switch tasks to task ptr, first checking that * ptr isn't the current task, in which case it does nothing. This @@ -155,6 +157,6 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz #define arch_align_stack(x) (x) -void die(char *str, struct pt_regs *fp, unsigned long err); +extern void die(const char *str, struct pt_regs *fp, unsigned long err); #endif /* _H8300_SYSTEM_H */ diff --git a/arch/h8300/kernel/traps.c b/arch/h8300/kernel/traps.c index 3c0b66b..dfa05bd 100644 --- a/arch/h8300/kernel/traps.c +++ b/arch/h8300/kernel/traps.c @@ -96,7 +96,7 @@ static void dump(struct pt_regs *fp) printk("\n\n"); } -void die(char *str, struct pt_regs *fp, unsigned long err) +void die(const char *str, struct pt_regs *fp, unsigned long err) { static int diecount; -- cgit v0.10.2 From 1e72910e248fb94839cd63c0c62107b1f15716f9 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 31 Aug 2010 16:52:21 +0100 Subject: h8300: Fix missing consts in kernel_execve() Fix missing consts in h8300's kernel_execve(): arch/h8300/kernel/sys_h8300.c: In function 'kernel_execve': arch/h8300/kernel/sys_h8300.c:59: warning: initialization from incompatible pointer type arch/h8300/kernel/sys_h8300.c:60: warning: initialization from incompatible pointer type Signed-off-by: David Howells Signed-off-by: Linus Torvalds diff --git a/arch/h8300/kernel/sys_h8300.c b/arch/h8300/kernel/sys_h8300.c index dc1ac02..aaf5e5a 100644 --- a/arch/h8300/kernel/sys_h8300.c +++ b/arch/h8300/kernel/sys_h8300.c @@ -56,8 +56,8 @@ int kernel_execve(const char *filename, const char *const envp[]) { register long res __asm__("er0"); - register char *const *_c __asm__("er3") = envp; - register char *const *_b __asm__("er2") = argv; + register const char *const *_c __asm__("er3") = envp; + register const char *const *_b __asm__("er2") = argv; register const char * _a __asm__("er1") = filename; __asm__ __volatile__ ("mov.l %1,er0\n\t" "trapa #0\n\t" -- cgit v0.10.2 From e6ba59bcae6968ee18ef5a237a8020a0ea331ae1 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Fri, 3 Sep 2010 11:15:19 +1000 Subject: m68knommu: fix missing linker segments Recent changes to linker segments that hold per-cpu data broke linking for m68knommu targets: LD vmlinux /usr/local/bin/m68k-uclinux-ld.real: error: no memory region specified for loadable section `.data..shared_aligned' Add missing segments into the m68knommu linker script. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S index a91b271..ef33213 100644 --- a/arch/m68knommu/kernel/vmlinux.lds.S +++ b/arch/m68knommu/kernel/vmlinux.lds.S @@ -150,6 +150,8 @@ SECTIONS { _sdata = . ; DATA_DATA CACHELINE_ALIGNED_DATA(32) + PAGE_ALIGNED_DATA(PAGE_SIZE) + *(.data..shared_aligned) INIT_TASK_DATA(THREAD_SIZE) _edata = . ; } > DATA -- cgit v0.10.2