Annotation of /trunk/kernel-magellan/patches-3.9/0108-3.9.9-all-fixes.patch
Parent Directory | Revision Log
Revision 2234 -
(hide annotations)
(download)
Thu Jul 11 17:29:27 2013 UTC (11 years, 2 months ago) by niro
File size: 35022 byte(s)
Thu Jul 11 17:29:27 2013 UTC (11 years, 2 months ago) by niro
File size: 35022 byte(s)
-linux-3.9.9
1 | niro | 2234 | diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h |
2 | index e1489c5..738fcba 100644 | ||
3 | --- a/arch/arm/include/asm/cacheflush.h | ||
4 | +++ b/arch/arm/include/asm/cacheflush.h | ||
5 | @@ -320,9 +320,7 @@ static inline void flush_anon_page(struct vm_area_struct *vma, | ||
6 | } | ||
7 | |||
8 | #define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE | ||
9 | -static inline void flush_kernel_dcache_page(struct page *page) | ||
10 | -{ | ||
11 | -} | ||
12 | +extern void flush_kernel_dcache_page(struct page *); | ||
13 | |||
14 | #define flush_dcache_mmap_lock(mapping) \ | ||
15 | spin_lock_irq(&(mapping)->tree_lock) | ||
16 | diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c | ||
17 | index 1c8f7f5..b5ae9fd 100644 | ||
18 | --- a/arch/arm/mm/flush.c | ||
19 | +++ b/arch/arm/mm/flush.c | ||
20 | @@ -298,6 +298,39 @@ void flush_dcache_page(struct page *page) | ||
21 | EXPORT_SYMBOL(flush_dcache_page); | ||
22 | |||
23 | /* | ||
24 | + * Ensure cache coherency for the kernel mapping of this page. We can | ||
25 | + * assume that the page is pinned via kmap. | ||
26 | + * | ||
27 | + * If the page only exists in the page cache and there are no user | ||
28 | + * space mappings, this is a no-op since the page was already marked | ||
29 | + * dirty at creation. Otherwise, we need to flush the dirty kernel | ||
30 | + * cache lines directly. | ||
31 | + */ | ||
32 | +void flush_kernel_dcache_page(struct page *page) | ||
33 | +{ | ||
34 | + if (cache_is_vivt() || cache_is_vipt_aliasing()) { | ||
35 | + struct address_space *mapping; | ||
36 | + | ||
37 | + mapping = page_mapping(page); | ||
38 | + | ||
39 | + if (!mapping || mapping_mapped(mapping)) { | ||
40 | + void *addr; | ||
41 | + | ||
42 | + addr = page_address(page); | ||
43 | + /* | ||
44 | + * kmap_atomic() doesn't set the page virtual | ||
45 | + * address for highmem pages, and | ||
46 | + * kunmap_atomic() takes care of cache | ||
47 | + * flushing already. | ||
48 | + */ | ||
49 | + if (!IS_ENABLED(CONFIG_HIGHMEM) || addr) | ||
50 | + __cpuc_flush_dcache_area(addr, PAGE_SIZE); | ||
51 | + } | ||
52 | + } | ||
53 | +} | ||
54 | +EXPORT_SYMBOL(flush_kernel_dcache_page); | ||
55 | + | ||
56 | +/* | ||
57 | * Flush an anonymous page so that users of get_user_pages() | ||
58 | * can safely access the data. The expected sequence is: | ||
59 | * | ||
60 | diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c | ||
61 | index d51225f..eb5293a 100644 | ||
62 | --- a/arch/arm/mm/nommu.c | ||
63 | +++ b/arch/arm/mm/nommu.c | ||
64 | @@ -57,6 +57,12 @@ void flush_dcache_page(struct page *page) | ||
65 | } | ||
66 | EXPORT_SYMBOL(flush_dcache_page); | ||
67 | |||
68 | +void flush_kernel_dcache_page(struct page *page) | ||
69 | +{ | ||
70 | + __cpuc_flush_dcache_area(page_address(page), PAGE_SIZE); | ||
71 | +} | ||
72 | +EXPORT_SYMBOL(flush_kernel_dcache_page); | ||
73 | + | ||
74 | void copy_to_user_page(struct vm_area_struct *vma, struct page *page, | ||
75 | unsigned long uaddr, void *dst, const void *src, | ||
76 | unsigned long len) | ||
77 | diff --git a/arch/powerpc/platforms/pseries/eeh_pe.c b/arch/powerpc/platforms/pseries/eeh_pe.c | ||
78 | index fe43d1a..9d4a9e8 100644 | ||
79 | --- a/arch/powerpc/platforms/pseries/eeh_pe.c | ||
80 | +++ b/arch/powerpc/platforms/pseries/eeh_pe.c | ||
81 | @@ -639,7 +639,8 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe) | ||
82 | |||
83 | if (pe->type & EEH_PE_PHB) { | ||
84 | bus = pe->phb->bus; | ||
85 | - } else if (pe->type & EEH_PE_BUS) { | ||
86 | + } else if (pe->type & EEH_PE_BUS || | ||
87 | + pe->type & EEH_PE_DEVICE) { | ||
88 | edev = list_first_entry(&pe->edevs, struct eeh_dev, list); | ||
89 | pdev = eeh_dev_to_pci_dev(edev); | ||
90 | if (pdev) | ||
91 | diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c | ||
92 | index d8a6a38..feb719d 100644 | ||
93 | --- a/arch/s390/kernel/ipl.c | ||
94 | +++ b/arch/s390/kernel/ipl.c | ||
95 | @@ -754,9 +754,9 @@ static struct bin_attribute sys_reipl_fcp_scp_data_attr = { | ||
96 | .write = reipl_fcp_scpdata_write, | ||
97 | }; | ||
98 | |||
99 | -DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%016llx\n", | ||
100 | +DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%llx\n", | ||
101 | reipl_block_fcp->ipl_info.fcp.wwpn); | ||
102 | -DEFINE_IPL_ATTR_RW(reipl_fcp, lun, "0x%016llx\n", "%016llx\n", | ||
103 | +DEFINE_IPL_ATTR_RW(reipl_fcp, lun, "0x%016llx\n", "%llx\n", | ||
104 | reipl_block_fcp->ipl_info.fcp.lun); | ||
105 | DEFINE_IPL_ATTR_RW(reipl_fcp, bootprog, "%lld\n", "%lld\n", | ||
106 | reipl_block_fcp->ipl_info.fcp.bootprog); | ||
107 | @@ -1323,9 +1323,9 @@ static struct shutdown_action __refdata reipl_action = { | ||
108 | |||
109 | /* FCP dump device attributes */ | ||
110 | |||
111 | -DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%016llx\n", | ||
112 | +DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%llx\n", | ||
113 | dump_block_fcp->ipl_info.fcp.wwpn); | ||
114 | -DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%016llx\n", | ||
115 | +DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%llx\n", | ||
116 | dump_block_fcp->ipl_info.fcp.lun); | ||
117 | DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n", | ||
118 | dump_block_fcp->ipl_info.fcp.bootprog); | ||
119 | diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c | ||
120 | index 1630f43..1d95be9 100644 | ||
121 | --- a/arch/s390/kernel/irq.c | ||
122 | +++ b/arch/s390/kernel/irq.c | ||
123 | @@ -313,3 +313,69 @@ void measurement_alert_subclass_unregister(void) | ||
124 | spin_unlock(&ma_subclass_lock); | ||
125 | } | ||
126 | EXPORT_SYMBOL(measurement_alert_subclass_unregister); | ||
127 | + | ||
128 | +#ifdef CONFIG_SMP | ||
129 | +void synchronize_irq(unsigned int irq) | ||
130 | +{ | ||
131 | + /* | ||
132 | + * Not needed, the handler is protected by a lock and IRQs that occur | ||
133 | + * after the handler is deleted are just NOPs. | ||
134 | + */ | ||
135 | +} | ||
136 | +EXPORT_SYMBOL_GPL(synchronize_irq); | ||
137 | +#endif | ||
138 | + | ||
139 | +#ifndef CONFIG_PCI | ||
140 | + | ||
141 | +/* Only PCI devices have dynamically-defined IRQ handlers */ | ||
142 | + | ||
143 | +int request_irq(unsigned int irq, irq_handler_t handler, | ||
144 | + unsigned long irqflags, const char *devname, void *dev_id) | ||
145 | +{ | ||
146 | + return -EINVAL; | ||
147 | +} | ||
148 | +EXPORT_SYMBOL_GPL(request_irq); | ||
149 | + | ||
150 | +void free_irq(unsigned int irq, void *dev_id) | ||
151 | +{ | ||
152 | + WARN_ON(1); | ||
153 | +} | ||
154 | +EXPORT_SYMBOL_GPL(free_irq); | ||
155 | + | ||
156 | +void enable_irq(unsigned int irq) | ||
157 | +{ | ||
158 | + WARN_ON(1); | ||
159 | +} | ||
160 | +EXPORT_SYMBOL_GPL(enable_irq); | ||
161 | + | ||
162 | +void disable_irq(unsigned int irq) | ||
163 | +{ | ||
164 | + WARN_ON(1); | ||
165 | +} | ||
166 | +EXPORT_SYMBOL_GPL(disable_irq); | ||
167 | + | ||
168 | +#endif /* !CONFIG_PCI */ | ||
169 | + | ||
170 | +void disable_irq_nosync(unsigned int irq) | ||
171 | +{ | ||
172 | + disable_irq(irq); | ||
173 | +} | ||
174 | +EXPORT_SYMBOL_GPL(disable_irq_nosync); | ||
175 | + | ||
176 | +unsigned long probe_irq_on(void) | ||
177 | +{ | ||
178 | + return 0; | ||
179 | +} | ||
180 | +EXPORT_SYMBOL_GPL(probe_irq_on); | ||
181 | + | ||
182 | +int probe_irq_off(unsigned long val) | ||
183 | +{ | ||
184 | + return 0; | ||
185 | +} | ||
186 | +EXPORT_SYMBOL_GPL(probe_irq_off); | ||
187 | + | ||
188 | +unsigned int probe_irq_mask(unsigned long val) | ||
189 | +{ | ||
190 | + return val; | ||
191 | +} | ||
192 | +EXPORT_SYMBOL_GPL(probe_irq_mask); | ||
193 | diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c | ||
194 | index 27b4c17..4fd5b5a 100644 | ||
195 | --- a/arch/s390/pci/pci.c | ||
196 | +++ b/arch/s390/pci/pci.c | ||
197 | @@ -306,15 +306,6 @@ static int zpci_cfg_store(struct zpci_dev *zdev, int offset, u32 val, u8 len) | ||
198 | return rc; | ||
199 | } | ||
200 | |||
201 | -void synchronize_irq(unsigned int irq) | ||
202 | -{ | ||
203 | - /* | ||
204 | - * Not needed, the handler is protected by a lock and IRQs that occur | ||
205 | - * after the handler is deleted are just NOPs. | ||
206 | - */ | ||
207 | -} | ||
208 | -EXPORT_SYMBOL_GPL(synchronize_irq); | ||
209 | - | ||
210 | void enable_irq(unsigned int irq) | ||
211 | { | ||
212 | struct msi_desc *msi = irq_get_msi_desc(irq); | ||
213 | @@ -331,30 +322,6 @@ void disable_irq(unsigned int irq) | ||
214 | } | ||
215 | EXPORT_SYMBOL_GPL(disable_irq); | ||
216 | |||
217 | -void disable_irq_nosync(unsigned int irq) | ||
218 | -{ | ||
219 | - disable_irq(irq); | ||
220 | -} | ||
221 | -EXPORT_SYMBOL_GPL(disable_irq_nosync); | ||
222 | - | ||
223 | -unsigned long probe_irq_on(void) | ||
224 | -{ | ||
225 | - return 0; | ||
226 | -} | ||
227 | -EXPORT_SYMBOL_GPL(probe_irq_on); | ||
228 | - | ||
229 | -int probe_irq_off(unsigned long val) | ||
230 | -{ | ||
231 | - return 0; | ||
232 | -} | ||
233 | -EXPORT_SYMBOL_GPL(probe_irq_off); | ||
234 | - | ||
235 | -unsigned int probe_irq_mask(unsigned long val) | ||
236 | -{ | ||
237 | - return val; | ||
238 | -} | ||
239 | -EXPORT_SYMBOL_GPL(probe_irq_mask); | ||
240 | - | ||
241 | void pcibios_fixup_bus(struct pci_bus *bus) | ||
242 | { | ||
243 | } | ||
244 | diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h | ||
245 | index 95fd352..b00bf09 100644 | ||
246 | --- a/arch/x86/include/asm/irq_remapping.h | ||
247 | +++ b/arch/x86/include/asm/irq_remapping.h | ||
248 | @@ -23,11 +23,13 @@ | ||
249 | #define __X86_IRQ_REMAPPING_H | ||
250 | |||
251 | #include <asm/io_apic.h> | ||
252 | +#include <linux/irq.h> | ||
253 | |||
254 | #ifdef CONFIG_IRQ_REMAP | ||
255 | |||
256 | extern void setup_irq_remapping_ops(void); | ||
257 | extern int irq_remapping_supported(void); | ||
258 | +extern void set_irq_remapping_broken(void); | ||
259 | extern int irq_remapping_prepare(void); | ||
260 | extern int irq_remapping_enable(void); | ||
261 | extern void irq_remapping_disable(void); | ||
262 | @@ -54,6 +56,7 @@ void irq_remap_modify_chip_defaults(struct irq_chip *chip); | ||
263 | |||
264 | static inline void setup_irq_remapping_ops(void) { } | ||
265 | static inline int irq_remapping_supported(void) { return 0; } | ||
266 | +static inline void set_irq_remapping_broken(void) { } | ||
267 | static inline int irq_remapping_prepare(void) { return -ENODEV; } | ||
268 | static inline int irq_remapping_enable(void) { return -ENODEV; } | ||
269 | static inline void irq_remapping_disable(void) { } | ||
270 | diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c | ||
271 | index 3755ef4..94ab6b9 100644 | ||
272 | --- a/arch/x86/kernel/early-quirks.c | ||
273 | +++ b/arch/x86/kernel/early-quirks.c | ||
274 | @@ -18,6 +18,7 @@ | ||
275 | #include <asm/apic.h> | ||
276 | #include <asm/iommu.h> | ||
277 | #include <asm/gart.h> | ||
278 | +#include <asm/irq_remapping.h> | ||
279 | |||
280 | static void __init fix_hypertransport_config(int num, int slot, int func) | ||
281 | { | ||
282 | @@ -192,6 +193,21 @@ static void __init ati_bugs_contd(int num, int slot, int func) | ||
283 | } | ||
284 | #endif | ||
285 | |||
286 | +static void __init intel_remapping_check(int num, int slot, int func) | ||
287 | +{ | ||
288 | + u8 revision; | ||
289 | + | ||
290 | + revision = read_pci_config_byte(num, slot, func, PCI_REVISION_ID); | ||
291 | + | ||
292 | + /* | ||
293 | + * Revision 0x13 of this chipset supports irq remapping | ||
294 | + * but has an erratum that breaks its behavior, flag it as such | ||
295 | + */ | ||
296 | + if (revision == 0x13) | ||
297 | + set_irq_remapping_broken(); | ||
298 | + | ||
299 | +} | ||
300 | + | ||
301 | #define QFLAG_APPLY_ONCE 0x1 | ||
302 | #define QFLAG_APPLIED 0x2 | ||
303 | #define QFLAG_DONE (QFLAG_APPLY_ONCE|QFLAG_APPLIED) | ||
304 | @@ -221,6 +237,10 @@ static struct chipset early_qrk[] __initdata = { | ||
305 | PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs }, | ||
306 | { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, | ||
307 | PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs_contd }, | ||
308 | + { PCI_VENDOR_ID_INTEL, 0x3403, PCI_CLASS_BRIDGE_HOST, | ||
309 | + PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check }, | ||
310 | + { PCI_VENDOR_ID_INTEL, 0x3406, PCI_CLASS_BRIDGE_HOST, | ||
311 | + PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check }, | ||
312 | {} | ||
313 | }; | ||
314 | |||
315 | diff --git a/crypto/algboss.c b/crypto/algboss.c | ||
316 | index 769219b..76fc0b2 100644 | ||
317 | --- a/crypto/algboss.c | ||
318 | +++ b/crypto/algboss.c | ||
319 | @@ -45,10 +45,9 @@ struct cryptomgr_param { | ||
320 | } nu32; | ||
321 | } attrs[CRYPTO_MAX_ATTRS]; | ||
322 | |||
323 | - char larval[CRYPTO_MAX_ALG_NAME]; | ||
324 | char template[CRYPTO_MAX_ALG_NAME]; | ||
325 | |||
326 | - struct completion *completion; | ||
327 | + struct crypto_larval *larval; | ||
328 | |||
329 | u32 otype; | ||
330 | u32 omask; | ||
331 | @@ -87,7 +86,8 @@ static int cryptomgr_probe(void *data) | ||
332 | crypto_tmpl_put(tmpl); | ||
333 | |||
334 | out: | ||
335 | - complete_all(param->completion); | ||
336 | + complete_all(¶m->larval->completion); | ||
337 | + crypto_alg_put(¶m->larval->alg); | ||
338 | kfree(param); | ||
339 | module_put_and_exit(0); | ||
340 | } | ||
341 | @@ -187,18 +187,19 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval) | ||
342 | param->otype = larval->alg.cra_flags; | ||
343 | param->omask = larval->mask; | ||
344 | |||
345 | - memcpy(param->larval, larval->alg.cra_name, CRYPTO_MAX_ALG_NAME); | ||
346 | - | ||
347 | - param->completion = &larval->completion; | ||
348 | + crypto_alg_get(&larval->alg); | ||
349 | + param->larval = larval; | ||
350 | |||
351 | thread = kthread_run(cryptomgr_probe, param, "cryptomgr_probe"); | ||
352 | if (IS_ERR(thread)) | ||
353 | - goto err_free_param; | ||
354 | + goto err_put_larval; | ||
355 | |||
356 | wait_for_completion_interruptible(&larval->completion); | ||
357 | |||
358 | return NOTIFY_STOP; | ||
359 | |||
360 | +err_put_larval: | ||
361 | + crypto_alg_put(&larval->alg); | ||
362 | err_free_param: | ||
363 | kfree(param); | ||
364 | err_put_module: | ||
365 | diff --git a/crypto/api.c b/crypto/api.c | ||
366 | index 033a714..3b61803 100644 | ||
367 | --- a/crypto/api.c | ||
368 | +++ b/crypto/api.c | ||
369 | @@ -34,12 +34,6 @@ EXPORT_SYMBOL_GPL(crypto_alg_sem); | ||
370 | BLOCKING_NOTIFIER_HEAD(crypto_chain); | ||
371 | EXPORT_SYMBOL_GPL(crypto_chain); | ||
372 | |||
373 | -static inline struct crypto_alg *crypto_alg_get(struct crypto_alg *alg) | ||
374 | -{ | ||
375 | - atomic_inc(&alg->cra_refcnt); | ||
376 | - return alg; | ||
377 | -} | ||
378 | - | ||
379 | struct crypto_alg *crypto_mod_get(struct crypto_alg *alg) | ||
380 | { | ||
381 | return try_module_get(alg->cra_module) ? crypto_alg_get(alg) : NULL; | ||
382 | diff --git a/crypto/internal.h b/crypto/internal.h | ||
383 | index 9ebedae..bd39bfc 100644 | ||
384 | --- a/crypto/internal.h | ||
385 | +++ b/crypto/internal.h | ||
386 | @@ -103,6 +103,12 @@ int crypto_register_notifier(struct notifier_block *nb); | ||
387 | int crypto_unregister_notifier(struct notifier_block *nb); | ||
388 | int crypto_probing_notify(unsigned long val, void *v); | ||
389 | |||
390 | +static inline struct crypto_alg *crypto_alg_get(struct crypto_alg *alg) | ||
391 | +{ | ||
392 | + atomic_inc(&alg->cra_refcnt); | ||
393 | + return alg; | ||
394 | +} | ||
395 | + | ||
396 | static inline void crypto_alg_put(struct crypto_alg *alg) | ||
397 | { | ||
398 | if (atomic_dec_and_test(&alg->cra_refcnt) && alg->cra_destroy) | ||
399 | diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c | ||
400 | index 3badf18..3ce078c 100644 | ||
401 | --- a/drivers/ata/libata-acpi.c | ||
402 | +++ b/drivers/ata/libata-acpi.c | ||
403 | @@ -157,8 +157,10 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev, | ||
404 | |||
405 | spin_unlock_irqrestore(ap->lock, flags); | ||
406 | |||
407 | - if (wait) | ||
408 | + if (wait) { | ||
409 | ata_port_wait_eh(ap); | ||
410 | + flush_work(&ap->hotplug_task.work); | ||
411 | + } | ||
412 | } | ||
413 | |||
414 | static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data) | ||
415 | @@ -215,6 +217,38 @@ static const struct acpi_dock_ops ata_acpi_ap_dock_ops = { | ||
416 | .uevent = ata_acpi_ap_uevent, | ||
417 | }; | ||
418 | |||
419 | +void ata_acpi_hotplug_init(struct ata_host *host) | ||
420 | +{ | ||
421 | + int i; | ||
422 | + | ||
423 | + for (i = 0; i < host->n_ports; i++) { | ||
424 | + struct ata_port *ap = host->ports[i]; | ||
425 | + acpi_handle handle; | ||
426 | + struct ata_device *dev; | ||
427 | + | ||
428 | + if (!ap) | ||
429 | + continue; | ||
430 | + | ||
431 | + handle = ata_ap_acpi_handle(ap); | ||
432 | + if (handle) { | ||
433 | + /* we might be on a docking station */ | ||
434 | + register_hotplug_dock_device(handle, | ||
435 | + &ata_acpi_ap_dock_ops, ap); | ||
436 | + } | ||
437 | + | ||
438 | + ata_for_each_dev(dev, &ap->link, ALL) { | ||
439 | + handle = ata_dev_acpi_handle(dev); | ||
440 | + if (!handle) | ||
441 | + continue; | ||
442 | + | ||
443 | + /* we might be on a docking station */ | ||
444 | + register_hotplug_dock_device(handle, | ||
445 | + &ata_acpi_dev_dock_ops, | ||
446 | + dev); | ||
447 | + } | ||
448 | + } | ||
449 | +} | ||
450 | + | ||
451 | /** | ||
452 | * ata_acpi_dissociate - dissociate ATA host from ACPI objects | ||
453 | * @host: target ATA host | ||
454 | diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c | ||
455 | index cf15aee..8038ee3 100644 | ||
456 | --- a/drivers/ata/libata-core.c | ||
457 | +++ b/drivers/ata/libata-core.c | ||
458 | @@ -6148,6 +6148,8 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) | ||
459 | if (rc) | ||
460 | goto err_tadd; | ||
461 | |||
462 | + ata_acpi_hotplug_init(host); | ||
463 | + | ||
464 | /* set cable, sata_spd_limit and report */ | ||
465 | for (i = 0; i < host->n_ports; i++) { | ||
466 | struct ata_port *ap = host->ports[i]; | ||
467 | diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h | ||
468 | index c949dd3..577d902b 100644 | ||
469 | --- a/drivers/ata/libata.h | ||
470 | +++ b/drivers/ata/libata.h | ||
471 | @@ -122,6 +122,7 @@ extern int ata_acpi_register(void); | ||
472 | extern void ata_acpi_unregister(void); | ||
473 | extern void ata_acpi_bind(struct ata_device *dev); | ||
474 | extern void ata_acpi_unbind(struct ata_device *dev); | ||
475 | +extern void ata_acpi_hotplug_init(struct ata_host *host); | ||
476 | #else | ||
477 | static inline void ata_acpi_dissociate(struct ata_host *host) { } | ||
478 | static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; } | ||
479 | @@ -134,6 +135,7 @@ static inline int ata_acpi_register(void) { return 0; } | ||
480 | static inline void ata_acpi_unregister(void) { } | ||
481 | static inline void ata_acpi_bind(struct ata_device *dev) { } | ||
482 | static inline void ata_acpi_unbind(struct ata_device *dev) { } | ||
483 | +static inline void ata_acpi_hotplug_init(struct ata_host *host) {} | ||
484 | #endif | ||
485 | |||
486 | /* libata-scsi.c */ | ||
487 | diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c | ||
488 | index f3b8f23..5b19b2d 100644 | ||
489 | --- a/drivers/iommu/intel_irq_remapping.c | ||
490 | +++ b/drivers/iommu/intel_irq_remapping.c | ||
491 | @@ -524,6 +524,16 @@ static int __init intel_irq_remapping_supported(void) | ||
492 | |||
493 | if (disable_irq_remap) | ||
494 | return 0; | ||
495 | + if (irq_remap_broken) { | ||
496 | + WARN_TAINT(1, TAINT_FIRMWARE_WORKAROUND, | ||
497 | + "This system BIOS has enabled interrupt remapping\n" | ||
498 | + "on a chipset that contains an erratum making that\n" | ||
499 | + "feature unstable. To maintain system stability\n" | ||
500 | + "interrupt remapping is being disabled. Please\n" | ||
501 | + "contact your BIOS vendor for an update\n"); | ||
502 | + disable_irq_remap = 1; | ||
503 | + return 0; | ||
504 | + } | ||
505 | |||
506 | if (!dmar_ir_support()) | ||
507 | return 0; | ||
508 | diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c | ||
509 | index 7c11ff3..dcfea4e 100644 | ||
510 | --- a/drivers/iommu/irq_remapping.c | ||
511 | +++ b/drivers/iommu/irq_remapping.c | ||
512 | @@ -18,6 +18,7 @@ | ||
513 | int irq_remapping_enabled; | ||
514 | |||
515 | int disable_irq_remap; | ||
516 | +int irq_remap_broken; | ||
517 | int disable_sourceid_checking; | ||
518 | int no_x2apic_optout; | ||
519 | |||
520 | @@ -210,6 +211,11 @@ void __init setup_irq_remapping_ops(void) | ||
521 | #endif | ||
522 | } | ||
523 | |||
524 | +void set_irq_remapping_broken(void) | ||
525 | +{ | ||
526 | + irq_remap_broken = 1; | ||
527 | +} | ||
528 | + | ||
529 | int irq_remapping_supported(void) | ||
530 | { | ||
531 | if (disable_irq_remap) | ||
532 | diff --git a/drivers/iommu/irq_remapping.h b/drivers/iommu/irq_remapping.h | ||
533 | index ecb6376..90c4dae 100644 | ||
534 | --- a/drivers/iommu/irq_remapping.h | ||
535 | +++ b/drivers/iommu/irq_remapping.h | ||
536 | @@ -32,6 +32,7 @@ struct pci_dev; | ||
537 | struct msi_msg; | ||
538 | |||
539 | extern int disable_irq_remap; | ||
540 | +extern int irq_remap_broken; | ||
541 | extern int disable_sourceid_checking; | ||
542 | extern int no_x2apic_optout; | ||
543 | extern int irq_remapping_enabled; | ||
544 | @@ -89,6 +90,7 @@ extern struct irq_remap_ops amd_iommu_irq_ops; | ||
545 | |||
546 | #define irq_remapping_enabled 0 | ||
547 | #define disable_irq_remap 1 | ||
548 | +#define irq_remap_broken 0 | ||
549 | |||
550 | #endif /* CONFIG_IRQ_REMAP */ | ||
551 | |||
552 | diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c | ||
553 | index 6e15ef0..cbd388e 100644 | ||
554 | --- a/drivers/net/can/usb/usb_8dev.c | ||
555 | +++ b/drivers/net/can/usb/usb_8dev.c | ||
556 | @@ -977,7 +977,7 @@ static int usb_8dev_probe(struct usb_interface *intf, | ||
557 | err = usb_8dev_cmd_version(priv, &version); | ||
558 | if (err) { | ||
559 | netdev_err(netdev, "can't get firmware version\n"); | ||
560 | - goto cleanup_cmd_msg_buffer; | ||
561 | + goto cleanup_unregister_candev; | ||
562 | } else { | ||
563 | netdev_info(netdev, | ||
564 | "firmware: %d.%d, hardware: %d.%d\n", | ||
565 | @@ -989,6 +989,9 @@ static int usb_8dev_probe(struct usb_interface *intf, | ||
566 | |||
567 | return 0; | ||
568 | |||
569 | +cleanup_unregister_candev: | ||
570 | + unregister_netdev(priv->netdev); | ||
571 | + | ||
572 | cleanup_cmd_msg_buffer: | ||
573 | kfree(priv->cmd_msg_buffer); | ||
574 | |||
575 | diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c | ||
576 | index 147614e..6a8a382 100644 | ||
577 | --- a/drivers/net/wan/dlci.c | ||
578 | +++ b/drivers/net/wan/dlci.c | ||
579 | @@ -384,21 +384,37 @@ static int dlci_del(struct dlci_add *dlci) | ||
580 | struct frad_local *flp; | ||
581 | struct net_device *master, *slave; | ||
582 | int err; | ||
583 | + bool found = false; | ||
584 | + | ||
585 | + rtnl_lock(); | ||
586 | |||
587 | /* validate slave device */ | ||
588 | master = __dev_get_by_name(&init_net, dlci->devname); | ||
589 | - if (!master) | ||
590 | - return -ENODEV; | ||
591 | + if (!master) { | ||
592 | + err = -ENODEV; | ||
593 | + goto out; | ||
594 | + } | ||
595 | + | ||
596 | + list_for_each_entry(dlp, &dlci_devs, list) { | ||
597 | + if (dlp->master == master) { | ||
598 | + found = true; | ||
599 | + break; | ||
600 | + } | ||
601 | + } | ||
602 | + if (!found) { | ||
603 | + err = -ENODEV; | ||
604 | + goto out; | ||
605 | + } | ||
606 | |||
607 | if (netif_running(master)) { | ||
608 | - return -EBUSY; | ||
609 | + err = -EBUSY; | ||
610 | + goto out; | ||
611 | } | ||
612 | |||
613 | dlp = netdev_priv(master); | ||
614 | slave = dlp->slave; | ||
615 | flp = netdev_priv(slave); | ||
616 | |||
617 | - rtnl_lock(); | ||
618 | err = (*flp->deassoc)(slave, master); | ||
619 | if (!err) { | ||
620 | list_del(&dlp->list); | ||
621 | @@ -407,8 +423,8 @@ static int dlci_del(struct dlci_add *dlci) | ||
622 | |||
623 | dev_put(slave); | ||
624 | } | ||
625 | +out: | ||
626 | rtnl_unlock(); | ||
627 | - | ||
628 | return err; | ||
629 | } | ||
630 | |||
631 | diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | ||
632 | index a8016d7..305bed8 100644 | ||
633 | --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c | ||
634 | +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | ||
635 | @@ -1174,7 +1174,7 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | ||
636 | mutex_lock(&priv->htc_pm_lock); | ||
637 | |||
638 | priv->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE); | ||
639 | - if (priv->ps_idle) | ||
640 | + if (!priv->ps_idle) | ||
641 | chip_reset = true; | ||
642 | |||
643 | mutex_unlock(&priv->htc_pm_lock); | ||
644 | diff --git a/drivers/net/wireless/iwlwifi/dvm/rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c | ||
645 | index a82b6b3..5c36c21 100644 | ||
646 | --- a/drivers/net/wireless/iwlwifi/dvm/rxon.c | ||
647 | +++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c | ||
648 | @@ -1377,7 +1377,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv) | ||
649 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | ||
650 | int ret; | ||
651 | |||
652 | - if (!(priv->calib_disabled & IWL_CHAIN_NOISE_CALIB_DISABLED)) | ||
653 | + if (priv->calib_disabled & IWL_CHAIN_NOISE_CALIB_DISABLED) | ||
654 | return; | ||
655 | |||
656 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && | ||
657 | diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c | ||
658 | index 92849e5..d420c53 100644 | ||
659 | --- a/drivers/net/wireless/rt2x00/rt2800lib.c | ||
660 | +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | ||
661 | @@ -2634,19 +2634,26 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, | ||
662 | * TODO: we do not use +6 dBm option to do not increase power beyond | ||
663 | * regulatory limit, however this could be utilized for devices with | ||
664 | * CAPABILITY_POWER_LIMIT. | ||
665 | + * | ||
666 | + * TODO: add different temperature compensation code for RT3290 & RT5390 | ||
667 | + * to allow to use BBP_R1 for those chips. | ||
668 | */ | ||
669 | - rt2800_bbp_read(rt2x00dev, 1, &r1); | ||
670 | - if (delta <= -12) { | ||
671 | - power_ctrl = 2; | ||
672 | - delta += 12; | ||
673 | - } else if (delta <= -6) { | ||
674 | - power_ctrl = 1; | ||
675 | - delta += 6; | ||
676 | - } else { | ||
677 | - power_ctrl = 0; | ||
678 | + if (!rt2x00_rt(rt2x00dev, RT3290) && | ||
679 | + !rt2x00_rt(rt2x00dev, RT5390)) { | ||
680 | + rt2800_bbp_read(rt2x00dev, 1, &r1); | ||
681 | + if (delta <= -12) { | ||
682 | + power_ctrl = 2; | ||
683 | + delta += 12; | ||
684 | + } else if (delta <= -6) { | ||
685 | + power_ctrl = 1; | ||
686 | + delta += 6; | ||
687 | + } else { | ||
688 | + power_ctrl = 0; | ||
689 | + } | ||
690 | + rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl); | ||
691 | + rt2800_bbp_write(rt2x00dev, 1, r1); | ||
692 | } | ||
693 | - rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl); | ||
694 | - rt2800_bbp_write(rt2x00dev, 1, r1); | ||
695 | + | ||
696 | offset = TX_PWR_CFG_0; | ||
697 | |||
698 | for (i = 0; i < EEPROM_TXPOWER_BYRATE_SIZE; i += 2) { | ||
699 | diff --git a/drivers/of/base.c b/drivers/of/base.c | ||
700 | index 321d3ef..e77e719 100644 | ||
701 | --- a/drivers/of/base.c | ||
702 | +++ b/drivers/of/base.c | ||
703 | @@ -1166,11 +1166,11 @@ static int __of_parse_phandle_with_args(const struct device_node *np, | ||
704 | out_args->args_count = count; | ||
705 | for (i = 0; i < count; i++) | ||
706 | out_args->args[i] = be32_to_cpup(list++); | ||
707 | + } else { | ||
708 | + of_node_put(node); | ||
709 | } | ||
710 | |||
711 | /* Found it! return success */ | ||
712 | - if (node) | ||
713 | - of_node_put(node); | ||
714 | return 0; | ||
715 | } | ||
716 | |||
717 | diff --git a/fs/exec.c b/fs/exec.c | ||
718 | index 6d56ff2..0d5c76f 100644 | ||
719 | --- a/fs/exec.c | ||
720 | +++ b/fs/exec.c | ||
721 | @@ -1136,13 +1136,6 @@ void setup_new_exec(struct linux_binprm * bprm) | ||
722 | set_dumpable(current->mm, suid_dumpable); | ||
723 | } | ||
724 | |||
725 | - /* | ||
726 | - * Flush performance counters when crossing a | ||
727 | - * security domain: | ||
728 | - */ | ||
729 | - if (!get_dumpable(current->mm)) | ||
730 | - perf_event_exit_task(current); | ||
731 | - | ||
732 | /* An exec changes our domain. We are no longer part of the thread | ||
733 | group */ | ||
734 | |||
735 | @@ -1206,6 +1199,15 @@ void install_exec_creds(struct linux_binprm *bprm) | ||
736 | |||
737 | commit_creds(bprm->cred); | ||
738 | bprm->cred = NULL; | ||
739 | + | ||
740 | + /* | ||
741 | + * Disable monitoring for regular users | ||
742 | + * when executing setuid binaries. Must | ||
743 | + * wait until new credentials are committed | ||
744 | + * by commit_creds() above | ||
745 | + */ | ||
746 | + if (get_dumpable(current->mm) != SUID_DUMP_USER) | ||
747 | + perf_event_exit_task(current); | ||
748 | /* | ||
749 | * cred_guard_mutex must be held at least to this point to prevent | ||
750 | * ptrace_attach() from altering our determination of the task's | ||
751 | diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c | ||
752 | index de08c92f..605af51 100644 | ||
753 | --- a/fs/ubifs/dir.c | ||
754 | +++ b/fs/ubifs/dir.c | ||
755 | @@ -349,31 +349,50 @@ static unsigned int vfs_dent_type(uint8_t type) | ||
756 | static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | ||
757 | { | ||
758 | int err, over = 0; | ||
759 | + loff_t pos = file->f_pos; | ||
760 | struct qstr nm; | ||
761 | union ubifs_key key; | ||
762 | struct ubifs_dent_node *dent; | ||
763 | struct inode *dir = file_inode(file); | ||
764 | struct ubifs_info *c = dir->i_sb->s_fs_info; | ||
765 | |||
766 | - dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos); | ||
767 | + dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, pos); | ||
768 | |||
769 | - if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2) | ||
770 | + if (pos > UBIFS_S_KEY_HASH_MASK || pos == 2) | ||
771 | /* | ||
772 | * The directory was seek'ed to a senseless position or there | ||
773 | * are no more entries. | ||
774 | */ | ||
775 | return 0; | ||
776 | |||
777 | + if (file->f_version == 0) { | ||
778 | + /* | ||
779 | + * The file was seek'ed, which means that @file->private_data | ||
780 | + * is now invalid. This may also be just the first | ||
781 | + * 'ubifs_readdir()' invocation, in which case | ||
782 | + * @file->private_data is NULL, and the below code is | ||
783 | + * basically a no-op. | ||
784 | + */ | ||
785 | + kfree(file->private_data); | ||
786 | + file->private_data = NULL; | ||
787 | + } | ||
788 | + | ||
789 | + /* | ||
790 | + * 'generic_file_llseek()' unconditionally sets @file->f_version to | ||
791 | + * zero, and we use this for detecting whether the file was seek'ed. | ||
792 | + */ | ||
793 | + file->f_version = 1; | ||
794 | + | ||
795 | /* File positions 0 and 1 correspond to "." and ".." */ | ||
796 | - if (file->f_pos == 0) { | ||
797 | + if (pos == 0) { | ||
798 | ubifs_assert(!file->private_data); | ||
799 | over = filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR); | ||
800 | if (over) | ||
801 | return 0; | ||
802 | - file->f_pos = 1; | ||
803 | + file->f_pos = pos = 1; | ||
804 | } | ||
805 | |||
806 | - if (file->f_pos == 1) { | ||
807 | + if (pos == 1) { | ||
808 | ubifs_assert(!file->private_data); | ||
809 | over = filldir(dirent, "..", 2, 1, | ||
810 | parent_ino(file->f_path.dentry), DT_DIR); | ||
811 | @@ -389,7 +408,7 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | ||
812 | goto out; | ||
813 | } | ||
814 | |||
815 | - file->f_pos = key_hash_flash(c, &dent->key); | ||
816 | + file->f_pos = pos = key_hash_flash(c, &dent->key); | ||
817 | file->private_data = dent; | ||
818 | } | ||
819 | |||
820 | @@ -397,17 +416,16 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | ||
821 | if (!dent) { | ||
822 | /* | ||
823 | * The directory was seek'ed to and is now readdir'ed. | ||
824 | - * Find the entry corresponding to @file->f_pos or the | ||
825 | - * closest one. | ||
826 | + * Find the entry corresponding to @pos or the closest one. | ||
827 | */ | ||
828 | - dent_key_init_hash(c, &key, dir->i_ino, file->f_pos); | ||
829 | + dent_key_init_hash(c, &key, dir->i_ino, pos); | ||
830 | nm.name = NULL; | ||
831 | dent = ubifs_tnc_next_ent(c, &key, &nm); | ||
832 | if (IS_ERR(dent)) { | ||
833 | err = PTR_ERR(dent); | ||
834 | goto out; | ||
835 | } | ||
836 | - file->f_pos = key_hash_flash(c, &dent->key); | ||
837 | + file->f_pos = pos = key_hash_flash(c, &dent->key); | ||
838 | file->private_data = dent; | ||
839 | } | ||
840 | |||
841 | @@ -419,7 +437,7 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | ||
842 | ubifs_inode(dir)->creat_sqnum); | ||
843 | |||
844 | nm.len = le16_to_cpu(dent->nlen); | ||
845 | - over = filldir(dirent, dent->name, nm.len, file->f_pos, | ||
846 | + over = filldir(dirent, dent->name, nm.len, pos, | ||
847 | le64_to_cpu(dent->inum), | ||
848 | vfs_dent_type(dent->type)); | ||
849 | if (over) | ||
850 | @@ -435,9 +453,17 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | ||
851 | } | ||
852 | |||
853 | kfree(file->private_data); | ||
854 | - file->f_pos = key_hash_flash(c, &dent->key); | ||
855 | + file->f_pos = pos = key_hash_flash(c, &dent->key); | ||
856 | file->private_data = dent; | ||
857 | cond_resched(); | ||
858 | + | ||
859 | + if (file->f_version == 0) | ||
860 | + /* | ||
861 | + * The file was seek'ed meanwhile, lets return and start | ||
862 | + * reading direntries from the new position on the next | ||
863 | + * invocation. | ||
864 | + */ | ||
865 | + return 0; | ||
866 | } | ||
867 | |||
868 | out: | ||
869 | @@ -448,15 +474,13 @@ out: | ||
870 | |||
871 | kfree(file->private_data); | ||
872 | file->private_data = NULL; | ||
873 | + /* 2 is a special value indicating that there are no more direntries */ | ||
874 | file->f_pos = 2; | ||
875 | return 0; | ||
876 | } | ||
877 | |||
878 | -/* If a directory is seeked, we have to free saved readdir() state */ | ||
879 | static loff_t ubifs_dir_llseek(struct file *file, loff_t offset, int whence) | ||
880 | { | ||
881 | - kfree(file->private_data); | ||
882 | - file->private_data = NULL; | ||
883 | return generic_file_llseek(file, offset, whence); | ||
884 | } | ||
885 | |||
886 | diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c | ||
887 | index a64f8ae..20185ea 100644 | ||
888 | --- a/kernel/events/hw_breakpoint.c | ||
889 | +++ b/kernel/events/hw_breakpoint.c | ||
890 | @@ -120,7 +120,7 @@ static int task_bp_pinned(int cpu, struct perf_event *bp, enum bp_type_idx type) | ||
891 | list_for_each_entry(iter, &bp_task_head, hw.bp_list) { | ||
892 | if (iter->hw.bp_target == tsk && | ||
893 | find_slot_idx(iter) == type && | ||
894 | - cpu == iter->cpu) | ||
895 | + (iter->cpu < 0 || cpu == iter->cpu)) | ||
896 | count += hw_breakpoint_weight(iter); | ||
897 | } | ||
898 | |||
899 | @@ -149,7 +149,7 @@ fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp, | ||
900 | return; | ||
901 | } | ||
902 | |||
903 | - for_each_online_cpu(cpu) { | ||
904 | + for_each_possible_cpu(cpu) { | ||
905 | unsigned int nr; | ||
906 | |||
907 | nr = per_cpu(nr_cpu_bp_pinned[type], cpu); | ||
908 | @@ -235,7 +235,7 @@ toggle_bp_slot(struct perf_event *bp, bool enable, enum bp_type_idx type, | ||
909 | if (cpu >= 0) { | ||
910 | toggle_bp_task_slot(bp, cpu, enable, type, weight); | ||
911 | } else { | ||
912 | - for_each_online_cpu(cpu) | ||
913 | + for_each_possible_cpu(cpu) | ||
914 | toggle_bp_task_slot(bp, cpu, enable, type, weight); | ||
915 | } | ||
916 | |||
917 | diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c | ||
918 | index c5f9cd6..04b32e1 100644 | ||
919 | --- a/net/bluetooth/l2cap_core.c | ||
920 | +++ b/net/bluetooth/l2cap_core.c | ||
921 | @@ -2743,6 +2743,9 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, | ||
922 | BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u", | ||
923 | conn, code, ident, dlen); | ||
924 | |||
925 | + if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE) | ||
926 | + return NULL; | ||
927 | + | ||
928 | len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; | ||
929 | count = min_t(unsigned int, conn->mtu, len); | ||
930 | |||
931 | @@ -4221,7 +4224,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, | ||
932 | struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; | ||
933 | u16 type, result; | ||
934 | |||
935 | - if (cmd_len != sizeof(*rsp)) | ||
936 | + if (cmd_len < sizeof(*rsp)) | ||
937 | return -EPROTO; | ||
938 | |||
939 | type = __le16_to_cpu(rsp->type); | ||
940 | diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | ||
941 | index 2b6c226..a560ae0 100644 | ||
942 | --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | ||
943 | +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | ||
944 | @@ -204,7 +204,7 @@ static unsigned int __ipv6_conntrack_in(struct net *net, | ||
945 | if (ct != NULL && !nf_ct_is_untracked(ct)) { | ||
946 | help = nfct_help(ct); | ||
947 | if ((help && help->helper) || !nf_ct_is_confirmed(ct)) { | ||
948 | - nf_conntrack_get_reasm(skb); | ||
949 | + nf_conntrack_get_reasm(reasm); | ||
950 | NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, reasm, | ||
951 | (struct net_device *)in, | ||
952 | (struct net_device *)out, | ||
953 | diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h | ||
954 | index 5672533..4e74cd6 100644 | ||
955 | --- a/net/mac80211/ieee80211_i.h | ||
956 | +++ b/net/mac80211/ieee80211_i.h | ||
957 | @@ -1520,9 +1520,9 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, | ||
958 | ieee80211_tx_skb_tid(sdata, skb, 7); | ||
959 | } | ||
960 | |||
961 | -void ieee802_11_parse_elems(u8 *start, size_t len, | ||
962 | +void ieee802_11_parse_elems(const u8 *start, size_t len, | ||
963 | struct ieee802_11_elems *elems); | ||
964 | -u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | ||
965 | +u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, | ||
966 | struct ieee802_11_elems *elems, | ||
967 | u64 filter, u32 crc); | ||
968 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, | ||
969 | diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c | ||
970 | index 0a60f40..9726603 100644 | ||
971 | --- a/net/mac80211/mlme.c | ||
972 | +++ b/net/mac80211/mlme.c | ||
973 | @@ -2422,8 +2422,11 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | ||
974 | u16 capab_info, aid; | ||
975 | struct ieee802_11_elems elems; | ||
976 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | ||
977 | + const struct cfg80211_bss_ies *bss_ies = NULL; | ||
978 | + struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data; | ||
979 | u32 changed = 0; | ||
980 | int err; | ||
981 | + bool ret; | ||
982 | |||
983 | /* AssocResp and ReassocResp have identical structure */ | ||
984 | |||
985 | @@ -2455,21 +2458,86 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | ||
986 | ifmgd->aid = aid; | ||
987 | |||
988 | /* | ||
989 | + * Some APs are erroneously not including some information in their | ||
990 | + * (re)association response frames. Try to recover by using the data | ||
991 | + * from the beacon or probe response. This seems to afflict mobile | ||
992 | + * 2G/3G/4G wifi routers, reported models include the "Onda PN51T", | ||
993 | + * "Vodafone PocketWiFi 2", "ZTE MF60" and a similar T-Mobile device. | ||
994 | + */ | ||
995 | + if ((assoc_data->wmm && !elems.wmm_param) || | ||
996 | + (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && | ||
997 | + (!elems.ht_cap_elem || !elems.ht_operation)) || | ||
998 | + (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && | ||
999 | + (!elems.vht_cap_elem || !elems.vht_operation))) { | ||
1000 | + const struct cfg80211_bss_ies *ies; | ||
1001 | + struct ieee802_11_elems bss_elems; | ||
1002 | + | ||
1003 | + rcu_read_lock(); | ||
1004 | + ies = rcu_dereference(cbss->ies); | ||
1005 | + if (ies) | ||
1006 | + bss_ies = kmemdup(ies, sizeof(*ies) + ies->len, | ||
1007 | + GFP_ATOMIC); | ||
1008 | + rcu_read_unlock(); | ||
1009 | + if (!bss_ies) | ||
1010 | + return false; | ||
1011 | + | ||
1012 | + ieee802_11_parse_elems(bss_ies->data, bss_ies->len, | ||
1013 | + &bss_elems); | ||
1014 | + if (assoc_data->wmm && | ||
1015 | + !elems.wmm_param && bss_elems.wmm_param) { | ||
1016 | + elems.wmm_param = bss_elems.wmm_param; | ||
1017 | + sdata_info(sdata, | ||
1018 | + "AP bug: WMM param missing from AssocResp\n"); | ||
1019 | + } | ||
1020 | + | ||
1021 | + /* | ||
1022 | + * Also check if we requested HT/VHT, otherwise the AP doesn't | ||
1023 | + * have to include the IEs in the (re)association response. | ||
1024 | + */ | ||
1025 | + if (!elems.ht_cap_elem && bss_elems.ht_cap_elem && | ||
1026 | + !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { | ||
1027 | + elems.ht_cap_elem = bss_elems.ht_cap_elem; | ||
1028 | + sdata_info(sdata, | ||
1029 | + "AP bug: HT capability missing from AssocResp\n"); | ||
1030 | + } | ||
1031 | + if (!elems.ht_operation && bss_elems.ht_operation && | ||
1032 | + !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { | ||
1033 | + elems.ht_operation = bss_elems.ht_operation; | ||
1034 | + sdata_info(sdata, | ||
1035 | + "AP bug: HT operation missing from AssocResp\n"); | ||
1036 | + } | ||
1037 | + if (!elems.vht_cap_elem && bss_elems.vht_cap_elem && | ||
1038 | + !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) { | ||
1039 | + elems.vht_cap_elem = bss_elems.vht_cap_elem; | ||
1040 | + sdata_info(sdata, | ||
1041 | + "AP bug: VHT capa missing from AssocResp\n"); | ||
1042 | + } | ||
1043 | + if (!elems.vht_operation && bss_elems.vht_operation && | ||
1044 | + !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) { | ||
1045 | + elems.vht_operation = bss_elems.vht_operation; | ||
1046 | + sdata_info(sdata, | ||
1047 | + "AP bug: VHT operation missing from AssocResp\n"); | ||
1048 | + } | ||
1049 | + } | ||
1050 | + | ||
1051 | + /* | ||
1052 | * We previously checked these in the beacon/probe response, so | ||
1053 | * they should be present here. This is just a safety net. | ||
1054 | */ | ||
1055 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && | ||
1056 | (!elems.wmm_param || !elems.ht_cap_elem || !elems.ht_operation)) { | ||
1057 | sdata_info(sdata, | ||
1058 | - "HT AP is missing WMM params or HT capability/operation in AssocResp\n"); | ||
1059 | - return false; | ||
1060 | + "HT AP is missing WMM params or HT capability/operation\n"); | ||
1061 | + ret = false; | ||
1062 | + goto out; | ||
1063 | } | ||
1064 | |||
1065 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && | ||
1066 | (!elems.vht_cap_elem || !elems.vht_operation)) { | ||
1067 | sdata_info(sdata, | ||
1068 | - "VHT AP is missing VHT capability/operation in AssocResp\n"); | ||
1069 | - return false; | ||
1070 | + "VHT AP is missing VHT capability/operation\n"); | ||
1071 | + ret = false; | ||
1072 | + goto out; | ||
1073 | } | ||
1074 | |||
1075 | mutex_lock(&sdata->local->sta_mtx); | ||
1076 | @@ -2480,7 +2548,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | ||
1077 | sta = sta_info_get(sdata, cbss->bssid); | ||
1078 | if (WARN_ON(!sta)) { | ||
1079 | mutex_unlock(&sdata->local->sta_mtx); | ||
1080 | - return false; | ||
1081 | + ret = false; | ||
1082 | + goto out; | ||
1083 | } | ||
1084 | |||
1085 | sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; | ||
1086 | @@ -2533,7 +2602,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | ||
1087 | sta->sta.addr); | ||
1088 | WARN_ON(__sta_info_destroy(sta)); | ||
1089 | mutex_unlock(&sdata->local->sta_mtx); | ||
1090 | - return false; | ||
1091 | + ret = false; | ||
1092 | + goto out; | ||
1093 | } | ||
1094 | |||
1095 | mutex_unlock(&sdata->local->sta_mtx); | ||
1096 | @@ -2573,7 +2643,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | ||
1097 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); | ||
1098 | ieee80211_sta_reset_beacon_monitor(sdata); | ||
1099 | |||
1100 | - return true; | ||
1101 | + ret = true; | ||
1102 | + out: | ||
1103 | + kfree(bss_ies); | ||
1104 | + return ret; | ||
1105 | } | ||
1106 | |||
1107 | static enum rx_mgmt_action __must_check | ||
1108 | diff --git a/net/mac80211/util.c b/net/mac80211/util.c | ||
1109 | index 0f38f43..1f4b908 100644 | ||
1110 | --- a/net/mac80211/util.c | ||
1111 | +++ b/net/mac80211/util.c | ||
1112 | @@ -626,12 +626,12 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw, | ||
1113 | } | ||
1114 | EXPORT_SYMBOL(ieee80211_queue_delayed_work); | ||
1115 | |||
1116 | -u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | ||
1117 | +u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, | ||
1118 | struct ieee802_11_elems *elems, | ||
1119 | u64 filter, u32 crc) | ||
1120 | { | ||
1121 | size_t left = len; | ||
1122 | - u8 *pos = start; | ||
1123 | + const u8 *pos = start; | ||
1124 | bool calc_crc = filter != 0; | ||
1125 | DECLARE_BITMAP(seen_elems, 256); | ||
1126 | |||
1127 | @@ -877,7 +877,7 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | ||
1128 | return crc; | ||
1129 | } | ||
1130 | |||
1131 | -void ieee802_11_parse_elems(u8 *start, size_t len, | ||
1132 | +void ieee802_11_parse_elems(const u8 *start, size_t len, | ||
1133 | struct ieee802_11_elems *elems) | ||
1134 | { | ||
1135 | ieee802_11_parse_elems_crc(start, len, elems, 0, 0); |