Annotation of /trunk/kernel-magellan/patches-3.6/0106-3.6.7-all-fixes.patch
Parent Directory | Revision Log
Revision 1960 -
(hide 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 | niro | 1960 | 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; |