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