Contents of /trunk/kernel-magellan/patches-3.6/0106-3.6.7-all-fixes.patch
Parent Directory | Revision Log
Revision 1960 -
(show annotations)
(download)
Mon Nov 19 08:41:04 2012 UTC (11 years, 10 months ago) by niro
File size: 102677 byte(s)
Mon Nov 19 08:41:04 2012 UTC (11 years, 10 months ago) by niro
File size: 102677 byte(s)
-3.6.7-magellan-r1
1 | diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c |
2 | index 5141d80..dde1a3f 100644 |
3 | --- a/arch/x86/xen/mmu.c |
4 | +++ b/arch/x86/xen/mmu.c |
5 | @@ -1215,6 +1215,25 @@ unsigned long xen_read_cr2_direct(void) |
6 | return this_cpu_read(xen_vcpu_info.arch.cr2); |
7 | } |
8 | |
9 | +void xen_flush_tlb_all(void) |
10 | +{ |
11 | + struct mmuext_op *op; |
12 | + struct multicall_space mcs; |
13 | + |
14 | + trace_xen_mmu_flush_tlb_all(0); |
15 | + |
16 | + preempt_disable(); |
17 | + |
18 | + mcs = xen_mc_entry(sizeof(*op)); |
19 | + |
20 | + op = mcs.args; |
21 | + op->cmd = MMUEXT_TLB_FLUSH_ALL; |
22 | + MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); |
23 | + |
24 | + xen_mc_issue(PARAVIRT_LAZY_MMU); |
25 | + |
26 | + preempt_enable(); |
27 | +} |
28 | static void xen_flush_tlb(void) |
29 | { |
30 | struct mmuext_op *op; |
31 | @@ -2366,7 +2385,7 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma, |
32 | err = 0; |
33 | out: |
34 | |
35 | - flush_tlb_all(); |
36 | + xen_flush_tlb_all(); |
37 | |
38 | return err; |
39 | } |
40 | diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c |
41 | index 5062eec..7aff5c7 100644 |
42 | --- a/drivers/gpu/drm/drm_fops.c |
43 | +++ b/drivers/gpu/drm/drm_fops.c |
44 | @@ -121,6 +121,8 @@ int drm_open(struct inode *inode, struct file *filp) |
45 | int minor_id = iminor(inode); |
46 | struct drm_minor *minor; |
47 | int retcode = 0; |
48 | + int need_setup = 0; |
49 | + struct address_space *old_mapping; |
50 | |
51 | minor = idr_find(&drm_minors_idr, minor_id); |
52 | if (!minor) |
53 | @@ -132,23 +134,37 @@ int drm_open(struct inode *inode, struct file *filp) |
54 | if (drm_device_is_unplugged(dev)) |
55 | return -ENODEV; |
56 | |
57 | + if (!dev->open_count++) |
58 | + need_setup = 1; |
59 | + mutex_lock(&dev->struct_mutex); |
60 | + old_mapping = dev->dev_mapping; |
61 | + if (old_mapping == NULL) |
62 | + dev->dev_mapping = &inode->i_data; |
63 | + /* ihold ensures nobody can remove inode with our i_data */ |
64 | + ihold(container_of(dev->dev_mapping, struct inode, i_data)); |
65 | + inode->i_mapping = dev->dev_mapping; |
66 | + filp->f_mapping = dev->dev_mapping; |
67 | + mutex_unlock(&dev->struct_mutex); |
68 | + |
69 | retcode = drm_open_helper(inode, filp, dev); |
70 | - if (!retcode) { |
71 | - atomic_inc(&dev->counts[_DRM_STAT_OPENS]); |
72 | - if (!dev->open_count++) |
73 | - retcode = drm_setup(dev); |
74 | - } |
75 | - if (!retcode) { |
76 | - mutex_lock(&dev->struct_mutex); |
77 | - if (dev->dev_mapping == NULL) |
78 | - dev->dev_mapping = &inode->i_data; |
79 | - /* ihold ensures nobody can remove inode with our i_data */ |
80 | - ihold(container_of(dev->dev_mapping, struct inode, i_data)); |
81 | - inode->i_mapping = dev->dev_mapping; |
82 | - filp->f_mapping = dev->dev_mapping; |
83 | - mutex_unlock(&dev->struct_mutex); |
84 | + if (retcode) |
85 | + goto err_undo; |
86 | + atomic_inc(&dev->counts[_DRM_STAT_OPENS]); |
87 | + if (need_setup) { |
88 | + retcode = drm_setup(dev); |
89 | + if (retcode) |
90 | + goto err_undo; |
91 | } |
92 | + return 0; |
93 | |
94 | +err_undo: |
95 | + mutex_lock(&dev->struct_mutex); |
96 | + filp->f_mapping = old_mapping; |
97 | + inode->i_mapping = old_mapping; |
98 | + iput(container_of(dev->dev_mapping, struct inode, i_data)); |
99 | + dev->dev_mapping = old_mapping; |
100 | + mutex_unlock(&dev->struct_mutex); |
101 | + dev->open_count--; |
102 | return retcode; |
103 | } |
104 | EXPORT_SYMBOL(drm_open); |
105 | diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c |
106 | index 914c0df..0969a7c 100644 |
107 | --- a/drivers/gpu/drm/i915/i915_dma.c |
108 | +++ b/drivers/gpu/drm/i915/i915_dma.c |
109 | @@ -1484,7 +1484,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) |
110 | goto put_gmch; |
111 | } |
112 | |
113 | - i915_kick_out_firmware_fb(dev_priv); |
114 | + if (drm_core_check_feature(dev, DRIVER_MODESET)) |
115 | + i915_kick_out_firmware_fb(dev_priv); |
116 | |
117 | pci_set_master(dev->pdev); |
118 | |
119 | diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c |
120 | index 830d0dd..cf49a57 100644 |
121 | --- a/drivers/gpu/drm/i915/intel_overlay.c |
122 | +++ b/drivers/gpu/drm/i915/intel_overlay.c |
123 | @@ -431,9 +431,17 @@ static int intel_overlay_off(struct intel_overlay *overlay) |
124 | intel_ring_emit(ring, flip_addr); |
125 | intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); |
126 | /* turn overlay off */ |
127 | - intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); |
128 | - intel_ring_emit(ring, flip_addr); |
129 | - intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); |
130 | + if (IS_I830(dev)) { |
131 | + /* Workaround: Don't disable the overlay fully, since otherwise |
132 | + * it dies on the next OVERLAY_ON cmd. */ |
133 | + intel_ring_emit(ring, MI_NOOP); |
134 | + intel_ring_emit(ring, MI_NOOP); |
135 | + intel_ring_emit(ring, MI_NOOP); |
136 | + } else { |
137 | + intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); |
138 | + intel_ring_emit(ring, flip_addr); |
139 | + intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); |
140 | + } |
141 | intel_ring_advance(ring); |
142 | |
143 | return intel_overlay_do_wait_request(overlay, request, |
144 | diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c |
145 | index 123afd3..20cb52d 100644 |
146 | --- a/drivers/gpu/drm/i915/intel_sdvo.c |
147 | +++ b/drivers/gpu/drm/i915/intel_sdvo.c |
148 | @@ -882,6 +882,45 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo) |
149 | } |
150 | #endif |
151 | |
152 | +static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo, |
153 | + unsigned if_index, uint8_t tx_rate, |
154 | + uint8_t *data, unsigned length) |
155 | +{ |
156 | + uint8_t set_buf_index[2] = { if_index, 0 }; |
157 | + uint8_t hbuf_size, tmp[8]; |
158 | + int i; |
159 | + |
160 | + if (!intel_sdvo_set_value(intel_sdvo, |
161 | + SDVO_CMD_SET_HBUF_INDEX, |
162 | + set_buf_index, 2)) |
163 | + return false; |
164 | + |
165 | + if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO, |
166 | + &hbuf_size, 1)) |
167 | + return false; |
168 | + |
169 | + /* Buffer size is 0 based, hooray! */ |
170 | + hbuf_size++; |
171 | + |
172 | + DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n", |
173 | + if_index, length, hbuf_size); |
174 | + |
175 | + for (i = 0; i < hbuf_size; i += 8) { |
176 | + memset(tmp, 0, 8); |
177 | + if (i < length) |
178 | + memcpy(tmp, data + i, min_t(unsigned, 8, length - i)); |
179 | + |
180 | + if (!intel_sdvo_set_value(intel_sdvo, |
181 | + SDVO_CMD_SET_HBUF_DATA, |
182 | + tmp, 8)) |
183 | + return false; |
184 | + } |
185 | + |
186 | + return intel_sdvo_set_value(intel_sdvo, |
187 | + SDVO_CMD_SET_HBUF_TXRATE, |
188 | + &tx_rate, 1); |
189 | +} |
190 | + |
191 | static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) |
192 | { |
193 | struct dip_infoframe avi_if = { |
194 | @@ -889,11 +928,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) |
195 | .ver = DIP_VERSION_AVI, |
196 | .len = DIP_LEN_AVI, |
197 | }; |
198 | - uint8_t tx_rate = SDVO_HBUF_TX_VSYNC; |
199 | - uint8_t set_buf_index[2] = { 1, 0 }; |
200 | uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)]; |
201 | - uint64_t *data = (uint64_t *)sdvo_data; |
202 | - unsigned i; |
203 | |
204 | intel_dip_infoframe_csum(&avi_if); |
205 | |
206 | @@ -903,22 +938,9 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) |
207 | sdvo_data[3] = avi_if.checksum; |
208 | memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi)); |
209 | |
210 | - if (!intel_sdvo_set_value(intel_sdvo, |
211 | - SDVO_CMD_SET_HBUF_INDEX, |
212 | - set_buf_index, 2)) |
213 | - return false; |
214 | - |
215 | - for (i = 0; i < sizeof(sdvo_data); i += 8) { |
216 | - if (!intel_sdvo_set_value(intel_sdvo, |
217 | - SDVO_CMD_SET_HBUF_DATA, |
218 | - data, 8)) |
219 | - return false; |
220 | - data++; |
221 | - } |
222 | - |
223 | - return intel_sdvo_set_value(intel_sdvo, |
224 | - SDVO_CMD_SET_HBUF_TXRATE, |
225 | - &tx_rate, 1); |
226 | + return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF, |
227 | + SDVO_HBUF_TX_VSYNC, |
228 | + sdvo_data, sizeof(sdvo_data)); |
229 | } |
230 | |
231 | static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) |
232 | diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h |
233 | index 9d03014..770bdd6 100644 |
234 | --- a/drivers/gpu/drm/i915/intel_sdvo_regs.h |
235 | +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h |
236 | @@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg { |
237 | #define SDVO_CMD_SET_AUDIO_STAT 0x91 |
238 | #define SDVO_CMD_GET_AUDIO_STAT 0x92 |
239 | #define SDVO_CMD_SET_HBUF_INDEX 0x93 |
240 | + #define SDVO_HBUF_INDEX_ELD 0 |
241 | + #define SDVO_HBUF_INDEX_AVI_IF 1 |
242 | #define SDVO_CMD_GET_HBUF_INDEX 0x94 |
243 | #define SDVO_CMD_GET_HBUF_INFO 0x95 |
244 | #define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96 |
245 | diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c |
246 | index e932810..4a33cdc 100644 |
247 | --- a/drivers/gpu/drm/radeon/evergreen_cs.c |
248 | +++ b/drivers/gpu/drm/radeon/evergreen_cs.c |
249 | @@ -2725,6 +2725,9 @@ static bool evergreen_vm_reg_valid(u32 reg) |
250 | /* check config regs */ |
251 | switch (reg) { |
252 | case GRBM_GFX_INDEX: |
253 | + case CP_STRMOUT_CNTL: |
254 | + case CP_COHER_CNTL: |
255 | + case CP_COHER_SIZE: |
256 | case VGT_VTX_VECT_EJECT_REG: |
257 | case VGT_CACHE_INVALIDATION: |
258 | case VGT_GS_VERTEX_REUSE: |
259 | diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h |
260 | index 7934785..302af4f 100644 |
261 | --- a/drivers/gpu/drm/radeon/evergreend.h |
262 | +++ b/drivers/gpu/drm/radeon/evergreend.h |
263 | @@ -87,6 +87,10 @@ |
264 | |
265 | #define CONFIG_MEMSIZE 0x5428 |
266 | |
267 | +#define CP_STRMOUT_CNTL 0x84FC |
268 | + |
269 | +#define CP_COHER_CNTL 0x85F0 |
270 | +#define CP_COHER_SIZE 0x85F4 |
271 | #define CP_COHER_BASE 0x85F8 |
272 | #define CP_STALLED_STAT1 0x8674 |
273 | #define CP_STALLED_STAT2 0x8678 |
274 | diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c |
275 | index d16f50f..dd402bb 100644 |
276 | --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c |
277 | +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c |
278 | @@ -651,6 +651,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc |
279 | tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN; |
280 | WREG32(RADEON_DAC_CNTL, tmp); |
281 | |
282 | + tmp = dac_macro_cntl; |
283 | tmp &= ~(RADEON_DAC_PDWN_R | |
284 | RADEON_DAC_PDWN_G | |
285 | RADEON_DAC_PDWN_B); |
286 | diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c |
287 | index 0139e22..6ab4a90 100644 |
288 | --- a/drivers/gpu/drm/radeon/si.c |
289 | +++ b/drivers/gpu/drm/radeon/si.c |
290 | @@ -2472,6 +2472,7 @@ static bool si_vm_reg_valid(u32 reg) |
291 | /* check config regs */ |
292 | switch (reg) { |
293 | case GRBM_GFX_INDEX: |
294 | + case CP_STRMOUT_CNTL: |
295 | case VGT_VTX_VECT_EJECT_REG: |
296 | case VGT_CACHE_INVALIDATION: |
297 | case VGT_ESGS_RING_SIZE: |
298 | diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h |
299 | index ef4815c..6f0083a 100644 |
300 | --- a/drivers/gpu/drm/radeon/sid.h |
301 | +++ b/drivers/gpu/drm/radeon/sid.h |
302 | @@ -424,6 +424,7 @@ |
303 | # define RDERR_INT_ENABLE (1 << 0) |
304 | # define GUI_IDLE_INT_ENABLE (1 << 19) |
305 | |
306 | +#define CP_STRMOUT_CNTL 0x84FC |
307 | #define SCRATCH_REG0 0x8500 |
308 | #define SCRATCH_REG1 0x8504 |
309 | #define SCRATCH_REG2 0x8508 |
310 | diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h |
311 | index fccd361..87aa5f5 100644 |
312 | --- a/drivers/gpu/drm/udl/udl_drv.h |
313 | +++ b/drivers/gpu/drm/udl/udl_drv.h |
314 | @@ -104,7 +104,7 @@ udl_fb_user_fb_create(struct drm_device *dev, |
315 | |
316 | int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, |
317 | const char *front, char **urb_buf_ptr, |
318 | - u32 byte_offset, u32 byte_width, |
319 | + u32 byte_offset, u32 device_byte_offset, u32 byte_width, |
320 | int *ident_ptr, int *sent_ptr); |
321 | |
322 | int udl_dumb_create(struct drm_file *file_priv, |
323 | diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c |
324 | index ce9a611..6f6ca50 100644 |
325 | --- a/drivers/gpu/drm/udl/udl_fb.c |
326 | +++ b/drivers/gpu/drm/udl/udl_fb.c |
327 | @@ -114,9 +114,10 @@ static void udlfb_dpy_deferred_io(struct fb_info *info, |
328 | list_for_each_entry(cur, &fbdefio->pagelist, lru) { |
329 | |
330 | if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8), |
331 | - &urb, (char *) info->fix.smem_start, |
332 | - &cmd, cur->index << PAGE_SHIFT, |
333 | - PAGE_SIZE, &bytes_identical, &bytes_sent)) |
334 | + &urb, (char *) info->fix.smem_start, |
335 | + &cmd, cur->index << PAGE_SHIFT, |
336 | + cur->index << PAGE_SHIFT, |
337 | + PAGE_SIZE, &bytes_identical, &bytes_sent)) |
338 | goto error; |
339 | bytes_rendered += PAGE_SIZE; |
340 | } |
341 | @@ -187,10 +188,11 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, |
342 | for (i = y; i < y + height ; i++) { |
343 | const int line_offset = fb->base.pitches[0] * i; |
344 | const int byte_offset = line_offset + (x * bpp); |
345 | - |
346 | + const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp); |
347 | if (udl_render_hline(dev, bpp, &urb, |
348 | (char *) fb->obj->vmapping, |
349 | - &cmd, byte_offset, width * bpp, |
350 | + &cmd, byte_offset, dev_byte_offset, |
351 | + width * bpp, |
352 | &bytes_identical, &bytes_sent)) |
353 | goto error; |
354 | } |
355 | diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c |
356 | index b9320e2..fc11344 100644 |
357 | --- a/drivers/gpu/drm/udl/udl_transfer.c |
358 | +++ b/drivers/gpu/drm/udl/udl_transfer.c |
359 | @@ -213,11 +213,12 @@ static void udl_compress_hline16( |
360 | */ |
361 | int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, |
362 | const char *front, char **urb_buf_ptr, |
363 | - u32 byte_offset, u32 byte_width, |
364 | + u32 byte_offset, u32 device_byte_offset, |
365 | + u32 byte_width, |
366 | int *ident_ptr, int *sent_ptr) |
367 | { |
368 | const u8 *line_start, *line_end, *next_pixel; |
369 | - u32 base16 = 0 + (byte_offset / bpp) * 2; |
370 | + u32 base16 = 0 + (device_byte_offset / bpp) * 2; |
371 | struct urb *urb = *urb_ptr; |
372 | u8 *cmd = *urb_buf_ptr; |
373 | u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; |
374 | diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c |
375 | index 3fa884d..27151f7 100644 |
376 | --- a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c |
377 | +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c |
378 | @@ -306,7 +306,7 @@ void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin) |
379 | |
380 | BUG_ON(!atomic_read(&bo->reserved)); |
381 | BUG_ON(old_mem_type != TTM_PL_VRAM && |
382 | - old_mem_type != VMW_PL_FLAG_GMR); |
383 | + old_mem_type != VMW_PL_GMR); |
384 | |
385 | pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED; |
386 | if (pin) |
387 | diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c |
388 | index ba2c35d..4a04ae0 100644 |
389 | --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c |
390 | +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c |
391 | @@ -1099,6 +1099,11 @@ static void vmw_pm_complete(struct device *kdev) |
392 | struct drm_device *dev = pci_get_drvdata(pdev); |
393 | struct vmw_private *dev_priv = vmw_priv(dev); |
394 | |
395 | + mutex_lock(&dev_priv->hw_mutex); |
396 | + vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); |
397 | + (void) vmw_read(dev_priv, SVGA_REG_ID); |
398 | + mutex_unlock(&dev_priv->hw_mutex); |
399 | + |
400 | /** |
401 | * Reclaim 3d reference held by fbdev and potentially |
402 | * start fifo. |
403 | diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c |
404 | index 1821b74..de3c7e0 100644 |
405 | --- a/drivers/hwmon/w83627ehf.c |
406 | +++ b/drivers/hwmon/w83627ehf.c |
407 | @@ -2083,6 +2083,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) |
408 | mutex_init(&data->lock); |
409 | mutex_init(&data->update_lock); |
410 | data->name = w83627ehf_device_names[sio_data->kind]; |
411 | + data->bank = 0xff; /* Force initial bank selection */ |
412 | platform_set_drvdata(pdev, data); |
413 | |
414 | /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */ |
415 | diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c |
416 | index 63209aa..eb96f16 100644 |
417 | --- a/drivers/input/touchscreen/tsc40.c |
418 | +++ b/drivers/input/touchscreen/tsc40.c |
419 | @@ -107,7 +107,6 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv) |
420 | __set_bit(BTN_TOUCH, input_dev->keybit); |
421 | input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0); |
422 | input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0); |
423 | - input_set_abs_params(ptsc->dev, ABS_PRESSURE, 0, 0, 0, 0); |
424 | |
425 | serio_set_drvdata(serio, ptsc); |
426 | |
427 | diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c |
428 | index 9a11dc3..b1facf9 100644 |
429 | --- a/drivers/mmc/host/sdhci.c |
430 | +++ b/drivers/mmc/host/sdhci.c |
431 | @@ -1307,16 +1307,19 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) |
432 | */ |
433 | if ((host->flags & SDHCI_NEEDS_RETUNING) && |
434 | !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) { |
435 | - /* eMMC uses cmd21 while sd and sdio use cmd19 */ |
436 | - tuning_opcode = mmc->card->type == MMC_TYPE_MMC ? |
437 | - MMC_SEND_TUNING_BLOCK_HS200 : |
438 | - MMC_SEND_TUNING_BLOCK; |
439 | - spin_unlock_irqrestore(&host->lock, flags); |
440 | - sdhci_execute_tuning(mmc, tuning_opcode); |
441 | - spin_lock_irqsave(&host->lock, flags); |
442 | - |
443 | - /* Restore original mmc_request structure */ |
444 | - host->mrq = mrq; |
445 | + if (mmc->card) { |
446 | + /* eMMC uses cmd21 but sd and sdio use cmd19 */ |
447 | + tuning_opcode = |
448 | + mmc->card->type == MMC_TYPE_MMC ? |
449 | + MMC_SEND_TUNING_BLOCK_HS200 : |
450 | + MMC_SEND_TUNING_BLOCK; |
451 | + spin_unlock_irqrestore(&host->lock, flags); |
452 | + sdhci_execute_tuning(mmc, tuning_opcode); |
453 | + spin_lock_irqsave(&host->lock, flags); |
454 | + |
455 | + /* Restore original mmc_request structure */ |
456 | + host->mrq = mrq; |
457 | + } |
458 | } |
459 | |
460 | if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23)) |
461 | diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c |
462 | index ba0e493..9058d21 100644 |
463 | --- a/drivers/mmc/host/sh_mmcif.c |
464 | +++ b/drivers/mmc/host/sh_mmcif.c |
465 | @@ -1464,9 +1464,9 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev) |
466 | |
467 | platform_set_drvdata(pdev, NULL); |
468 | |
469 | + clk_disable(host->hclk); |
470 | mmc_free_host(host->mmc); |
471 | pm_runtime_put_sync(&pdev->dev); |
472 | - clk_disable(host->hclk); |
473 | pm_runtime_disable(&pdev->dev); |
474 | |
475 | return 0; |
476 | diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c |
477 | index 56b20d1..116f0e9 100644 |
478 | --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c |
479 | +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c |
480 | @@ -2673,6 +2673,9 @@ static int ixgbe_get_ts_info(struct net_device *dev, |
481 | case ixgbe_mac_X540: |
482 | case ixgbe_mac_82599EB: |
483 | info->so_timestamping = |
484 | + SOF_TIMESTAMPING_TX_SOFTWARE | |
485 | + SOF_TIMESTAMPING_RX_SOFTWARE | |
486 | + SOF_TIMESTAMPING_SOFTWARE | |
487 | SOF_TIMESTAMPING_TX_HARDWARE | |
488 | SOF_TIMESTAMPING_RX_HARDWARE | |
489 | SOF_TIMESTAMPING_RAW_HARDWARE; |
490 | diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c |
491 | index 53743f7..af8b414 100644 |
492 | --- a/drivers/net/ethernet/nxp/lpc_eth.c |
493 | +++ b/drivers/net/ethernet/nxp/lpc_eth.c |
494 | @@ -1524,6 +1524,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev) |
495 | pldat->dma_buff_base_p); |
496 | free_irq(ndev->irq, ndev); |
497 | iounmap(pldat->net_base); |
498 | + mdiobus_unregister(pldat->mii_bus); |
499 | mdiobus_free(pldat->mii_bus); |
500 | clk_disable(pldat->clk); |
501 | clk_put(pldat->clk); |
502 | diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c |
503 | index fc9f578..9c382b5 100644 |
504 | --- a/drivers/net/usb/usbnet.c |
505 | +++ b/drivers/net/usb/usbnet.c |
506 | @@ -1158,6 +1158,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, |
507 | usb_anchor_urb(urb, &dev->deferred); |
508 | /* no use to process more packets */ |
509 | netif_stop_queue(net); |
510 | + usb_put_urb(urb); |
511 | spin_unlock_irqrestore(&dev->txq.lock, flags); |
512 | netdev_dbg(dev->net, "Delaying transmission for resumption\n"); |
513 | goto deferred; |
514 | @@ -1310,6 +1311,8 @@ void usbnet_disconnect (struct usb_interface *intf) |
515 | |
516 | cancel_work_sync(&dev->kevent); |
517 | |
518 | + usb_scuttle_anchored_urbs(&dev->deferred); |
519 | + |
520 | if (dev->driver_info->unbind) |
521 | dev->driver_info->unbind (dev, intf); |
522 | |
523 | diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c |
524 | index 423a9f3..88b6acc 100644 |
525 | --- a/drivers/net/wireless/ath/ath9k/xmit.c |
526 | +++ b/drivers/net/wireless/ath/ath9k/xmit.c |
527 | @@ -312,6 +312,7 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) |
528 | } |
529 | |
530 | bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); |
531 | + bf->bf_next = NULL; |
532 | list_del(&bf->list); |
533 | |
534 | spin_unlock_bh(&sc->tx.txbuflock); |
535 | @@ -393,7 +394,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, |
536 | u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first; |
537 | u32 ba[WME_BA_BMP_SIZE >> 5]; |
538 | int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; |
539 | - bool rc_update = true; |
540 | + bool rc_update = true, isba; |
541 | struct ieee80211_tx_rate rates[4]; |
542 | struct ath_frame_info *fi; |
543 | int nframes; |
544 | @@ -437,13 +438,17 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, |
545 | tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; |
546 | tid = ATH_AN_2_TID(an, tidno); |
547 | seq_first = tid->seq_start; |
548 | + isba = ts->ts_flags & ATH9K_TX_BA; |
549 | |
550 | /* |
551 | * The hardware occasionally sends a tx status for the wrong TID. |
552 | * In this case, the BA status cannot be considered valid and all |
553 | * subframes need to be retransmitted |
554 | + * |
555 | + * Only BlockAcks have a TID and therefore normal Acks cannot be |
556 | + * checked |
557 | */ |
558 | - if (tidno != ts->tid) |
559 | + if (isba && tidno != ts->tid) |
560 | txok = false; |
561 | |
562 | isaggr = bf_isaggr(bf); |
563 | @@ -1774,6 +1779,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, |
564 | list_add_tail(&bf->list, &bf_head); |
565 | bf->bf_state.bf_type = 0; |
566 | |
567 | + bf->bf_next = NULL; |
568 | bf->bf_lastbf = bf; |
569 | ath_tx_fill_desc(sc, bf, txq, fi->framelen); |
570 | ath_tx_txqaddbuf(sc, txq, &bf_head, false); |
571 | diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c |
572 | index b93516d..1345bdd 100644 |
573 | --- a/drivers/net/wireless/rt2x00/rt2800lib.c |
574 | +++ b/drivers/net/wireless/rt2x00/rt2800lib.c |
575 | @@ -2395,7 +2395,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) |
576 | /* |
577 | * Check if temperature compensation is supported. |
578 | */ |
579 | - if (tssi_bounds[4] == 0xff) |
580 | + if (tssi_bounds[4] == 0xff || step == 0xff) |
581 | return 0; |
582 | |
583 | /* |
584 | diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c |
585 | index dd4fce2..6b6f50a 100644 |
586 | --- a/drivers/target/iscsi/iscsi_target.c |
587 | +++ b/drivers/target/iscsi/iscsi_target.c |
588 | @@ -3735,7 +3735,9 @@ restart: |
589 | */ |
590 | iscsit_thread_check_cpumask(conn, current, 1); |
591 | |
592 | - schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT); |
593 | + wait_event_interruptible(conn->queues_wq, |
594 | + !iscsit_conn_all_queues_empty(conn) || |
595 | + ts->status == ISCSI_THREAD_SET_RESET); |
596 | |
597 | if ((ts->status == ISCSI_THREAD_SET_RESET) || |
598 | signal_pending(current)) |
599 | diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h |
600 | index a90294f..1d63d56 100644 |
601 | --- a/drivers/target/iscsi/iscsi_target_core.h |
602 | +++ b/drivers/target/iscsi/iscsi_target_core.h |
603 | @@ -486,6 +486,7 @@ struct iscsi_tmr_req { |
604 | }; |
605 | |
606 | struct iscsi_conn { |
607 | + wait_queue_head_t queues_wq; |
608 | /* Authentication Successful for this connection */ |
609 | u8 auth_complete; |
610 | /* State connection is currently in */ |
611 | diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c |
612 | index 6aba439..7b643ab 100644 |
613 | --- a/drivers/target/iscsi/iscsi_target_login.c |
614 | +++ b/drivers/target/iscsi/iscsi_target_login.c |
615 | @@ -45,6 +45,7 @@ extern spinlock_t sess_idr_lock; |
616 | |
617 | static int iscsi_login_init_conn(struct iscsi_conn *conn) |
618 | { |
619 | + init_waitqueue_head(&conn->queues_wq); |
620 | INIT_LIST_HEAD(&conn->conn_list); |
621 | INIT_LIST_HEAD(&conn->conn_cmd_list); |
622 | INIT_LIST_HEAD(&conn->immed_queue_list); |
623 | diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c |
624 | index b42cdeb..552f45a 100644 |
625 | --- a/drivers/target/iscsi/iscsi_target_util.c |
626 | +++ b/drivers/target/iscsi/iscsi_target_util.c |
627 | @@ -488,7 +488,7 @@ void iscsit_add_cmd_to_immediate_queue( |
628 | atomic_set(&conn->check_immediate_queue, 1); |
629 | spin_unlock_bh(&conn->immed_queue_lock); |
630 | |
631 | - wake_up_process(conn->thread_set->tx_thread); |
632 | + wake_up(&conn->queues_wq); |
633 | } |
634 | |
635 | struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *conn) |
636 | @@ -562,7 +562,7 @@ void iscsit_add_cmd_to_response_queue( |
637 | atomic_inc(&cmd->response_queue_count); |
638 | spin_unlock_bh(&conn->response_queue_lock); |
639 | |
640 | - wake_up_process(conn->thread_set->tx_thread); |
641 | + wake_up(&conn->queues_wq); |
642 | } |
643 | |
644 | struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *conn) |
645 | @@ -616,6 +616,24 @@ static void iscsit_remove_cmd_from_response_queue( |
646 | } |
647 | } |
648 | |
649 | +bool iscsit_conn_all_queues_empty(struct iscsi_conn *conn) |
650 | +{ |
651 | + bool empty; |
652 | + |
653 | + spin_lock_bh(&conn->immed_queue_lock); |
654 | + empty = list_empty(&conn->immed_queue_list); |
655 | + spin_unlock_bh(&conn->immed_queue_lock); |
656 | + |
657 | + if (!empty) |
658 | + return empty; |
659 | + |
660 | + spin_lock_bh(&conn->response_queue_lock); |
661 | + empty = list_empty(&conn->response_queue_list); |
662 | + spin_unlock_bh(&conn->response_queue_lock); |
663 | + |
664 | + return empty; |
665 | +} |
666 | + |
667 | void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn) |
668 | { |
669 | struct iscsi_queue_req *qr, *qr_tmp; |
670 | diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h |
671 | index e1c729b..2ff9bbc 100644 |
672 | --- a/drivers/target/iscsi/iscsi_target_util.h |
673 | +++ b/drivers/target/iscsi/iscsi_target_util.h |
674 | @@ -25,6 +25,7 @@ extern struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_ |
675 | extern void iscsit_add_cmd_to_response_queue(struct iscsi_cmd *, struct iscsi_conn *, u8); |
676 | extern struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *); |
677 | extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_conn *); |
678 | +extern bool iscsit_conn_all_queues_empty(struct iscsi_conn *); |
679 | extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *); |
680 | extern void iscsit_release_cmd(struct iscsi_cmd *); |
681 | extern void iscsit_free_cmd(struct iscsi_cmd *); |
682 | diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c |
683 | index 06aca11..ac0b69f 100644 |
684 | --- a/drivers/target/target_core_configfs.c |
685 | +++ b/drivers/target/target_core_configfs.c |
686 | @@ -3214,7 +3214,8 @@ static int __init target_core_init_configfs(void) |
687 | if (ret < 0) |
688 | goto out; |
689 | |
690 | - if (core_dev_setup_virtual_lun0() < 0) |
691 | + ret = core_dev_setup_virtual_lun0(); |
692 | + if (ret < 0) |
693 | goto out; |
694 | |
695 | return 0; |
696 | diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c |
697 | index 9fc9a60..68d4c10 100644 |
698 | --- a/drivers/target/target_core_device.c |
699 | +++ b/drivers/target/target_core_device.c |
700 | @@ -850,20 +850,20 @@ int se_dev_check_shutdown(struct se_device *dev) |
701 | |
702 | static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size) |
703 | { |
704 | - u32 tmp, aligned_max_sectors; |
705 | + u32 aligned_max_sectors; |
706 | + u32 alignment; |
707 | /* |
708 | * Limit max_sectors to a PAGE_SIZE aligned value for modern |
709 | * transport_allocate_data_tasks() operation. |
710 | */ |
711 | - tmp = rounddown((max_sectors * block_size), PAGE_SIZE); |
712 | - aligned_max_sectors = (tmp / block_size); |
713 | - if (max_sectors != aligned_max_sectors) { |
714 | - printk(KERN_INFO "Rounding down aligned max_sectors from %u" |
715 | - " to %u\n", max_sectors, aligned_max_sectors); |
716 | - return aligned_max_sectors; |
717 | - } |
718 | + alignment = max(1ul, PAGE_SIZE / block_size); |
719 | + aligned_max_sectors = rounddown(max_sectors, alignment); |
720 | + |
721 | + if (max_sectors != aligned_max_sectors) |
722 | + pr_info("Rounding down aligned max_sectors from %u to %u\n", |
723 | + max_sectors, aligned_max_sectors); |
724 | |
725 | - return max_sectors; |
726 | + return aligned_max_sectors; |
727 | } |
728 | |
729 | void se_dev_set_default_attribs( |
730 | diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c |
731 | index 9229bd9..6fd434d 100644 |
732 | --- a/drivers/target/target_core_spc.c |
733 | +++ b/drivers/target/target_core_spc.c |
734 | @@ -605,6 +605,8 @@ static int spc_emulate_inquiry(struct se_cmd *cmd) |
735 | unsigned char buf[SE_INQUIRY_BUF]; |
736 | int p, ret; |
737 | |
738 | + memset(buf, 0, SE_INQUIRY_BUF); |
739 | + |
740 | if (dev == tpg->tpg_virt_lun0.lun_se_dev) |
741 | buf[0] = 0x3f; /* Not connected */ |
742 | else |
743 | diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c |
744 | index 1c59a3c..be75c43 100644 |
745 | --- a/drivers/target/target_core_tmr.c |
746 | +++ b/drivers/target/target_core_tmr.c |
747 | @@ -140,15 +140,15 @@ void core_tmr_abort_task( |
748 | printk("ABORT_TASK: Found referenced %s task_tag: %u\n", |
749 | se_cmd->se_tfo->get_fabric_name(), ref_tag); |
750 | |
751 | - spin_lock_irq(&se_cmd->t_state_lock); |
752 | + spin_lock(&se_cmd->t_state_lock); |
753 | if (se_cmd->transport_state & CMD_T_COMPLETE) { |
754 | printk("ABORT_TASK: ref_tag: %u already complete, skipping\n", ref_tag); |
755 | - spin_unlock_irq(&se_cmd->t_state_lock); |
756 | + spin_unlock(&se_cmd->t_state_lock); |
757 | spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); |
758 | goto out; |
759 | } |
760 | se_cmd->transport_state |= CMD_T_ABORTED; |
761 | - spin_unlock_irq(&se_cmd->t_state_lock); |
762 | + spin_unlock(&se_cmd->t_state_lock); |
763 | |
764 | list_del_init(&se_cmd->se_cmd_list); |
765 | kref_get(&se_cmd->cmd_kref); |
766 | diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c |
767 | index 7f12416..9a113b7 100644 |
768 | --- a/drivers/xen/gntdev.c |
769 | +++ b/drivers/xen/gntdev.c |
770 | @@ -105,6 +105,21 @@ static void gntdev_print_maps(struct gntdev_priv *priv, |
771 | #endif |
772 | } |
773 | |
774 | +static void gntdev_free_map(struct grant_map *map) |
775 | +{ |
776 | + if (map == NULL) |
777 | + return; |
778 | + |
779 | + if (map->pages) |
780 | + free_xenballooned_pages(map->count, map->pages); |
781 | + kfree(map->pages); |
782 | + kfree(map->grants); |
783 | + kfree(map->map_ops); |
784 | + kfree(map->unmap_ops); |
785 | + kfree(map->kmap_ops); |
786 | + kfree(map); |
787 | +} |
788 | + |
789 | static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) |
790 | { |
791 | struct grant_map *add; |
792 | @@ -142,12 +157,7 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) |
793 | return add; |
794 | |
795 | err: |
796 | - kfree(add->pages); |
797 | - kfree(add->grants); |
798 | - kfree(add->map_ops); |
799 | - kfree(add->unmap_ops); |
800 | - kfree(add->kmap_ops); |
801 | - kfree(add); |
802 | + gntdev_free_map(add); |
803 | return NULL; |
804 | } |
805 | |
806 | @@ -198,17 +208,9 @@ static void gntdev_put_map(struct grant_map *map) |
807 | evtchn_put(map->notify.event); |
808 | } |
809 | |
810 | - if (map->pages) { |
811 | - if (!use_ptemod) |
812 | - unmap_grant_pages(map, 0, map->count); |
813 | - |
814 | - free_xenballooned_pages(map->count, map->pages); |
815 | - } |
816 | - kfree(map->pages); |
817 | - kfree(map->grants); |
818 | - kfree(map->map_ops); |
819 | - kfree(map->unmap_ops); |
820 | - kfree(map); |
821 | + if (map->pages && !use_ptemod) |
822 | + unmap_grant_pages(map, 0, map->count); |
823 | + gntdev_free_map(map); |
824 | } |
825 | |
826 | /* ------------------------------------------------------------------ */ |
827 | diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c |
828 | index 8ff95a2..0967d0c 100644 |
829 | --- a/fs/gfs2/lops.c |
830 | +++ b/fs/gfs2/lops.c |
831 | @@ -393,12 +393,10 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) |
832 | struct gfs2_meta_header *mh; |
833 | struct gfs2_trans *tr; |
834 | |
835 | - lock_buffer(bd->bd_bh); |
836 | - gfs2_log_lock(sdp); |
837 | tr = current->journal_info; |
838 | tr->tr_touched = 1; |
839 | if (!list_empty(&bd->bd_list)) |
840 | - goto out; |
841 | + return; |
842 | set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); |
843 | set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); |
844 | mh = (struct gfs2_meta_header *)bd->bd_bh->b_data; |
845 | @@ -414,9 +412,6 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) |
846 | sdp->sd_log_num_buf++; |
847 | list_add(&bd->bd_list, &sdp->sd_log_le_buf); |
848 | tr->tr_num_buf_new++; |
849 | -out: |
850 | - gfs2_log_unlock(sdp); |
851 | - unlock_buffer(bd->bd_bh); |
852 | } |
853 | |
854 | static void gfs2_check_magic(struct buffer_head *bh) |
855 | @@ -777,12 +772,10 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) |
856 | struct address_space *mapping = bd->bd_bh->b_page->mapping; |
857 | struct gfs2_inode *ip = GFS2_I(mapping->host); |
858 | |
859 | - lock_buffer(bd->bd_bh); |
860 | - gfs2_log_lock(sdp); |
861 | if (tr) |
862 | tr->tr_touched = 1; |
863 | if (!list_empty(&bd->bd_list)) |
864 | - goto out; |
865 | + return; |
866 | set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); |
867 | set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); |
868 | if (gfs2_is_jdata(ip)) { |
869 | @@ -793,9 +786,6 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) |
870 | } else { |
871 | list_add_tail(&bd->bd_list, &sdp->sd_log_le_ordered); |
872 | } |
873 | -out: |
874 | - gfs2_log_unlock(sdp); |
875 | - unlock_buffer(bd->bd_bh); |
876 | } |
877 | |
878 | /** |
879 | diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c |
880 | index adbd278..4136270 100644 |
881 | --- a/fs/gfs2/trans.c |
882 | +++ b/fs/gfs2/trans.c |
883 | @@ -155,14 +155,22 @@ void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta) |
884 | struct gfs2_sbd *sdp = gl->gl_sbd; |
885 | struct gfs2_bufdata *bd; |
886 | |
887 | + lock_buffer(bh); |
888 | + gfs2_log_lock(sdp); |
889 | bd = bh->b_private; |
890 | if (bd) |
891 | gfs2_assert(sdp, bd->bd_gl == gl); |
892 | else { |
893 | + gfs2_log_unlock(sdp); |
894 | + unlock_buffer(bh); |
895 | gfs2_attach_bufdata(gl, bh, meta); |
896 | bd = bh->b_private; |
897 | + lock_buffer(bh); |
898 | + gfs2_log_lock(sdp); |
899 | } |
900 | lops_add(sdp, bd); |
901 | + gfs2_log_unlock(sdp); |
902 | + unlock_buffer(bh); |
903 | } |
904 | |
905 | void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) |
906 | diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c |
907 | index 31c26c4..ca4b11e 100644 |
908 | --- a/fs/nfs/dns_resolve.c |
909 | +++ b/fs/nfs/dns_resolve.c |
910 | @@ -217,7 +217,7 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen) |
911 | { |
912 | char buf1[NFS_DNS_HOSTNAME_MAXLEN+1]; |
913 | struct nfs_dns_ent key, *item; |
914 | - unsigned long ttl; |
915 | + unsigned int ttl; |
916 | ssize_t len; |
917 | int ret = -EINVAL; |
918 | |
919 | @@ -240,7 +240,8 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen) |
920 | key.namelen = len; |
921 | memset(&key.h, 0, sizeof(key.h)); |
922 | |
923 | - ttl = get_expiry(&buf); |
924 | + if (get_uint(&buf, &ttl) < 0) |
925 | + goto out; |
926 | if (ttl == 0) |
927 | goto out; |
928 | key.h.expiry_time = ttl + seconds_since_boot(); |
929 | diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h |
930 | index 31fdb03..e794dee 100644 |
931 | --- a/fs/nfs/internal.h |
932 | +++ b/fs/nfs/internal.h |
933 | @@ -353,8 +353,9 @@ extern void nfs_sb_active(struct super_block *sb); |
934 | extern void nfs_sb_deactive(struct super_block *sb); |
935 | |
936 | /* namespace.c */ |
937 | +#define NFS_PATH_CANONICAL 1 |
938 | extern char *nfs_path(char **p, struct dentry *dentry, |
939 | - char *buffer, ssize_t buflen); |
940 | + char *buffer, ssize_t buflen, unsigned flags); |
941 | extern struct vfsmount *nfs_d_automount(struct path *path); |
942 | struct vfsmount *nfs_submount(struct nfs_server *, struct dentry *, |
943 | struct nfs_fh *, struct nfs_fattr *); |
944 | @@ -491,7 +492,7 @@ static inline char *nfs_devname(struct dentry *dentry, |
945 | char *buffer, ssize_t buflen) |
946 | { |
947 | char *dummy; |
948 | - return nfs_path(&dummy, dentry, buffer, buflen); |
949 | + return nfs_path(&dummy, dentry, buffer, buflen, NFS_PATH_CANONICAL); |
950 | } |
951 | |
952 | /* |
953 | diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c |
954 | index 8e65c7f..015f71f 100644 |
955 | --- a/fs/nfs/mount_clnt.c |
956 | +++ b/fs/nfs/mount_clnt.c |
957 | @@ -181,7 +181,7 @@ int nfs_mount(struct nfs_mount_request *info) |
958 | else |
959 | msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC_MNT]; |
960 | |
961 | - status = rpc_call_sync(mnt_clnt, &msg, 0); |
962 | + status = rpc_call_sync(mnt_clnt, &msg, RPC_TASK_SOFT|RPC_TASK_TIMEOUT); |
963 | rpc_shutdown_client(mnt_clnt); |
964 | |
965 | if (status < 0) |
966 | diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c |
967 | index 6559253..dd057bc 100644 |
968 | --- a/fs/nfs/namespace.c |
969 | +++ b/fs/nfs/namespace.c |
970 | @@ -33,6 +33,7 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ; |
971 | * @dentry - pointer to dentry |
972 | * @buffer - result buffer |
973 | * @buflen - length of buffer |
974 | + * @flags - options (see below) |
975 | * |
976 | * Helper function for constructing the server pathname |
977 | * by arbitrary hashed dentry. |
978 | @@ -40,8 +41,14 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ; |
979 | * This is mainly for use in figuring out the path on the |
980 | * server side when automounting on top of an existing partition |
981 | * and in generating /proc/mounts and friends. |
982 | + * |
983 | + * Supported flags: |
984 | + * NFS_PATH_CANONICAL: ensure there is exactly one slash after |
985 | + * the original device (export) name |
986 | + * (if unset, the original name is returned verbatim) |
987 | */ |
988 | -char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen) |
989 | +char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen, |
990 | + unsigned flags) |
991 | { |
992 | char *end; |
993 | int namelen; |
994 | @@ -74,7 +81,7 @@ rename_retry: |
995 | rcu_read_unlock(); |
996 | goto rename_retry; |
997 | } |
998 | - if (*end != '/') { |
999 | + if ((flags & NFS_PATH_CANONICAL) && *end != '/') { |
1000 | if (--buflen < 0) { |
1001 | spin_unlock(&dentry->d_lock); |
1002 | rcu_read_unlock(); |
1003 | @@ -91,9 +98,11 @@ rename_retry: |
1004 | return end; |
1005 | } |
1006 | namelen = strlen(base); |
1007 | - /* Strip off excess slashes in base string */ |
1008 | - while (namelen > 0 && base[namelen - 1] == '/') |
1009 | - namelen--; |
1010 | + if (flags & NFS_PATH_CANONICAL) { |
1011 | + /* Strip off excess slashes in base string */ |
1012 | + while (namelen > 0 && base[namelen - 1] == '/') |
1013 | + namelen--; |
1014 | + } |
1015 | buflen -= namelen; |
1016 | if (buflen < 0) { |
1017 | spin_unlock(&dentry->d_lock); |
1018 | diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c |
1019 | index 017b4b0..c077b25 100644 |
1020 | --- a/fs/nfs/nfs4namespace.c |
1021 | +++ b/fs/nfs/nfs4namespace.c |
1022 | @@ -81,7 +81,8 @@ static char *nfs_path_component(const char *nfspath, const char *end) |
1023 | static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen) |
1024 | { |
1025 | char *limit; |
1026 | - char *path = nfs_path(&limit, dentry, buffer, buflen); |
1027 | + char *path = nfs_path(&limit, dentry, buffer, buflen, |
1028 | + NFS_PATH_CANONICAL); |
1029 | if (!IS_ERR(path)) { |
1030 | char *path_component = nfs_path_component(path, limit); |
1031 | if (path_component) |
1032 | diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c |
1033 | index d5a0cf1..7bff871 100644 |
1034 | --- a/fs/nfs/nfs4proc.c |
1035 | +++ b/fs/nfs/nfs4proc.c |
1036 | @@ -331,8 +331,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc |
1037 | dprintk("%s ERROR: %d Reset session\n", __func__, |
1038 | errorcode); |
1039 | nfs4_schedule_session_recovery(clp->cl_session, errorcode); |
1040 | - exception->retry = 1; |
1041 | - break; |
1042 | + goto wait_on_recovery; |
1043 | #endif /* defined(CONFIG_NFS_V4_1) */ |
1044 | case -NFS4ERR_FILE_OPEN: |
1045 | if (exception->timeout > HZ) { |
1046 | @@ -1499,9 +1498,11 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) |
1047 | data->timestamp = jiffies; |
1048 | if (nfs4_setup_sequence(data->o_arg.server, |
1049 | &data->o_arg.seq_args, |
1050 | - &data->o_res.seq_res, task)) |
1051 | - return; |
1052 | - rpc_call_start(task); |
1053 | + &data->o_res.seq_res, |
1054 | + task) != 0) |
1055 | + nfs_release_seqid(data->o_arg.seqid); |
1056 | + else |
1057 | + rpc_call_start(task); |
1058 | return; |
1059 | unlock_no_action: |
1060 | rcu_read_unlock(); |
1061 | @@ -2182,9 +2183,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) |
1062 | if (nfs4_setup_sequence(NFS_SERVER(calldata->inode), |
1063 | &calldata->arg.seq_args, |
1064 | &calldata->res.seq_res, |
1065 | - task)) |
1066 | - goto out; |
1067 | - rpc_call_start(task); |
1068 | + task) != 0) |
1069 | + nfs_release_seqid(calldata->arg.seqid); |
1070 | + else |
1071 | + rpc_call_start(task); |
1072 | out: |
1073 | dprintk("%s: done!\n", __func__); |
1074 | } |
1075 | @@ -4390,6 +4392,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) |
1076 | if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN) |
1077 | rpc_restart_call_prepare(task); |
1078 | } |
1079 | + nfs_release_seqid(calldata->arg.seqid); |
1080 | } |
1081 | |
1082 | static void nfs4_locku_prepare(struct rpc_task *task, void *data) |
1083 | @@ -4406,9 +4409,11 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) |
1084 | calldata->timestamp = jiffies; |
1085 | if (nfs4_setup_sequence(calldata->server, |
1086 | &calldata->arg.seq_args, |
1087 | - &calldata->res.seq_res, task)) |
1088 | - return; |
1089 | - rpc_call_start(task); |
1090 | + &calldata->res.seq_res, |
1091 | + task) != 0) |
1092 | + nfs_release_seqid(calldata->arg.seqid); |
1093 | + else |
1094 | + rpc_call_start(task); |
1095 | } |
1096 | |
1097 | static const struct rpc_call_ops nfs4_locku_ops = { |
1098 | @@ -4553,7 +4558,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) |
1099 | /* Do we need to do an open_to_lock_owner? */ |
1100 | if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { |
1101 | if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) |
1102 | - return; |
1103 | + goto out_release_lock_seqid; |
1104 | data->arg.open_stateid = &state->stateid; |
1105 | data->arg.new_lock_owner = 1; |
1106 | data->res.open_seqid = data->arg.open_seqid; |
1107 | @@ -4562,10 +4567,15 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) |
1108 | data->timestamp = jiffies; |
1109 | if (nfs4_setup_sequence(data->server, |
1110 | &data->arg.seq_args, |
1111 | - &data->res.seq_res, task)) |
1112 | + &data->res.seq_res, |
1113 | + task) == 0) { |
1114 | + rpc_call_start(task); |
1115 | return; |
1116 | - rpc_call_start(task); |
1117 | - dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status); |
1118 | + } |
1119 | + nfs_release_seqid(data->arg.open_seqid); |
1120 | +out_release_lock_seqid: |
1121 | + nfs_release_seqid(data->arg.lock_seqid); |
1122 | + dprintk("%s: done!, ret = %d\n", __func__, task->tk_status); |
1123 | } |
1124 | |
1125 | static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata) |
1126 | diff --git a/fs/nfs/super.c b/fs/nfs/super.c |
1127 | index b8eda70..d8d7396 100644 |
1128 | --- a/fs/nfs/super.c |
1129 | +++ b/fs/nfs/super.c |
1130 | @@ -765,7 +765,7 @@ int nfs_show_devname(struct seq_file *m, struct dentry *root) |
1131 | int err = 0; |
1132 | if (!page) |
1133 | return -ENOMEM; |
1134 | - devname = nfs_path(&dummy, root, page, PAGE_SIZE); |
1135 | + devname = nfs_path(&dummy, root, page, PAGE_SIZE, 0); |
1136 | if (IS_ERR(devname)) |
1137 | err = PTR_ERR(devname); |
1138 | else |
1139 | diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c |
1140 | index a8d0ed9..becf4a9 100644 |
1141 | --- a/fs/xfs/xfs_buf_item.c |
1142 | +++ b/fs/xfs/xfs_buf_item.c |
1143 | @@ -526,7 +526,25 @@ xfs_buf_item_unpin( |
1144 | } |
1145 | xfs_buf_relse(bp); |
1146 | } else if (freed && remove) { |
1147 | + /* |
1148 | + * There are currently two references to the buffer - the active |
1149 | + * LRU reference and the buf log item. What we are about to do |
1150 | + * here - simulate a failed IO completion - requires 3 |
1151 | + * references. |
1152 | + * |
1153 | + * The LRU reference is removed by the xfs_buf_stale() call. The |
1154 | + * buf item reference is removed by the xfs_buf_iodone() |
1155 | + * callback that is run by xfs_buf_do_callbacks() during ioend |
1156 | + * processing (via the bp->b_iodone callback), and then finally |
1157 | + * the ioend processing will drop the IO reference if the buffer |
1158 | + * is marked XBF_ASYNC. |
1159 | + * |
1160 | + * Hence we need to take an additional reference here so that IO |
1161 | + * completion processing doesn't free the buffer prematurely. |
1162 | + */ |
1163 | xfs_buf_lock(bp); |
1164 | + xfs_buf_hold(bp); |
1165 | + bp->b_flags |= XBF_ASYNC; |
1166 | xfs_buf_ioerror(bp, EIO); |
1167 | XFS_BUF_UNDONE(bp); |
1168 | xfs_buf_stale(bp); |
1169 | diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c |
1170 | index 5da3ace..d308749 100644 |
1171 | --- a/fs/xfs/xfs_log_recover.c |
1172 | +++ b/fs/xfs/xfs_log_recover.c |
1173 | @@ -3541,7 +3541,7 @@ xlog_do_recovery_pass( |
1174 | * - order is important. |
1175 | */ |
1176 | error = xlog_bread_offset(log, 0, |
1177 | - bblks - split_bblks, hbp, |
1178 | + bblks - split_bblks, dbp, |
1179 | offset + BBTOB(split_bblks)); |
1180 | if (error) |
1181 | goto bread_err2; |
1182 | diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h |
1183 | index f10553c..fb5204b 100644 |
1184 | --- a/include/net/cfg80211.h |
1185 | +++ b/include/net/cfg80211.h |
1186 | @@ -2633,6 +2633,15 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb); |
1187 | unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc); |
1188 | |
1189 | /** |
1190 | + * ieee80211_get_mesh_hdrlen - get mesh extension header length |
1191 | + * @meshhdr: the mesh extension header, only the flags field |
1192 | + * (first byte) will be accessed |
1193 | + * Returns the length of the extension header, which is always at |
1194 | + * least 6 bytes and at most 18 if address 5 and 6 are present. |
1195 | + */ |
1196 | +unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); |
1197 | + |
1198 | +/** |
1199 | * DOC: Data path helpers |
1200 | * |
1201 | * In addition to generic utilities, cfg80211 also offers |
1202 | diff --git a/include/sound/core.h b/include/sound/core.h |
1203 | index bc05668..93896ad 100644 |
1204 | --- a/include/sound/core.h |
1205 | +++ b/include/sound/core.h |
1206 | @@ -132,6 +132,7 @@ struct snd_card { |
1207 | int shutdown; /* this card is going down */ |
1208 | int free_on_last_close; /* free in context of file_release */ |
1209 | wait_queue_head_t shutdown_sleep; |
1210 | + atomic_t refcount; /* refcount for disconnection */ |
1211 | struct device *dev; /* device assigned to this card */ |
1212 | struct device *card_dev; /* cardX object for sysfs */ |
1213 | |
1214 | @@ -189,6 +190,7 @@ struct snd_minor { |
1215 | const struct file_operations *f_ops; /* file operations */ |
1216 | void *private_data; /* private data for f_ops->open */ |
1217 | struct device *dev; /* device for sysfs */ |
1218 | + struct snd_card *card_ptr; /* assigned card instance */ |
1219 | }; |
1220 | |
1221 | /* return a device pointer linked to each sound device as a parent */ |
1222 | @@ -295,6 +297,7 @@ int snd_card_info_done(void); |
1223 | int snd_component_add(struct snd_card *card, const char *component); |
1224 | int snd_card_file_add(struct snd_card *card, struct file *file); |
1225 | int snd_card_file_remove(struct snd_card *card, struct file *file); |
1226 | +void snd_card_unref(struct snd_card *card); |
1227 | |
1228 | #define snd_card_set_dev(card, devptr) ((card)->dev = (devptr)) |
1229 | |
1230 | diff --git a/include/trace/events/xen.h b/include/trace/events/xen.h |
1231 | index 15ba03b..d06b6da 100644 |
1232 | --- a/include/trace/events/xen.h |
1233 | +++ b/include/trace/events/xen.h |
1234 | @@ -377,6 +377,14 @@ DECLARE_EVENT_CLASS(xen_mmu_pgd, |
1235 | DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin); |
1236 | DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin); |
1237 | |
1238 | +TRACE_EVENT(xen_mmu_flush_tlb_all, |
1239 | + TP_PROTO(int x), |
1240 | + TP_ARGS(x), |
1241 | + TP_STRUCT__entry(__array(char, x, 0)), |
1242 | + TP_fast_assign((void)x), |
1243 | + TP_printk("%s", "") |
1244 | + ); |
1245 | + |
1246 | TRACE_EVENT(xen_mmu_flush_tlb, |
1247 | TP_PROTO(int x), |
1248 | TP_ARGS(x), |
1249 | diff --git a/kernel/futex.c b/kernel/futex.c |
1250 | index 3717e7b..20ef219 100644 |
1251 | --- a/kernel/futex.c |
1252 | +++ b/kernel/futex.c |
1253 | @@ -716,7 +716,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, |
1254 | struct futex_pi_state **ps, |
1255 | struct task_struct *task, int set_waiters) |
1256 | { |
1257 | - int lock_taken, ret, ownerdied = 0; |
1258 | + int lock_taken, ret, force_take = 0; |
1259 | u32 uval, newval, curval, vpid = task_pid_vnr(task); |
1260 | |
1261 | retry: |
1262 | @@ -755,17 +755,15 @@ retry: |
1263 | newval = curval | FUTEX_WAITERS; |
1264 | |
1265 | /* |
1266 | - * There are two cases, where a futex might have no owner (the |
1267 | - * owner TID is 0): OWNER_DIED. We take over the futex in this |
1268 | - * case. We also do an unconditional take over, when the owner |
1269 | - * of the futex died. |
1270 | - * |
1271 | - * This is safe as we are protected by the hash bucket lock ! |
1272 | + * Should we force take the futex? See below. |
1273 | */ |
1274 | - if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) { |
1275 | - /* Keep the OWNER_DIED bit */ |
1276 | + if (unlikely(force_take)) { |
1277 | + /* |
1278 | + * Keep the OWNER_DIED and the WAITERS bit and set the |
1279 | + * new TID value. |
1280 | + */ |
1281 | newval = (curval & ~FUTEX_TID_MASK) | vpid; |
1282 | - ownerdied = 0; |
1283 | + force_take = 0; |
1284 | lock_taken = 1; |
1285 | } |
1286 | |
1287 | @@ -775,7 +773,7 @@ retry: |
1288 | goto retry; |
1289 | |
1290 | /* |
1291 | - * We took the lock due to owner died take over. |
1292 | + * We took the lock due to forced take over. |
1293 | */ |
1294 | if (unlikely(lock_taken)) |
1295 | return 1; |
1296 | @@ -790,20 +788,25 @@ retry: |
1297 | switch (ret) { |
1298 | case -ESRCH: |
1299 | /* |
1300 | - * No owner found for this futex. Check if the |
1301 | - * OWNER_DIED bit is set to figure out whether |
1302 | - * this is a robust futex or not. |
1303 | + * We failed to find an owner for this |
1304 | + * futex. So we have no pi_state to block |
1305 | + * on. This can happen in two cases: |
1306 | + * |
1307 | + * 1) The owner died |
1308 | + * 2) A stale FUTEX_WAITERS bit |
1309 | + * |
1310 | + * Re-read the futex value. |
1311 | */ |
1312 | if (get_futex_value_locked(&curval, uaddr)) |
1313 | return -EFAULT; |
1314 | |
1315 | /* |
1316 | - * We simply start over in case of a robust |
1317 | - * futex. The code above will take the futex |
1318 | - * and return happy. |
1319 | + * If the owner died or we have a stale |
1320 | + * WAITERS bit the owner TID in the user space |
1321 | + * futex is 0. |
1322 | */ |
1323 | - if (curval & FUTEX_OWNER_DIED) { |
1324 | - ownerdied = 1; |
1325 | + if (!(curval & FUTEX_TID_MASK)) { |
1326 | + force_take = 1; |
1327 | goto retry; |
1328 | } |
1329 | default: |
1330 | diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c |
1331 | index 6705d35..e7b5777 100644 |
1332 | --- a/net/batman-adv/bridge_loop_avoidance.c |
1333 | +++ b/net/batman-adv/bridge_loop_avoidance.c |
1334 | @@ -1205,8 +1205,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv) |
1335 | /** |
1336 | * batadv_bla_check_bcast_duplist |
1337 | * @bat_priv: the bat priv with all the soft interface information |
1338 | - * @bcast_packet: originator mac address |
1339 | - * @hdr_size: maximum length of the frame |
1340 | + * @bcast_packet: encapsulated broadcast frame plus batman header |
1341 | + * @bcast_packet_len: length of encapsulated broadcast frame plus batman header |
1342 | * |
1343 | * check if it is on our broadcast list. Another gateway might |
1344 | * have sent the same packet because it is connected to the same backbone, |
1345 | @@ -1219,14 +1219,14 @@ int batadv_bla_init(struct batadv_priv *bat_priv) |
1346 | */ |
1347 | int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, |
1348 | struct batadv_bcast_packet *bcast_packet, |
1349 | - int hdr_size) |
1350 | + int bcast_packet_len) |
1351 | { |
1352 | int i, length, curr; |
1353 | uint8_t *content; |
1354 | uint16_t crc; |
1355 | struct batadv_bcast_duplist_entry *entry; |
1356 | |
1357 | - length = hdr_size - sizeof(*bcast_packet); |
1358 | + length = bcast_packet_len - sizeof(*bcast_packet); |
1359 | content = (uint8_t *)bcast_packet; |
1360 | content += sizeof(*bcast_packet); |
1361 | |
1362 | diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c |
1363 | index bc2b88b..f861b7c 100644 |
1364 | --- a/net/batman-adv/routing.c |
1365 | +++ b/net/batman-adv/routing.c |
1366 | @@ -1136,8 +1136,14 @@ int batadv_recv_bcast_packet(struct sk_buff *skb, |
1367 | |
1368 | spin_unlock_bh(&orig_node->bcast_seqno_lock); |
1369 | |
1370 | + /* keep skb linear for crc calculation */ |
1371 | + if (skb_linearize(skb) < 0) |
1372 | + goto out; |
1373 | + |
1374 | + bcast_packet = (struct batadv_bcast_packet *)skb->data; |
1375 | + |
1376 | /* check whether this has been sent by another originator before */ |
1377 | - if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, hdr_size)) |
1378 | + if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, skb->len)) |
1379 | goto out; |
1380 | |
1381 | /* rebroadcast packet */ |
1382 | diff --git a/net/core/dev.c b/net/core/dev.c |
1383 | index 2fb9f59..aed87a4 100644 |
1384 | --- a/net/core/dev.c |
1385 | +++ b/net/core/dev.c |
1386 | @@ -1644,7 +1644,7 @@ static inline int deliver_skb(struct sk_buff *skb, |
1387 | |
1388 | static inline bool skb_loop_sk(struct packet_type *ptype, struct sk_buff *skb) |
1389 | { |
1390 | - if (ptype->af_packet_priv == NULL) |
1391 | + if (!ptype->af_packet_priv || !skb->sk) |
1392 | return false; |
1393 | |
1394 | if (ptype->id_match) |
1395 | diff --git a/net/core/skbuff.c b/net/core/skbuff.c |
1396 | index ef172af..9708777 100644 |
1397 | --- a/net/core/skbuff.c |
1398 | +++ b/net/core/skbuff.c |
1399 | @@ -3384,10 +3384,12 @@ EXPORT_SYMBOL(__skb_warn_lro_forwarding); |
1400 | |
1401 | void kfree_skb_partial(struct sk_buff *skb, bool head_stolen) |
1402 | { |
1403 | - if (head_stolen) |
1404 | + if (head_stolen) { |
1405 | + skb_release_head_state(skb); |
1406 | kmem_cache_free(skbuff_head_cache, skb); |
1407 | - else |
1408 | + } else { |
1409 | __kfree_skb(skb); |
1410 | + } |
1411 | } |
1412 | EXPORT_SYMBOL(kfree_skb_partial); |
1413 | |
1414 | diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c |
1415 | index 570e61f..6405a44 100644 |
1416 | --- a/net/ipv4/inet_diag.c |
1417 | +++ b/net/ipv4/inet_diag.c |
1418 | @@ -883,13 +883,16 @@ static int __inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, |
1419 | struct inet_diag_req_v2 *r, struct nlattr *bc) |
1420 | { |
1421 | const struct inet_diag_handler *handler; |
1422 | + int err = 0; |
1423 | |
1424 | handler = inet_diag_lock_handler(r->sdiag_protocol); |
1425 | if (!IS_ERR(handler)) |
1426 | handler->dump(skb, cb, r, bc); |
1427 | + else |
1428 | + err = PTR_ERR(handler); |
1429 | inet_diag_unlock_handler(handler); |
1430 | |
1431 | - return skb->len; |
1432 | + return err ? : skb->len; |
1433 | } |
1434 | |
1435 | static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) |
1436 | diff --git a/net/ipv4/route.c b/net/ipv4/route.c |
1437 | index 2a1383c..c017cb1 100644 |
1438 | --- a/net/ipv4/route.c |
1439 | +++ b/net/ipv4/route.c |
1440 | @@ -1166,8 +1166,12 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, |
1441 | spin_lock_bh(&fnhe_lock); |
1442 | |
1443 | if (daddr == fnhe->fnhe_daddr) { |
1444 | - struct rtable *orig; |
1445 | - |
1446 | + struct rtable *orig = rcu_dereference(fnhe->fnhe_rth); |
1447 | + if (orig && rt_is_expired(orig)) { |
1448 | + fnhe->fnhe_gw = 0; |
1449 | + fnhe->fnhe_pmtu = 0; |
1450 | + fnhe->fnhe_expires = 0; |
1451 | + } |
1452 | if (fnhe->fnhe_pmtu) { |
1453 | unsigned long expires = fnhe->fnhe_expires; |
1454 | unsigned long diff = expires - jiffies; |
1455 | @@ -1184,7 +1188,6 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, |
1456 | } else if (!rt->rt_gateway) |
1457 | rt->rt_gateway = daddr; |
1458 | |
1459 | - orig = rcu_dereference(fnhe->fnhe_rth); |
1460 | rcu_assign_pointer(fnhe->fnhe_rth, rt); |
1461 | if (orig) |
1462 | rt_free(orig); |
1463 | diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c |
1464 | index 5f64193..49dd993 100644 |
1465 | --- a/net/ipv4/tcp.c |
1466 | +++ b/net/ipv4/tcp.c |
1467 | @@ -548,14 +548,12 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) |
1468 | !tp->urg_data || |
1469 | before(tp->urg_seq, tp->copied_seq) || |
1470 | !before(tp->urg_seq, tp->rcv_nxt)) { |
1471 | - struct sk_buff *skb; |
1472 | |
1473 | answ = tp->rcv_nxt - tp->copied_seq; |
1474 | |
1475 | - /* Subtract 1, if FIN is in queue. */ |
1476 | - skb = skb_peek_tail(&sk->sk_receive_queue); |
1477 | - if (answ && skb) |
1478 | - answ -= tcp_hdr(skb)->fin; |
1479 | + /* Subtract 1, if FIN was received */ |
1480 | + if (answ && sock_flag(sk, SOCK_DONE)) |
1481 | + answ--; |
1482 | } else |
1483 | answ = tp->urg_seq - tp->copied_seq; |
1484 | release_sock(sk); |
1485 | diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c |
1486 | index 813b43a..834857f 100644 |
1487 | --- a/net/ipv4/tcp_illinois.c |
1488 | +++ b/net/ipv4/tcp_illinois.c |
1489 | @@ -313,11 +313,13 @@ static void tcp_illinois_info(struct sock *sk, u32 ext, |
1490 | .tcpv_rttcnt = ca->cnt_rtt, |
1491 | .tcpv_minrtt = ca->base_rtt, |
1492 | }; |
1493 | - u64 t = ca->sum_rtt; |
1494 | |
1495 | - do_div(t, ca->cnt_rtt); |
1496 | - info.tcpv_rtt = t; |
1497 | + if (info.tcpv_rttcnt > 0) { |
1498 | + u64 t = ca->sum_rtt; |
1499 | |
1500 | + do_div(t, info.tcpv_rttcnt); |
1501 | + info.tcpv_rtt = t; |
1502 | + } |
1503 | nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info); |
1504 | } |
1505 | } |
1506 | diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c |
1507 | index d377f48..c92c4da 100644 |
1508 | --- a/net/ipv4/tcp_input.c |
1509 | +++ b/net/ipv4/tcp_input.c |
1510 | @@ -4556,6 +4556,9 @@ int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size) |
1511 | struct tcphdr *th; |
1512 | bool fragstolen; |
1513 | |
1514 | + if (size == 0) |
1515 | + return 0; |
1516 | + |
1517 | skb = alloc_skb(size + sizeof(*th), sk->sk_allocation); |
1518 | if (!skb) |
1519 | goto err; |
1520 | diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c |
1521 | index ff36194..2edce30 100644 |
1522 | --- a/net/ipv6/ndisc.c |
1523 | +++ b/net/ipv6/ndisc.c |
1524 | @@ -535,7 +535,7 @@ static void ndisc_send_unsol_na(struct net_device *dev) |
1525 | { |
1526 | struct inet6_dev *idev; |
1527 | struct inet6_ifaddr *ifa; |
1528 | - struct in6_addr mcaddr; |
1529 | + struct in6_addr mcaddr = IN6ADDR_LINKLOCAL_ALLNODES_INIT; |
1530 | |
1531 | idev = in6_dev_get(dev); |
1532 | if (!idev) |
1533 | @@ -543,7 +543,6 @@ static void ndisc_send_unsol_na(struct net_device *dev) |
1534 | |
1535 | read_lock_bh(&idev->lock); |
1536 | list_for_each_entry(ifa, &idev->addr_list, if_list) { |
1537 | - addrconf_addr_solict_mult(&ifa->addr, &mcaddr); |
1538 | ndisc_send_na(dev, NULL, &mcaddr, &ifa->addr, |
1539 | /*router=*/ !!idev->cnf.forwarding, |
1540 | /*solicited=*/ false, /*override=*/ true, |
1541 | diff --git a/net/ipv6/route.c b/net/ipv6/route.c |
1542 | index 46eff42..070a3ce 100644 |
1543 | --- a/net/ipv6/route.c |
1544 | +++ b/net/ipv6/route.c |
1545 | @@ -219,7 +219,7 @@ static struct dst_ops ip6_dst_blackhole_ops = { |
1546 | }; |
1547 | |
1548 | static const u32 ip6_template_metrics[RTAX_MAX] = { |
1549 | - [RTAX_HOPLIMIT - 1] = 255, |
1550 | + [RTAX_HOPLIMIT - 1] = 0, |
1551 | }; |
1552 | |
1553 | static struct rt6_info ip6_null_entry_template = { |
1554 | @@ -1241,7 +1241,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, |
1555 | rt->rt6i_dst.addr = fl6->daddr; |
1556 | rt->rt6i_dst.plen = 128; |
1557 | rt->rt6i_idev = idev; |
1558 | - dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); |
1559 | + dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0); |
1560 | |
1561 | spin_lock_bh(&icmp6_dst_lock); |
1562 | rt->dst.next = icmp6_dst_gc_list; |
1563 | diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c |
1564 | index 3bfb34a..69bf48d 100644 |
1565 | --- a/net/l2tp/l2tp_eth.c |
1566 | +++ b/net/l2tp/l2tp_eth.c |
1567 | @@ -290,6 +290,7 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p |
1568 | |
1569 | out_del_dev: |
1570 | free_netdev(dev); |
1571 | + spriv->dev = NULL; |
1572 | out_del_session: |
1573 | l2tp_session_delete(session); |
1574 | out: |
1575 | diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c |
1576 | index 5746d62..327aa07 100644 |
1577 | --- a/net/mac80211/ibss.c |
1578 | +++ b/net/mac80211/ibss.c |
1579 | @@ -1074,7 +1074,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, |
1580 | sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; |
1581 | sdata->u.ibss.ibss_join_req = jiffies; |
1582 | |
1583 | - memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); |
1584 | + memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len); |
1585 | sdata->u.ibss.ssid_len = params->ssid_len; |
1586 | |
1587 | mutex_unlock(&sdata->u.ibss.mtx); |
1588 | diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c |
1589 | index 0cb4ede..37fe5ce 100644 |
1590 | --- a/net/mac80211/rx.c |
1591 | +++ b/net/mac80211/rx.c |
1592 | @@ -491,6 +491,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) |
1593 | |
1594 | if (ieee80211_is_action(hdr->frame_control)) { |
1595 | u8 category; |
1596 | + |
1597 | + /* make sure category field is present */ |
1598 | + if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE) |
1599 | + return RX_DROP_MONITOR; |
1600 | + |
1601 | mgmt = (struct ieee80211_mgmt *)hdr; |
1602 | category = mgmt->u.action.category; |
1603 | if (category != WLAN_CATEGORY_MESH_ACTION && |
1604 | @@ -843,14 +848,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) |
1605 | */ |
1606 | if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION && |
1607 | ieee80211_is_data_present(hdr->frame_control)) { |
1608 | - u16 ethertype; |
1609 | - u8 *payload; |
1610 | - |
1611 | - payload = rx->skb->data + |
1612 | - ieee80211_hdrlen(hdr->frame_control); |
1613 | - ethertype = (payload[6] << 8) | payload[7]; |
1614 | - if (cpu_to_be16(ethertype) == |
1615 | - rx->sdata->control_port_protocol) |
1616 | + unsigned int hdrlen; |
1617 | + __be16 ethertype; |
1618 | + |
1619 | + hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1620 | + |
1621 | + if (rx->skb->len < hdrlen + 8) |
1622 | + return RX_DROP_MONITOR; |
1623 | + |
1624 | + skb_copy_bits(rx->skb, hdrlen + 6, ðertype, 2); |
1625 | + if (ethertype == rx->sdata->control_port_protocol) |
1626 | return RX_CONTINUE; |
1627 | } |
1628 | |
1629 | @@ -1422,11 +1429,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) |
1630 | |
1631 | hdr = (struct ieee80211_hdr *)rx->skb->data; |
1632 | fc = hdr->frame_control; |
1633 | + |
1634 | + if (ieee80211_is_ctl(fc)) |
1635 | + return RX_CONTINUE; |
1636 | + |
1637 | sc = le16_to_cpu(hdr->seq_ctrl); |
1638 | frag = sc & IEEE80211_SCTL_FRAG; |
1639 | |
1640 | if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || |
1641 | - (rx->skb)->len < 24 || |
1642 | is_multicast_ether_addr(hdr->addr1))) { |
1643 | /* not fragmented */ |
1644 | goto out; |
1645 | @@ -1849,6 +1859,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) |
1646 | |
1647 | hdr = (struct ieee80211_hdr *) skb->data; |
1648 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1649 | + |
1650 | + /* make sure fixed part of mesh header is there, also checks skb len */ |
1651 | + if (!pskb_may_pull(rx->skb, hdrlen + 6)) |
1652 | + return RX_DROP_MONITOR; |
1653 | + |
1654 | + mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); |
1655 | + |
1656 | + /* make sure full mesh header is there, also checks skb len */ |
1657 | + if (!pskb_may_pull(rx->skb, |
1658 | + hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr))) |
1659 | + return RX_DROP_MONITOR; |
1660 | + |
1661 | + /* reload pointers */ |
1662 | + hdr = (struct ieee80211_hdr *) skb->data; |
1663 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); |
1664 | |
1665 | /* frame is in RMC, don't forward */ |
1666 | @@ -1857,7 +1881,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) |
1667 | mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata)) |
1668 | return RX_DROP_MONITOR; |
1669 | |
1670 | - if (!ieee80211_is_data(hdr->frame_control)) |
1671 | + if (!ieee80211_is_data(hdr->frame_control) || |
1672 | + !(status->rx_flags & IEEE80211_RX_RA_MATCH)) |
1673 | return RX_CONTINUE; |
1674 | |
1675 | if (!mesh_hdr->ttl) |
1676 | @@ -1871,9 +1896,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) |
1677 | if (is_multicast_ether_addr(hdr->addr1)) { |
1678 | mpp_addr = hdr->addr3; |
1679 | proxied_addr = mesh_hdr->eaddr1; |
1680 | - } else { |
1681 | + } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) { |
1682 | + /* has_a4 already checked in ieee80211_rx_mesh_check */ |
1683 | mpp_addr = hdr->addr4; |
1684 | proxied_addr = mesh_hdr->eaddr2; |
1685 | + } else { |
1686 | + return RX_DROP_MONITOR; |
1687 | } |
1688 | |
1689 | rcu_read_lock(); |
1690 | @@ -1901,9 +1929,6 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) |
1691 | } |
1692 | skb_set_queue_mapping(skb, q); |
1693 | |
1694 | - if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) |
1695 | - goto out; |
1696 | - |
1697 | if (!--mesh_hdr->ttl) { |
1698 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); |
1699 | return RX_DROP_MONITOR; |
1700 | @@ -2313,6 +2338,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) |
1701 | } |
1702 | break; |
1703 | case WLAN_CATEGORY_SELF_PROTECTED: |
1704 | + if (len < (IEEE80211_MIN_ACTION_SIZE + |
1705 | + sizeof(mgmt->u.action.u.self_prot.action_code))) |
1706 | + break; |
1707 | + |
1708 | switch (mgmt->u.action.u.self_prot.action_code) { |
1709 | case WLAN_SP_MESH_PEERING_OPEN: |
1710 | case WLAN_SP_MESH_PEERING_CLOSE: |
1711 | @@ -2331,6 +2360,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) |
1712 | } |
1713 | break; |
1714 | case WLAN_CATEGORY_MESH_ACTION: |
1715 | + if (len < (IEEE80211_MIN_ACTION_SIZE + |
1716 | + sizeof(mgmt->u.action.u.mesh_action.action_code))) |
1717 | + break; |
1718 | + |
1719 | if (!ieee80211_vif_is_mesh(&sdata->vif)) |
1720 | break; |
1721 | if (mesh_action_is_path_sel(mgmt) && |
1722 | @@ -2865,10 +2898,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, |
1723 | if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) |
1724 | local->dot11ReceivedFragmentCount++; |
1725 | |
1726 | - if (ieee80211_is_mgmt(fc)) |
1727 | - err = skb_linearize(skb); |
1728 | - else |
1729 | + if (ieee80211_is_mgmt(fc)) { |
1730 | + /* drop frame if too short for header */ |
1731 | + if (skb->len < ieee80211_hdrlen(fc)) |
1732 | + err = -ENOBUFS; |
1733 | + else |
1734 | + err = skb_linearize(skb); |
1735 | + } else { |
1736 | err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); |
1737 | + } |
1738 | |
1739 | if (err) { |
1740 | dev_kfree_skb(skb); |
1741 | diff --git a/net/mac80211/util.c b/net/mac80211/util.c |
1742 | index c9b52f7..1cfe6d5 100644 |
1743 | --- a/net/mac80211/util.c |
1744 | +++ b/net/mac80211/util.c |
1745 | @@ -637,13 +637,41 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, |
1746 | break; |
1747 | } |
1748 | |
1749 | - if (id != WLAN_EID_VENDOR_SPECIFIC && |
1750 | - id != WLAN_EID_QUIET && |
1751 | - test_bit(id, seen_elems)) { |
1752 | - elems->parse_error = true; |
1753 | - left -= elen; |
1754 | - pos += elen; |
1755 | - continue; |
1756 | + switch (id) { |
1757 | + case WLAN_EID_SSID: |
1758 | + case WLAN_EID_SUPP_RATES: |
1759 | + case WLAN_EID_FH_PARAMS: |
1760 | + case WLAN_EID_DS_PARAMS: |
1761 | + case WLAN_EID_CF_PARAMS: |
1762 | + case WLAN_EID_TIM: |
1763 | + case WLAN_EID_IBSS_PARAMS: |
1764 | + case WLAN_EID_CHALLENGE: |
1765 | + case WLAN_EID_RSN: |
1766 | + case WLAN_EID_ERP_INFO: |
1767 | + case WLAN_EID_EXT_SUPP_RATES: |
1768 | + case WLAN_EID_HT_CAPABILITY: |
1769 | + case WLAN_EID_HT_OPERATION: |
1770 | + case WLAN_EID_VHT_CAPABILITY: |
1771 | + case WLAN_EID_VHT_OPERATION: |
1772 | + case WLAN_EID_MESH_ID: |
1773 | + case WLAN_EID_MESH_CONFIG: |
1774 | + case WLAN_EID_PEER_MGMT: |
1775 | + case WLAN_EID_PREQ: |
1776 | + case WLAN_EID_PREP: |
1777 | + case WLAN_EID_PERR: |
1778 | + case WLAN_EID_RANN: |
1779 | + case WLAN_EID_CHANNEL_SWITCH: |
1780 | + case WLAN_EID_EXT_CHANSWITCH_ANN: |
1781 | + case WLAN_EID_COUNTRY: |
1782 | + case WLAN_EID_PWR_CONSTRAINT: |
1783 | + case WLAN_EID_TIMEOUT_INTERVAL: |
1784 | + if (test_bit(id, seen_elems)) { |
1785 | + elems->parse_error = true; |
1786 | + left -= elen; |
1787 | + pos += elen; |
1788 | + continue; |
1789 | + } |
1790 | + break; |
1791 | } |
1792 | |
1793 | if (calc_crc && id < 64 && (filter & (1ULL << id))) |
1794 | diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c |
1795 | index 9172179..0426b67 100644 |
1796 | --- a/net/netlink/af_netlink.c |
1797 | +++ b/net/netlink/af_netlink.c |
1798 | @@ -138,6 +138,8 @@ static int netlink_dump(struct sock *sk); |
1799 | static DEFINE_RWLOCK(nl_table_lock); |
1800 | static atomic_t nl_table_users = ATOMIC_INIT(0); |
1801 | |
1802 | +#define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock)); |
1803 | + |
1804 | static ATOMIC_NOTIFIER_HEAD(netlink_chain); |
1805 | |
1806 | static inline u32 netlink_group_mask(u32 group) |
1807 | @@ -345,6 +347,11 @@ netlink_update_listeners(struct sock *sk) |
1808 | struct hlist_node *node; |
1809 | unsigned long mask; |
1810 | unsigned int i; |
1811 | + struct listeners *listeners; |
1812 | + |
1813 | + listeners = nl_deref_protected(tbl->listeners); |
1814 | + if (!listeners) |
1815 | + return; |
1816 | |
1817 | for (i = 0; i < NLGRPLONGS(tbl->groups); i++) { |
1818 | mask = 0; |
1819 | @@ -352,7 +359,7 @@ netlink_update_listeners(struct sock *sk) |
1820 | if (i < NLGRPLONGS(nlk_sk(sk)->ngroups)) |
1821 | mask |= nlk_sk(sk)->groups[i]; |
1822 | } |
1823 | - tbl->listeners->masks[i] = mask; |
1824 | + listeners->masks[i] = mask; |
1825 | } |
1826 | /* this function is only called with the netlink table "grabbed", which |
1827 | * makes sure updates are visible before bind or setsockopt return. */ |
1828 | @@ -536,7 +543,11 @@ static int netlink_release(struct socket *sock) |
1829 | if (netlink_is_kernel(sk)) { |
1830 | BUG_ON(nl_table[sk->sk_protocol].registered == 0); |
1831 | if (--nl_table[sk->sk_protocol].registered == 0) { |
1832 | - kfree(nl_table[sk->sk_protocol].listeners); |
1833 | + struct listeners *old; |
1834 | + |
1835 | + old = nl_deref_protected(nl_table[sk->sk_protocol].listeners); |
1836 | + RCU_INIT_POINTER(nl_table[sk->sk_protocol].listeners, NULL); |
1837 | + kfree_rcu(old, rcu); |
1838 | nl_table[sk->sk_protocol].module = NULL; |
1839 | nl_table[sk->sk_protocol].registered = 0; |
1840 | } |
1841 | @@ -978,7 +989,7 @@ int netlink_has_listeners(struct sock *sk, unsigned int group) |
1842 | rcu_read_lock(); |
1843 | listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners); |
1844 | |
1845 | - if (group - 1 < nl_table[sk->sk_protocol].groups) |
1846 | + if (listeners && group - 1 < nl_table[sk->sk_protocol].groups) |
1847 | res = test_bit(group - 1, listeners->masks); |
1848 | |
1849 | rcu_read_unlock(); |
1850 | @@ -1620,7 +1631,7 @@ int __netlink_change_ngroups(struct sock *sk, unsigned int groups) |
1851 | new = kzalloc(sizeof(*new) + NLGRPSZ(groups), GFP_ATOMIC); |
1852 | if (!new) |
1853 | return -ENOMEM; |
1854 | - old = rcu_dereference_protected(tbl->listeners, 1); |
1855 | + old = nl_deref_protected(tbl->listeners); |
1856 | memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups)); |
1857 | rcu_assign_pointer(tbl->listeners, new); |
1858 | |
1859 | diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c |
1860 | index fe99628..b1c5be3 100644 |
1861 | --- a/net/sctp/sm_sideeffect.c |
1862 | +++ b/net/sctp/sm_sideeffect.c |
1863 | @@ -1634,8 +1634,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, |
1864 | asoc->outqueue.outstanding_bytes; |
1865 | sackh.num_gap_ack_blocks = 0; |
1866 | sackh.num_dup_tsns = 0; |
1867 | + chunk->subh.sack_hdr = &sackh; |
1868 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, |
1869 | - SCTP_SACKH(&sackh)); |
1870 | + SCTP_CHUNK(chunk)); |
1871 | break; |
1872 | |
1873 | case SCTP_CMD_DISCARD_PACKET: |
1874 | diff --git a/net/wireless/core.c b/net/wireless/core.c |
1875 | index dcd64d5..5797032 100644 |
1876 | --- a/net/wireless/core.c |
1877 | +++ b/net/wireless/core.c |
1878 | @@ -506,8 +506,7 @@ int wiphy_register(struct wiphy *wiphy) |
1879 | for (i = 0; i < sband->n_channels; i++) { |
1880 | sband->channels[i].orig_flags = |
1881 | sband->channels[i].flags; |
1882 | - sband->channels[i].orig_mag = |
1883 | - sband->channels[i].max_antenna_gain; |
1884 | + sband->channels[i].orig_mag = INT_MAX; |
1885 | sband->channels[i].orig_mpwr = |
1886 | sband->channels[i].max_power; |
1887 | sband->channels[i].band = band; |
1888 | diff --git a/net/wireless/util.c b/net/wireless/util.c |
1889 | index 994e2f0..09afde7 100644 |
1890 | --- a/net/wireless/util.c |
1891 | +++ b/net/wireless/util.c |
1892 | @@ -309,23 +309,21 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb) |
1893 | } |
1894 | EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); |
1895 | |
1896 | -static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) |
1897 | +unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) |
1898 | { |
1899 | int ae = meshhdr->flags & MESH_FLAGS_AE; |
1900 | - /* 7.1.3.5a.2 */ |
1901 | + /* 802.11-2012, 8.2.4.7.3 */ |
1902 | switch (ae) { |
1903 | + default: |
1904 | case 0: |
1905 | return 6; |
1906 | case MESH_FLAGS_AE_A4: |
1907 | return 12; |
1908 | case MESH_FLAGS_AE_A5_A6: |
1909 | return 18; |
1910 | - case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6): |
1911 | - return 24; |
1912 | - default: |
1913 | - return 6; |
1914 | } |
1915 | } |
1916 | +EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen); |
1917 | |
1918 | int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, |
1919 | enum nl80211_iftype iftype) |
1920 | @@ -373,6 +371,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, |
1921 | /* make sure meshdr->flags is on the linear part */ |
1922 | if (!pskb_may_pull(skb, hdrlen + 1)) |
1923 | return -1; |
1924 | + if (meshdr->flags & MESH_FLAGS_AE_A4) |
1925 | + return -1; |
1926 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { |
1927 | skb_copy_bits(skb, hdrlen + |
1928 | offsetof(struct ieee80211s_hdr, eaddr1), |
1929 | @@ -397,6 +397,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, |
1930 | /* make sure meshdr->flags is on the linear part */ |
1931 | if (!pskb_may_pull(skb, hdrlen + 1)) |
1932 | return -1; |
1933 | + if (meshdr->flags & MESH_FLAGS_AE_A5_A6) |
1934 | + return -1; |
1935 | if (meshdr->flags & MESH_FLAGS_AE_A4) |
1936 | skb_copy_bits(skb, hdrlen + |
1937 | offsetof(struct ieee80211s_hdr, eaddr1), |
1938 | diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c |
1939 | index eb60cb8..d5103f7 100644 |
1940 | --- a/sound/core/compress_offload.c |
1941 | +++ b/sound/core/compress_offload.c |
1942 | @@ -100,12 +100,15 @@ static int snd_compr_open(struct inode *inode, struct file *f) |
1943 | |
1944 | if (dirn != compr->direction) { |
1945 | pr_err("this device doesn't support this direction\n"); |
1946 | + snd_card_unref(compr->card); |
1947 | return -EINVAL; |
1948 | } |
1949 | |
1950 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
1951 | - if (!data) |
1952 | + if (!data) { |
1953 | + snd_card_unref(compr->card); |
1954 | return -ENOMEM; |
1955 | + } |
1956 | data->stream.ops = compr->ops; |
1957 | data->stream.direction = dirn; |
1958 | data->stream.private_data = compr->private_data; |
1959 | @@ -113,6 +116,7 @@ static int snd_compr_open(struct inode *inode, struct file *f) |
1960 | runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); |
1961 | if (!runtime) { |
1962 | kfree(data); |
1963 | + snd_card_unref(compr->card); |
1964 | return -ENOMEM; |
1965 | } |
1966 | runtime->state = SNDRV_PCM_STATE_OPEN; |
1967 | @@ -126,7 +130,8 @@ static int snd_compr_open(struct inode *inode, struct file *f) |
1968 | kfree(runtime); |
1969 | kfree(data); |
1970 | } |
1971 | - return ret; |
1972 | + snd_card_unref(compr->card); |
1973 | + return 0; |
1974 | } |
1975 | |
1976 | static int snd_compr_free(struct inode *inode, struct file *f) |
1977 | diff --git a/sound/core/control.c b/sound/core/control.c |
1978 | index 2487a6b..daa4fc8 100644 |
1979 | --- a/sound/core/control.c |
1980 | +++ b/sound/core/control.c |
1981 | @@ -86,6 +86,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file) |
1982 | write_lock_irqsave(&card->ctl_files_rwlock, flags); |
1983 | list_add_tail(&ctl->list, &card->ctl_files); |
1984 | write_unlock_irqrestore(&card->ctl_files_rwlock, flags); |
1985 | + snd_card_unref(card); |
1986 | return 0; |
1987 | |
1988 | __error: |
1989 | @@ -93,6 +94,8 @@ static int snd_ctl_open(struct inode *inode, struct file *file) |
1990 | __error2: |
1991 | snd_card_file_remove(card, file); |
1992 | __error1: |
1993 | + if (card) |
1994 | + snd_card_unref(card); |
1995 | return err; |
1996 | } |
1997 | |
1998 | @@ -1433,6 +1436,8 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer, |
1999 | spin_unlock_irq(&ctl->read_lock); |
2000 | schedule(); |
2001 | remove_wait_queue(&ctl->change_sleep, &wait); |
2002 | + if (ctl->card->shutdown) |
2003 | + return -ENODEV; |
2004 | if (signal_pending(current)) |
2005 | return -ERESTARTSYS; |
2006 | spin_lock_irq(&ctl->read_lock); |
2007 | diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c |
2008 | index 75ea16f..3f7f662 100644 |
2009 | --- a/sound/core/hwdep.c |
2010 | +++ b/sound/core/hwdep.c |
2011 | @@ -100,8 +100,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) |
2012 | if (hw == NULL) |
2013 | return -ENODEV; |
2014 | |
2015 | - if (!try_module_get(hw->card->module)) |
2016 | + if (!try_module_get(hw->card->module)) { |
2017 | + snd_card_unref(hw->card); |
2018 | return -EFAULT; |
2019 | + } |
2020 | |
2021 | init_waitqueue_entry(&wait, current); |
2022 | add_wait_queue(&hw->open_wait, &wait); |
2023 | @@ -129,6 +131,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) |
2024 | mutex_unlock(&hw->open_mutex); |
2025 | schedule(); |
2026 | mutex_lock(&hw->open_mutex); |
2027 | + if (hw->card->shutdown) { |
2028 | + err = -ENODEV; |
2029 | + break; |
2030 | + } |
2031 | if (signal_pending(current)) { |
2032 | err = -ERESTARTSYS; |
2033 | break; |
2034 | @@ -148,6 +154,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) |
2035 | mutex_unlock(&hw->open_mutex); |
2036 | if (err < 0) |
2037 | module_put(hw->card->module); |
2038 | + snd_card_unref(hw->card); |
2039 | return err; |
2040 | } |
2041 | |
2042 | @@ -459,12 +466,15 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device) |
2043 | mutex_unlock(®ister_mutex); |
2044 | return -EINVAL; |
2045 | } |
2046 | + mutex_lock(&hwdep->open_mutex); |
2047 | + wake_up(&hwdep->open_wait); |
2048 | #ifdef CONFIG_SND_OSSEMUL |
2049 | if (hwdep->ossreg) |
2050 | snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); |
2051 | #endif |
2052 | snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); |
2053 | list_del_init(&hwdep->list); |
2054 | + mutex_unlock(&hwdep->open_mutex); |
2055 | mutex_unlock(®ister_mutex); |
2056 | return 0; |
2057 | } |
2058 | diff --git a/sound/core/init.c b/sound/core/init.c |
2059 | index d8ec849..7b012d1 100644 |
2060 | --- a/sound/core/init.c |
2061 | +++ b/sound/core/init.c |
2062 | @@ -213,6 +213,7 @@ int snd_card_create(int idx, const char *xid, |
2063 | spin_lock_init(&card->files_lock); |
2064 | INIT_LIST_HEAD(&card->files_list); |
2065 | init_waitqueue_head(&card->shutdown_sleep); |
2066 | + atomic_set(&card->refcount, 0); |
2067 | #ifdef CONFIG_PM |
2068 | mutex_init(&card->power_lock); |
2069 | init_waitqueue_head(&card->power_sleep); |
2070 | @@ -446,21 +447,36 @@ static int snd_card_do_free(struct snd_card *card) |
2071 | return 0; |
2072 | } |
2073 | |
2074 | +/** |
2075 | + * snd_card_unref - release the reference counter |
2076 | + * @card: the card instance |
2077 | + * |
2078 | + * Decrements the reference counter. When it reaches to zero, wake up |
2079 | + * the sleeper and call the destructor if needed. |
2080 | + */ |
2081 | +void snd_card_unref(struct snd_card *card) |
2082 | +{ |
2083 | + if (atomic_dec_and_test(&card->refcount)) { |
2084 | + wake_up(&card->shutdown_sleep); |
2085 | + if (card->free_on_last_close) |
2086 | + snd_card_do_free(card); |
2087 | + } |
2088 | +} |
2089 | +EXPORT_SYMBOL(snd_card_unref); |
2090 | + |
2091 | int snd_card_free_when_closed(struct snd_card *card) |
2092 | { |
2093 | - int free_now = 0; |
2094 | - int ret = snd_card_disconnect(card); |
2095 | - if (ret) |
2096 | - return ret; |
2097 | + int ret; |
2098 | |
2099 | - spin_lock(&card->files_lock); |
2100 | - if (list_empty(&card->files_list)) |
2101 | - free_now = 1; |
2102 | - else |
2103 | - card->free_on_last_close = 1; |
2104 | - spin_unlock(&card->files_lock); |
2105 | + atomic_inc(&card->refcount); |
2106 | + ret = snd_card_disconnect(card); |
2107 | + if (ret) { |
2108 | + atomic_dec(&card->refcount); |
2109 | + return ret; |
2110 | + } |
2111 | |
2112 | - if (free_now) |
2113 | + card->free_on_last_close = 1; |
2114 | + if (atomic_dec_and_test(&card->refcount)) |
2115 | snd_card_do_free(card); |
2116 | return 0; |
2117 | } |
2118 | @@ -474,7 +490,7 @@ int snd_card_free(struct snd_card *card) |
2119 | return ret; |
2120 | |
2121 | /* wait, until all devices are ready for the free operation */ |
2122 | - wait_event(card->shutdown_sleep, list_empty(&card->files_list)); |
2123 | + wait_event(card->shutdown_sleep, !atomic_read(&card->refcount)); |
2124 | snd_card_do_free(card); |
2125 | return 0; |
2126 | } |
2127 | @@ -886,6 +902,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file) |
2128 | return -ENODEV; |
2129 | } |
2130 | list_add(&mfile->list, &card->files_list); |
2131 | + atomic_inc(&card->refcount); |
2132 | spin_unlock(&card->files_lock); |
2133 | return 0; |
2134 | } |
2135 | @@ -908,7 +925,6 @@ EXPORT_SYMBOL(snd_card_file_add); |
2136 | int snd_card_file_remove(struct snd_card *card, struct file *file) |
2137 | { |
2138 | struct snd_monitor_file *mfile, *found = NULL; |
2139 | - int last_close = 0; |
2140 | |
2141 | spin_lock(&card->files_lock); |
2142 | list_for_each_entry(mfile, &card->files_list, list) { |
2143 | @@ -923,19 +939,13 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) |
2144 | break; |
2145 | } |
2146 | } |
2147 | - if (list_empty(&card->files_list)) |
2148 | - last_close = 1; |
2149 | spin_unlock(&card->files_lock); |
2150 | - if (last_close) { |
2151 | - wake_up(&card->shutdown_sleep); |
2152 | - if (card->free_on_last_close) |
2153 | - snd_card_do_free(card); |
2154 | - } |
2155 | if (!found) { |
2156 | snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file); |
2157 | return -ENOENT; |
2158 | } |
2159 | kfree(found); |
2160 | + snd_card_unref(card); |
2161 | return 0; |
2162 | } |
2163 | |
2164 | diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c |
2165 | index 18297f7..c353768 100644 |
2166 | --- a/sound/core/oss/mixer_oss.c |
2167 | +++ b/sound/core/oss/mixer_oss.c |
2168 | @@ -52,14 +52,19 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file) |
2169 | SNDRV_OSS_DEVICE_TYPE_MIXER); |
2170 | if (card == NULL) |
2171 | return -ENODEV; |
2172 | - if (card->mixer_oss == NULL) |
2173 | + if (card->mixer_oss == NULL) { |
2174 | + snd_card_unref(card); |
2175 | return -ENODEV; |
2176 | + } |
2177 | err = snd_card_file_add(card, file); |
2178 | - if (err < 0) |
2179 | + if (err < 0) { |
2180 | + snd_card_unref(card); |
2181 | return err; |
2182 | + } |
2183 | fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL); |
2184 | if (fmixer == NULL) { |
2185 | snd_card_file_remove(card, file); |
2186 | + snd_card_unref(card); |
2187 | return -ENOMEM; |
2188 | } |
2189 | fmixer->card = card; |
2190 | @@ -68,8 +73,10 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file) |
2191 | if (!try_module_get(card->module)) { |
2192 | kfree(fmixer); |
2193 | snd_card_file_remove(card, file); |
2194 | + snd_card_unref(card); |
2195 | return -EFAULT; |
2196 | } |
2197 | + snd_card_unref(card); |
2198 | return 0; |
2199 | } |
2200 | |
2201 | diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c |
2202 | index 08fde00..4c1cc51 100644 |
2203 | --- a/sound/core/oss/pcm_oss.c |
2204 | +++ b/sound/core/oss/pcm_oss.c |
2205 | @@ -2441,6 +2441,10 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) |
2206 | mutex_unlock(&pcm->open_mutex); |
2207 | schedule(); |
2208 | mutex_lock(&pcm->open_mutex); |
2209 | + if (pcm->card->shutdown) { |
2210 | + err = -ENODEV; |
2211 | + break; |
2212 | + } |
2213 | if (signal_pending(current)) { |
2214 | err = -ERESTARTSYS; |
2215 | break; |
2216 | @@ -2450,6 +2454,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) |
2217 | mutex_unlock(&pcm->open_mutex); |
2218 | if (err < 0) |
2219 | goto __error; |
2220 | + snd_card_unref(pcm->card); |
2221 | return err; |
2222 | |
2223 | __error: |
2224 | @@ -2457,6 +2462,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) |
2225 | __error2: |
2226 | snd_card_file_remove(pcm->card, file); |
2227 | __error1: |
2228 | + if (pcm) |
2229 | + snd_card_unref(pcm->card); |
2230 | return err; |
2231 | } |
2232 | |
2233 | diff --git a/sound/core/pcm.c b/sound/core/pcm.c |
2234 | index 1a3070b..e30e1be 100644 |
2235 | --- a/sound/core/pcm.c |
2236 | +++ b/sound/core/pcm.c |
2237 | @@ -1086,11 +1086,19 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) |
2238 | if (list_empty(&pcm->list)) |
2239 | goto unlock; |
2240 | |
2241 | + mutex_lock(&pcm->open_mutex); |
2242 | + wake_up(&pcm->open_wait); |
2243 | list_del_init(&pcm->list); |
2244 | for (cidx = 0; cidx < 2; cidx++) |
2245 | - for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) |
2246 | - if (substream->runtime) |
2247 | + for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { |
2248 | + snd_pcm_stream_lock_irq(substream); |
2249 | + if (substream->runtime) { |
2250 | substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; |
2251 | + wake_up(&substream->runtime->sleep); |
2252 | + wake_up(&substream->runtime->tsleep); |
2253 | + } |
2254 | + snd_pcm_stream_unlock_irq(substream); |
2255 | + } |
2256 | list_for_each_entry(notify, &snd_pcm_notify_list, list) { |
2257 | notify->n_disconnect(pcm); |
2258 | } |
2259 | @@ -1106,6 +1114,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) |
2260 | } |
2261 | snd_unregister_device(devtype, pcm->card, pcm->device); |
2262 | } |
2263 | + mutex_unlock(&pcm->open_mutex); |
2264 | unlock: |
2265 | mutex_unlock(®ister_mutex); |
2266 | return 0; |
2267 | diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c |
2268 | index 53b5ada..bf3bf43 100644 |
2269 | --- a/sound/core/pcm_native.c |
2270 | +++ b/sound/core/pcm_native.c |
2271 | @@ -369,6 +369,14 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime) |
2272 | return usecs; |
2273 | } |
2274 | |
2275 | +static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state) |
2276 | +{ |
2277 | + snd_pcm_stream_lock_irq(substream); |
2278 | + if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED) |
2279 | + substream->runtime->status->state = state; |
2280 | + snd_pcm_stream_unlock_irq(substream); |
2281 | +} |
2282 | + |
2283 | static int snd_pcm_hw_params(struct snd_pcm_substream *substream, |
2284 | struct snd_pcm_hw_params *params) |
2285 | { |
2286 | @@ -452,7 +460,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, |
2287 | runtime->boundary *= 2; |
2288 | |
2289 | snd_pcm_timer_resolution_change(substream); |
2290 | - runtime->status->state = SNDRV_PCM_STATE_SETUP; |
2291 | + snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP); |
2292 | |
2293 | if (pm_qos_request_active(&substream->latency_pm_qos_req)) |
2294 | pm_qos_remove_request(&substream->latency_pm_qos_req); |
2295 | @@ -464,7 +472,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, |
2296 | /* hardware might be unusable from this time, |
2297 | so we force application to retry to set |
2298 | the correct hardware parameter settings */ |
2299 | - runtime->status->state = SNDRV_PCM_STATE_OPEN; |
2300 | + snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); |
2301 | if (substream->ops->hw_free != NULL) |
2302 | substream->ops->hw_free(substream); |
2303 | return err; |
2304 | @@ -512,7 +520,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream) |
2305 | return -EBADFD; |
2306 | if (substream->ops->hw_free) |
2307 | result = substream->ops->hw_free(substream); |
2308 | - runtime->status->state = SNDRV_PCM_STATE_OPEN; |
2309 | + snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); |
2310 | pm_qos_remove_request(&substream->latency_pm_qos_req); |
2311 | return result; |
2312 | } |
2313 | @@ -1320,7 +1328,7 @@ static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state) |
2314 | { |
2315 | struct snd_pcm_runtime *runtime = substream->runtime; |
2316 | runtime->control->appl_ptr = runtime->status->hw_ptr; |
2317 | - runtime->status->state = SNDRV_PCM_STATE_PREPARED; |
2318 | + snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED); |
2319 | } |
2320 | |
2321 | static struct action_ops snd_pcm_action_prepare = { |
2322 | @@ -1510,6 +1518,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, |
2323 | down_read(&snd_pcm_link_rwsem); |
2324 | snd_pcm_stream_lock_irq(substream); |
2325 | remove_wait_queue(&to_check->sleep, &wait); |
2326 | + if (card->shutdown) { |
2327 | + result = -ENODEV; |
2328 | + break; |
2329 | + } |
2330 | if (tout == 0) { |
2331 | if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) |
2332 | result = -ESTRPIPE; |
2333 | @@ -1633,6 +1645,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) |
2334 | write_unlock_irq(&snd_pcm_link_rwlock); |
2335 | up_write(&snd_pcm_link_rwsem); |
2336 | _nolock: |
2337 | + snd_card_unref(substream1->pcm->card); |
2338 | fput(file); |
2339 | if (res < 0) |
2340 | kfree(group); |
2341 | @@ -2107,7 +2120,10 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file) |
2342 | return err; |
2343 | pcm = snd_lookup_minor_data(iminor(inode), |
2344 | SNDRV_DEVICE_TYPE_PCM_PLAYBACK); |
2345 | - return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); |
2346 | + err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); |
2347 | + if (pcm) |
2348 | + snd_card_unref(pcm->card); |
2349 | + return err; |
2350 | } |
2351 | |
2352 | static int snd_pcm_capture_open(struct inode *inode, struct file *file) |
2353 | @@ -2118,7 +2134,10 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file) |
2354 | return err; |
2355 | pcm = snd_lookup_minor_data(iminor(inode), |
2356 | SNDRV_DEVICE_TYPE_PCM_CAPTURE); |
2357 | - return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); |
2358 | + err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); |
2359 | + if (pcm) |
2360 | + snd_card_unref(pcm->card); |
2361 | + return err; |
2362 | } |
2363 | |
2364 | static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) |
2365 | @@ -2155,6 +2174,10 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) |
2366 | mutex_unlock(&pcm->open_mutex); |
2367 | schedule(); |
2368 | mutex_lock(&pcm->open_mutex); |
2369 | + if (pcm->card->shutdown) { |
2370 | + err = -ENODEV; |
2371 | + break; |
2372 | + } |
2373 | if (signal_pending(current)) { |
2374 | err = -ERESTARTSYS; |
2375 | break; |
2376 | diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c |
2377 | index ebf6e49..1bb95ae 100644 |
2378 | --- a/sound/core/rawmidi.c |
2379 | +++ b/sound/core/rawmidi.c |
2380 | @@ -379,8 +379,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) |
2381 | if (rmidi == NULL) |
2382 | return -ENODEV; |
2383 | |
2384 | - if (!try_module_get(rmidi->card->module)) |
2385 | + if (!try_module_get(rmidi->card->module)) { |
2386 | + snd_card_unref(rmidi->card); |
2387 | return -ENXIO; |
2388 | + } |
2389 | |
2390 | mutex_lock(&rmidi->open_mutex); |
2391 | card = rmidi->card; |
2392 | @@ -422,6 +424,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) |
2393 | mutex_unlock(&rmidi->open_mutex); |
2394 | schedule(); |
2395 | mutex_lock(&rmidi->open_mutex); |
2396 | + if (rmidi->card->shutdown) { |
2397 | + err = -ENODEV; |
2398 | + break; |
2399 | + } |
2400 | if (signal_pending(current)) { |
2401 | err = -ERESTARTSYS; |
2402 | break; |
2403 | @@ -440,6 +446,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) |
2404 | #endif |
2405 | file->private_data = rawmidi_file; |
2406 | mutex_unlock(&rmidi->open_mutex); |
2407 | + snd_card_unref(rmidi->card); |
2408 | return 0; |
2409 | |
2410 | __error: |
2411 | @@ -447,6 +454,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) |
2412 | __error_card: |
2413 | mutex_unlock(&rmidi->open_mutex); |
2414 | module_put(rmidi->card->module); |
2415 | + snd_card_unref(rmidi->card); |
2416 | return err; |
2417 | } |
2418 | |
2419 | @@ -991,6 +999,8 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun |
2420 | spin_unlock_irq(&runtime->lock); |
2421 | schedule(); |
2422 | remove_wait_queue(&runtime->sleep, &wait); |
2423 | + if (rfile->rmidi->card->shutdown) |
2424 | + return -ENODEV; |
2425 | if (signal_pending(current)) |
2426 | return result > 0 ? result : -ERESTARTSYS; |
2427 | if (!runtime->avail) |
2428 | @@ -1234,6 +1244,8 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, |
2429 | spin_unlock_irq(&runtime->lock); |
2430 | timeout = schedule_timeout(30 * HZ); |
2431 | remove_wait_queue(&runtime->sleep, &wait); |
2432 | + if (rfile->rmidi->card->shutdown) |
2433 | + return -ENODEV; |
2434 | if (signal_pending(current)) |
2435 | return result > 0 ? result : -ERESTARTSYS; |
2436 | if (!runtime->avail && !timeout) |
2437 | @@ -1609,9 +1621,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device) |
2438 | static int snd_rawmidi_dev_disconnect(struct snd_device *device) |
2439 | { |
2440 | struct snd_rawmidi *rmidi = device->device_data; |
2441 | + int dir; |
2442 | |
2443 | mutex_lock(®ister_mutex); |
2444 | + mutex_lock(&rmidi->open_mutex); |
2445 | + wake_up(&rmidi->open_wait); |
2446 | list_del_init(&rmidi->list); |
2447 | + for (dir = 0; dir < 2; dir++) { |
2448 | + struct snd_rawmidi_substream *s; |
2449 | + list_for_each_entry(s, &rmidi->streams[dir].substreams, list) { |
2450 | + if (s->runtime) |
2451 | + wake_up(&s->runtime->sleep); |
2452 | + } |
2453 | + } |
2454 | + |
2455 | #ifdef CONFIG_SND_OSSEMUL |
2456 | if (rmidi->ossreg) { |
2457 | if ((int)rmidi->device == midi_map[rmidi->card->number]) { |
2458 | @@ -1626,6 +1649,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device) |
2459 | } |
2460 | #endif /* CONFIG_SND_OSSEMUL */ |
2461 | snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); |
2462 | + mutex_unlock(&rmidi->open_mutex); |
2463 | mutex_unlock(®ister_mutex); |
2464 | return 0; |
2465 | } |
2466 | diff --git a/sound/core/sound.c b/sound/core/sound.c |
2467 | index 28f3559..3700d96 100644 |
2468 | --- a/sound/core/sound.c |
2469 | +++ b/sound/core/sound.c |
2470 | @@ -99,6 +99,10 @@ static void snd_request_other(int minor) |
2471 | * |
2472 | * Checks that a minor device with the specified type is registered, and returns |
2473 | * its user data pointer. |
2474 | + * |
2475 | + * This function increments the reference counter of the card instance |
2476 | + * if an associated instance with the given minor number and type is found. |
2477 | + * The caller must call snd_card_unref() appropriately later. |
2478 | */ |
2479 | void *snd_lookup_minor_data(unsigned int minor, int type) |
2480 | { |
2481 | @@ -109,9 +113,11 @@ void *snd_lookup_minor_data(unsigned int minor, int type) |
2482 | return NULL; |
2483 | mutex_lock(&sound_mutex); |
2484 | mreg = snd_minors[minor]; |
2485 | - if (mreg && mreg->type == type) |
2486 | + if (mreg && mreg->type == type) { |
2487 | private_data = mreg->private_data; |
2488 | - else |
2489 | + if (private_data && mreg->card_ptr) |
2490 | + atomic_inc(&mreg->card_ptr->refcount); |
2491 | + } else |
2492 | private_data = NULL; |
2493 | mutex_unlock(&sound_mutex); |
2494 | return private_data; |
2495 | @@ -276,6 +282,7 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev, |
2496 | preg->device = dev; |
2497 | preg->f_ops = f_ops; |
2498 | preg->private_data = private_data; |
2499 | + preg->card_ptr = card; |
2500 | mutex_lock(&sound_mutex); |
2501 | #ifdef CONFIG_SND_DYNAMIC_MINORS |
2502 | minor = snd_find_free_minor(type); |
2503 | diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c |
2504 | index e952833..726a49a 100644 |
2505 | --- a/sound/core/sound_oss.c |
2506 | +++ b/sound/core/sound_oss.c |
2507 | @@ -40,6 +40,9 @@ |
2508 | static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS]; |
2509 | static DEFINE_MUTEX(sound_oss_mutex); |
2510 | |
2511 | +/* NOTE: This function increments the refcount of the associated card like |
2512 | + * snd_lookup_minor_data(); the caller must call snd_card_unref() appropriately |
2513 | + */ |
2514 | void *snd_lookup_oss_minor_data(unsigned int minor, int type) |
2515 | { |
2516 | struct snd_minor *mreg; |
2517 | @@ -49,9 +52,11 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type) |
2518 | return NULL; |
2519 | mutex_lock(&sound_oss_mutex); |
2520 | mreg = snd_oss_minors[minor]; |
2521 | - if (mreg && mreg->type == type) |
2522 | + if (mreg && mreg->type == type) { |
2523 | private_data = mreg->private_data; |
2524 | - else |
2525 | + if (private_data && mreg->card_ptr) |
2526 | + atomic_inc(&mreg->card_ptr->refcount); |
2527 | + } else |
2528 | private_data = NULL; |
2529 | mutex_unlock(&sound_oss_mutex); |
2530 | return private_data; |
2531 | @@ -123,6 +128,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, |
2532 | preg->device = dev; |
2533 | preg->f_ops = f_ops; |
2534 | preg->private_data = private_data; |
2535 | + preg->card_ptr = card; |
2536 | mutex_lock(&sound_oss_mutex); |
2537 | snd_oss_minors[minor] = preg; |
2538 | minor_unit = SNDRV_MINOR_OSS_DEVICE(minor); |
2539 | diff --git a/sound/usb/card.c b/sound/usb/card.c |
2540 | index 4a469f0..b3f5ad4 100644 |
2541 | --- a/sound/usb/card.c |
2542 | +++ b/sound/usb/card.c |
2543 | @@ -339,7 +339,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, |
2544 | } |
2545 | |
2546 | mutex_init(&chip->mutex); |
2547 | - mutex_init(&chip->shutdown_mutex); |
2548 | + init_rwsem(&chip->shutdown_rwsem); |
2549 | chip->index = idx; |
2550 | chip->dev = dev; |
2551 | chip->card = card; |
2552 | @@ -559,9 +559,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, |
2553 | return; |
2554 | |
2555 | card = chip->card; |
2556 | - mutex_lock(®ister_mutex); |
2557 | - mutex_lock(&chip->shutdown_mutex); |
2558 | + down_write(&chip->shutdown_rwsem); |
2559 | chip->shutdown = 1; |
2560 | + up_write(&chip->shutdown_rwsem); |
2561 | + |
2562 | + mutex_lock(®ister_mutex); |
2563 | chip->num_interfaces--; |
2564 | if (chip->num_interfaces <= 0) { |
2565 | snd_card_disconnect(card); |
2566 | @@ -582,11 +584,9 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, |
2567 | snd_usb_mixer_disconnect(p); |
2568 | } |
2569 | usb_chip[chip->index] = NULL; |
2570 | - mutex_unlock(&chip->shutdown_mutex); |
2571 | mutex_unlock(®ister_mutex); |
2572 | snd_card_free_when_closed(card); |
2573 | } else { |
2574 | - mutex_unlock(&chip->shutdown_mutex); |
2575 | mutex_unlock(®ister_mutex); |
2576 | } |
2577 | } |
2578 | @@ -618,16 +618,20 @@ int snd_usb_autoresume(struct snd_usb_audio *chip) |
2579 | { |
2580 | int err = -ENODEV; |
2581 | |
2582 | + down_read(&chip->shutdown_rwsem); |
2583 | if (!chip->shutdown && !chip->probing) |
2584 | err = usb_autopm_get_interface(chip->pm_intf); |
2585 | + up_read(&chip->shutdown_rwsem); |
2586 | |
2587 | return err; |
2588 | } |
2589 | |
2590 | void snd_usb_autosuspend(struct snd_usb_audio *chip) |
2591 | { |
2592 | + down_read(&chip->shutdown_rwsem); |
2593 | if (!chip->shutdown && !chip->probing) |
2594 | usb_autopm_put_interface(chip->pm_intf); |
2595 | + up_read(&chip->shutdown_rwsem); |
2596 | } |
2597 | |
2598 | static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) |
2599 | diff --git a/sound/usb/card.h b/sound/usb/card.h |
2600 | index d9d2b5a..6e262c5 100644 |
2601 | --- a/sound/usb/card.h |
2602 | +++ b/sound/usb/card.h |
2603 | @@ -125,6 +125,7 @@ struct snd_usb_substream { |
2604 | struct snd_usb_endpoint *data_endpoint; |
2605 | struct snd_usb_endpoint *sync_endpoint; |
2606 | unsigned long flags; |
2607 | + unsigned int speed; /* USB_SPEED_XXX */ |
2608 | |
2609 | u64 formats; /* format bitmasks (all or'ed) */ |
2610 | unsigned int num_formats; /* number of supported audio formats (list) */ |
2611 | diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c |
2612 | index fe56c9d..298070e 100644 |
2613 | --- a/sound/usb/mixer.c |
2614 | +++ b/sound/usb/mixer.c |
2615 | @@ -287,25 +287,32 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v |
2616 | unsigned char buf[2]; |
2617 | int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; |
2618 | int timeout = 10; |
2619 | - int err; |
2620 | + int idx = 0, err; |
2621 | |
2622 | err = snd_usb_autoresume(cval->mixer->chip); |
2623 | if (err < 0) |
2624 | return -EIO; |
2625 | + down_read(&chip->shutdown_rwsem); |
2626 | while (timeout-- > 0) { |
2627 | + if (chip->shutdown) |
2628 | + break; |
2629 | + idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); |
2630 | if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, |
2631 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
2632 | - validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), |
2633 | - buf, val_len) >= val_len) { |
2634 | + validx, idx, buf, val_len) >= val_len) { |
2635 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); |
2636 | - snd_usb_autosuspend(cval->mixer->chip); |
2637 | - return 0; |
2638 | + err = 0; |
2639 | + goto out; |
2640 | } |
2641 | } |
2642 | - snd_usb_autosuspend(cval->mixer->chip); |
2643 | snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", |
2644 | - request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); |
2645 | - return -EINVAL; |
2646 | + request, validx, idx, cval->val_type); |
2647 | + err = -EINVAL; |
2648 | + |
2649 | + out: |
2650 | + up_read(&chip->shutdown_rwsem); |
2651 | + snd_usb_autosuspend(cval->mixer->chip); |
2652 | + return err; |
2653 | } |
2654 | |
2655 | static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) |
2656 | @@ -313,7 +320,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v |
2657 | struct snd_usb_audio *chip = cval->mixer->chip; |
2658 | unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */ |
2659 | unsigned char *val; |
2660 | - int ret, size; |
2661 | + int idx = 0, ret, size; |
2662 | __u8 bRequest; |
2663 | |
2664 | if (request == UAC_GET_CUR) { |
2665 | @@ -330,16 +337,22 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v |
2666 | if (ret) |
2667 | goto error; |
2668 | |
2669 | - ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, |
2670 | + down_read(&chip->shutdown_rwsem); |
2671 | + if (chip->shutdown) |
2672 | + ret = -ENODEV; |
2673 | + else { |
2674 | + idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); |
2675 | + ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, |
2676 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
2677 | - validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), |
2678 | - buf, size); |
2679 | + validx, idx, buf, size); |
2680 | + } |
2681 | + up_read(&chip->shutdown_rwsem); |
2682 | snd_usb_autosuspend(chip); |
2683 | |
2684 | if (ret < 0) { |
2685 | error: |
2686 | snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", |
2687 | - request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); |
2688 | + request, validx, idx, cval->val_type); |
2689 | return ret; |
2690 | } |
2691 | |
2692 | @@ -417,7 +430,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, |
2693 | { |
2694 | struct snd_usb_audio *chip = cval->mixer->chip; |
2695 | unsigned char buf[2]; |
2696 | - int val_len, err, timeout = 10; |
2697 | + int idx = 0, val_len, err, timeout = 10; |
2698 | |
2699 | if (cval->mixer->protocol == UAC_VERSION_1) { |
2700 | val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; |
2701 | @@ -440,19 +453,27 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, |
2702 | err = snd_usb_autoresume(chip); |
2703 | if (err < 0) |
2704 | return -EIO; |
2705 | - while (timeout-- > 0) |
2706 | + down_read(&chip->shutdown_rwsem); |
2707 | + while (timeout-- > 0) { |
2708 | + if (chip->shutdown) |
2709 | + break; |
2710 | + idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); |
2711 | if (snd_usb_ctl_msg(chip->dev, |
2712 | usb_sndctrlpipe(chip->dev, 0), request, |
2713 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, |
2714 | - validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), |
2715 | - buf, val_len) >= 0) { |
2716 | - snd_usb_autosuspend(chip); |
2717 | - return 0; |
2718 | + validx, idx, buf, val_len) >= 0) { |
2719 | + err = 0; |
2720 | + goto out; |
2721 | } |
2722 | - snd_usb_autosuspend(chip); |
2723 | + } |
2724 | snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", |
2725 | - request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); |
2726 | - return -EINVAL; |
2727 | + request, validx, idx, cval->val_type, buf[0], buf[1]); |
2728 | + err = -EINVAL; |
2729 | + |
2730 | + out: |
2731 | + up_read(&chip->shutdown_rwsem); |
2732 | + snd_usb_autosuspend(chip); |
2733 | + return err; |
2734 | } |
2735 | |
2736 | static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value) |
2737 | diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c |
2738 | index 690000d..ae2b714 100644 |
2739 | --- a/sound/usb/mixer_quirks.c |
2740 | +++ b/sound/usb/mixer_quirks.c |
2741 | @@ -283,6 +283,11 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e |
2742 | if (value > 1) |
2743 | return -EINVAL; |
2744 | changed = value != mixer->audigy2nx_leds[index]; |
2745 | + down_read(&mixer->chip->shutdown_rwsem); |
2746 | + if (mixer->chip->shutdown) { |
2747 | + err = -ENODEV; |
2748 | + goto out; |
2749 | + } |
2750 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) |
2751 | err = snd_usb_ctl_msg(mixer->chip->dev, |
2752 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, |
2753 | @@ -299,6 +304,8 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e |
2754 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, |
2755 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, |
2756 | value, index + 2, NULL, 0); |
2757 | + out: |
2758 | + up_read(&mixer->chip->shutdown_rwsem); |
2759 | if (err < 0) |
2760 | return err; |
2761 | mixer->audigy2nx_leds[index] = value; |
2762 | @@ -392,11 +399,16 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, |
2763 | |
2764 | for (i = 0; jacks[i].name; ++i) { |
2765 | snd_iprintf(buffer, "%s: ", jacks[i].name); |
2766 | - err = snd_usb_ctl_msg(mixer->chip->dev, |
2767 | + down_read(&mixer->chip->shutdown_rwsem); |
2768 | + if (mixer->chip->shutdown) |
2769 | + err = 0; |
2770 | + else |
2771 | + err = snd_usb_ctl_msg(mixer->chip->dev, |
2772 | usb_rcvctrlpipe(mixer->chip->dev, 0), |
2773 | UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | |
2774 | USB_RECIP_INTERFACE, 0, |
2775 | jacks[i].unitid << 8, buf, 3); |
2776 | + up_read(&mixer->chip->shutdown_rwsem); |
2777 | if (err == 3 && (buf[0] == 3 || buf[0] == 6)) |
2778 | snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]); |
2779 | else |
2780 | @@ -426,10 +438,15 @@ static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol, |
2781 | else |
2782 | new_status = old_status & ~0x02; |
2783 | changed = new_status != old_status; |
2784 | - err = snd_usb_ctl_msg(mixer->chip->dev, |
2785 | + down_read(&mixer->chip->shutdown_rwsem); |
2786 | + if (mixer->chip->shutdown) |
2787 | + err = -ENODEV; |
2788 | + else |
2789 | + err = snd_usb_ctl_msg(mixer->chip->dev, |
2790 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x08, |
2791 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, |
2792 | 50, 0, &new_status, 1); |
2793 | + up_read(&mixer->chip->shutdown_rwsem); |
2794 | if (err < 0) |
2795 | return err; |
2796 | mixer->xonar_u1_status = new_status; |
2797 | @@ -468,11 +485,17 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol, |
2798 | u8 bRequest = (kcontrol->private_value >> 16) & 0xff; |
2799 | u16 wIndex = kcontrol->private_value & 0xffff; |
2800 | u8 tmp; |
2801 | + int ret; |
2802 | |
2803 | - int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, |
2804 | + down_read(&mixer->chip->shutdown_rwsem); |
2805 | + if (mixer->chip->shutdown) |
2806 | + ret = -ENODEV; |
2807 | + else |
2808 | + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, |
2809 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, |
2810 | 0, cpu_to_le16(wIndex), |
2811 | &tmp, sizeof(tmp), 1000); |
2812 | + up_read(&mixer->chip->shutdown_rwsem); |
2813 | |
2814 | if (ret < 0) { |
2815 | snd_printk(KERN_ERR |
2816 | @@ -493,11 +516,17 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, |
2817 | u8 bRequest = (kcontrol->private_value >> 16) & 0xff; |
2818 | u16 wIndex = kcontrol->private_value & 0xffff; |
2819 | u16 wValue = ucontrol->value.integer.value[0]; |
2820 | + int ret; |
2821 | |
2822 | - int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, |
2823 | + down_read(&mixer->chip->shutdown_rwsem); |
2824 | + if (mixer->chip->shutdown) |
2825 | + ret = -ENODEV; |
2826 | + else |
2827 | + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, |
2828 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, |
2829 | cpu_to_le16(wValue), cpu_to_le16(wIndex), |
2830 | NULL, 0, 1000); |
2831 | + up_read(&mixer->chip->shutdown_rwsem); |
2832 | |
2833 | if (ret < 0) { |
2834 | snd_printk(KERN_ERR |
2835 | @@ -656,11 +685,16 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl, |
2836 | return -EINVAL; |
2837 | |
2838 | |
2839 | - err = snd_usb_ctl_msg(chip->dev, |
2840 | + down_read(&mixer->chip->shutdown_rwsem); |
2841 | + if (mixer->chip->shutdown) |
2842 | + err = -ENODEV; |
2843 | + else |
2844 | + err = snd_usb_ctl_msg(chip->dev, |
2845 | usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, |
2846 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
2847 | validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), |
2848 | value, val_len); |
2849 | + up_read(&mixer->chip->shutdown_rwsem); |
2850 | if (err < 0) |
2851 | return err; |
2852 | |
2853 | @@ -703,11 +737,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, |
2854 | |
2855 | if (!pval->is_cached) { |
2856 | /* Read current value */ |
2857 | - err = snd_usb_ctl_msg(chip->dev, |
2858 | + down_read(&mixer->chip->shutdown_rwsem); |
2859 | + if (mixer->chip->shutdown) |
2860 | + err = -ENODEV; |
2861 | + else |
2862 | + err = snd_usb_ctl_msg(chip->dev, |
2863 | usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, |
2864 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
2865 | validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), |
2866 | value, val_len); |
2867 | + up_read(&mixer->chip->shutdown_rwsem); |
2868 | if (err < 0) |
2869 | return err; |
2870 | |
2871 | @@ -719,11 +758,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, |
2872 | if (cur_val != new_val) { |
2873 | value[0] = new_val; |
2874 | value[1] = 0; |
2875 | - err = snd_usb_ctl_msg(chip->dev, |
2876 | + down_read(&mixer->chip->shutdown_rwsem); |
2877 | + if (mixer->chip->shutdown) |
2878 | + err = -ENODEV; |
2879 | + else |
2880 | + err = snd_usb_ctl_msg(chip->dev, |
2881 | usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR, |
2882 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, |
2883 | validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), |
2884 | value, val_len); |
2885 | + up_read(&mixer->chip->shutdown_rwsem); |
2886 | if (err < 0) |
2887 | return err; |
2888 | |
2889 | diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c |
2890 | index f782ce1..ee3c15c 100644 |
2891 | --- a/sound/usb/pcm.c |
2892 | +++ b/sound/usb/pcm.c |
2893 | @@ -71,6 +71,8 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream |
2894 | unsigned int hwptr_done; |
2895 | |
2896 | subs = (struct snd_usb_substream *)substream->runtime->private_data; |
2897 | + if (subs->stream->chip->shutdown) |
2898 | + return SNDRV_PCM_POS_XRUN; |
2899 | spin_lock(&subs->lock); |
2900 | hwptr_done = subs->hwptr_done; |
2901 | substream->runtime->delay = snd_usb_pcm_delay(subs, |
2902 | @@ -471,8 +473,14 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, |
2903 | changed = subs->cur_audiofmt != fmt || |
2904 | subs->period_bytes != params_period_bytes(hw_params) || |
2905 | subs->cur_rate != rate; |
2906 | + |
2907 | + down_read(&subs->stream->chip->shutdown_rwsem); |
2908 | + if (subs->stream->chip->shutdown) { |
2909 | + ret = -ENODEV; |
2910 | + goto unlock; |
2911 | + } |
2912 | if ((ret = set_format(subs, fmt)) < 0) |
2913 | - return ret; |
2914 | + goto unlock; |
2915 | |
2916 | if (subs->cur_rate != rate) { |
2917 | struct usb_host_interface *alts; |
2918 | @@ -481,12 +489,11 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, |
2919 | alts = &iface->altsetting[fmt->altset_idx]; |
2920 | ret = snd_usb_init_sample_rate(subs->stream->chip, fmt->iface, alts, fmt, rate); |
2921 | if (ret < 0) |
2922 | - return ret; |
2923 | + goto unlock; |
2924 | subs->cur_rate = rate; |
2925 | } |
2926 | |
2927 | if (changed) { |
2928 | - mutex_lock(&subs->stream->chip->shutdown_mutex); |
2929 | /* format changed */ |
2930 | stop_endpoints(subs, 0, 0, 0); |
2931 | ret = snd_usb_endpoint_set_params(subs->data_endpoint, hw_params, fmt, |
2932 | @@ -497,8 +504,6 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, |
2933 | if (subs->sync_endpoint) |
2934 | ret = snd_usb_endpoint_set_params(subs->sync_endpoint, |
2935 | hw_params, fmt, NULL); |
2936 | -unlock: |
2937 | - mutex_unlock(&subs->stream->chip->shutdown_mutex); |
2938 | } |
2939 | |
2940 | if (ret == 0) { |
2941 | @@ -506,6 +511,8 @@ unlock: |
2942 | subs->altset_idx = fmt->altset_idx; |
2943 | } |
2944 | |
2945 | +unlock: |
2946 | + up_read(&subs->stream->chip->shutdown_rwsem); |
2947 | return ret; |
2948 | } |
2949 | |
2950 | @@ -521,10 +528,12 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) |
2951 | subs->cur_audiofmt = NULL; |
2952 | subs->cur_rate = 0; |
2953 | subs->period_bytes = 0; |
2954 | - mutex_lock(&subs->stream->chip->shutdown_mutex); |
2955 | - stop_endpoints(subs, 0, 1, 1); |
2956 | - deactivate_endpoints(subs); |
2957 | - mutex_unlock(&subs->stream->chip->shutdown_mutex); |
2958 | + down_read(&subs->stream->chip->shutdown_rwsem); |
2959 | + if (!subs->stream->chip->shutdown) { |
2960 | + stop_endpoints(subs, 0, 1, 1); |
2961 | + deactivate_endpoints(subs); |
2962 | + } |
2963 | + up_read(&subs->stream->chip->shutdown_rwsem); |
2964 | return snd_pcm_lib_free_vmalloc_buffer(substream); |
2965 | } |
2966 | |
2967 | @@ -537,14 +546,22 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) |
2968 | { |
2969 | struct snd_pcm_runtime *runtime = substream->runtime; |
2970 | struct snd_usb_substream *subs = runtime->private_data; |
2971 | + int ret = 0; |
2972 | |
2973 | if (! subs->cur_audiofmt) { |
2974 | snd_printk(KERN_ERR "usbaudio: no format is specified!\n"); |
2975 | return -ENXIO; |
2976 | } |
2977 | |
2978 | - if (snd_BUG_ON(!subs->data_endpoint)) |
2979 | - return -EIO; |
2980 | + down_read(&subs->stream->chip->shutdown_rwsem); |
2981 | + if (subs->stream->chip->shutdown) { |
2982 | + ret = -ENODEV; |
2983 | + goto unlock; |
2984 | + } |
2985 | + if (snd_BUG_ON(!subs->data_endpoint)) { |
2986 | + ret = -EIO; |
2987 | + goto unlock; |
2988 | + } |
2989 | |
2990 | /* some unit conversions in runtime */ |
2991 | subs->data_endpoint->maxframesize = |
2992 | @@ -562,9 +579,11 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) |
2993 | /* for playback, submit the URBs now; otherwise, the first hwptr_done |
2994 | * updates for all URBs would happen at the same time when starting */ |
2995 | if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) |
2996 | - return start_endpoints(subs, 1); |
2997 | + ret = start_endpoints(subs, 1); |
2998 | |
2999 | - return 0; |
3000 | + unlock: |
3001 | + up_read(&subs->stream->chip->shutdown_rwsem); |
3002 | + return ret; |
3003 | } |
3004 | |
3005 | static struct snd_pcm_hardware snd_usb_hardware = |
3006 | @@ -617,7 +636,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs, |
3007 | return 0; |
3008 | } |
3009 | /* check whether the period time is >= the data packet interval */ |
3010 | - if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) { |
3011 | + if (subs->speed != USB_SPEED_FULL) { |
3012 | ptime = 125 * (1 << fp->datainterval); |
3013 | if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { |
3014 | hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); |
3015 | @@ -895,7 +914,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre |
3016 | return err; |
3017 | |
3018 | param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; |
3019 | - if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) |
3020 | + if (subs->speed == USB_SPEED_FULL) |
3021 | /* full speed devices have fixed data packet interval */ |
3022 | ptmin = 1000; |
3023 | if (ptmin == 1000) |
3024 | diff --git a/sound/usb/proc.c b/sound/usb/proc.c |
3025 | index ebc1a5b..d218f76 100644 |
3026 | --- a/sound/usb/proc.c |
3027 | +++ b/sound/usb/proc.c |
3028 | @@ -108,7 +108,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s |
3029 | } |
3030 | snd_iprintf(buffer, "\n"); |
3031 | } |
3032 | - if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) |
3033 | + if (subs->speed != USB_SPEED_FULL) |
3034 | snd_iprintf(buffer, " Data packet interval: %d us\n", |
3035 | 125 * (1 << fp->datainterval)); |
3036 | // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize); |
3037 | @@ -124,7 +124,7 @@ static void proc_dump_ep_status(struct snd_usb_substream *subs, |
3038 | return; |
3039 | snd_iprintf(buffer, " Packet Size = %d\n", ep->curpacksize); |
3040 | snd_iprintf(buffer, " Momentary freq = %u Hz (%#x.%04x)\n", |
3041 | - snd_usb_get_speed(subs->dev) == USB_SPEED_FULL |
3042 | + subs->speed == USB_SPEED_FULL |
3043 | ? get_full_speed_hz(ep->freqm) |
3044 | : get_high_speed_hz(ep->freqm), |
3045 | ep->freqm >> 16, ep->freqm & 0xffff); |
3046 | diff --git a/sound/usb/stream.c b/sound/usb/stream.c |
3047 | index 083ed81..1de0c8c 100644 |
3048 | --- a/sound/usb/stream.c |
3049 | +++ b/sound/usb/stream.c |
3050 | @@ -90,6 +90,7 @@ static void snd_usb_init_substream(struct snd_usb_stream *as, |
3051 | subs->direction = stream; |
3052 | subs->dev = as->chip->dev; |
3053 | subs->txfr_quirk = as->chip->txfr_quirk; |
3054 | + subs->speed = snd_usb_get_speed(subs->dev); |
3055 | |
3056 | snd_usb_set_pcm_ops(as->pcm, stream); |
3057 | |
3058 | diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h |
3059 | index b8233eb..ef42797 100644 |
3060 | --- a/sound/usb/usbaudio.h |
3061 | +++ b/sound/usb/usbaudio.h |
3062 | @@ -37,7 +37,7 @@ struct snd_usb_audio { |
3063 | struct usb_interface *pm_intf; |
3064 | u32 usb_id; |
3065 | struct mutex mutex; |
3066 | - struct mutex shutdown_mutex; |
3067 | + struct rw_semaphore shutdown_rwsem; |
3068 | unsigned int shutdown:1; |
3069 | unsigned int probing:1; |
3070 | unsigned int autosuspended:1; |