diff options
Diffstat (limited to 'drivers')
53 files changed, 528 insertions, 219 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 292de3cab9cc..ccba6e46cfb3 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -33,6 +33,7 @@ #include <linux/proc_fs.h> #include <linux/acpi.h> #include <linux/slab.h> +#include <linux/regulator/machine.h> #ifdef CONFIG_X86 #include <asm/mpspec.h> #endif @@ -705,6 +706,14 @@ void __init acpi_early_init(void) goto error0; } + /* + * If the system is using ACPI then we can be reasonably + * confident that any regulators are managed by the firmware + * so tell the regulator core it has everything it needs to + * know. + */ + regulator_has_full_constraints(); + return; error0: diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index a22fb3e47256..34d19b1984a1 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -48,7 +48,7 @@ static inline int32_t div_fp(int32_t x, int32_t y) } struct sample { - int core_pct_busy; + int32_t core_pct_busy; u64 aperf; u64 mperf; int freq; @@ -68,7 +68,7 @@ struct _pid { int32_t i_gain; int32_t d_gain; int deadband; - int last_err; + int32_t last_err; }; struct cpudata { @@ -153,16 +153,15 @@ static inline void pid_d_gain_set(struct _pid *pid, int percent) pid->d_gain = div_fp(int_tofp(percent), int_tofp(100)); } -static signed int pid_calc(struct _pid *pid, int busy) +static signed int pid_calc(struct _pid *pid, int32_t busy) { - signed int err, result; + signed int result; int32_t pterm, dterm, fp_error; int32_t integral_limit; - err = pid->setpoint - busy; - fp_error = int_tofp(err); + fp_error = int_tofp(pid->setpoint) - busy; - if (abs(err) <= pid->deadband) + if (abs(fp_error) <= int_tofp(pid->deadband)) return 0; pterm = mul_fp(pid->p_gain, fp_error); @@ -176,8 +175,8 @@ static signed int pid_calc(struct _pid *pid, int busy) if (pid->integral < -integral_limit) pid->integral = -integral_limit; - dterm = mul_fp(pid->d_gain, (err - pid->last_err)); - pid->last_err = err; + dterm = mul_fp(pid->d_gain, fp_error - pid->last_err); + pid->last_err = fp_error; result = pterm + mul_fp(pid->integral, pid->i_gain) + dterm; @@ -367,12 +366,13 @@ static int intel_pstate_turbo_pstate(void) static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max) { int max_perf = cpu->pstate.turbo_pstate; + int max_perf_adj; int min_perf; if (limits.no_turbo) max_perf = cpu->pstate.max_pstate; - max_perf = fp_toint(mul_fp(int_tofp(max_perf), limits.max_perf)); - *max = clamp_t(int, max_perf, + max_perf_adj = fp_toint(mul_fp(int_tofp(max_perf), limits.max_perf)); + *max = clamp_t(int, max_perf_adj, cpu->pstate.min_pstate, cpu->pstate.turbo_pstate); min_perf = fp_toint(mul_fp(int_tofp(max_perf), limits.min_perf)); @@ -394,7 +394,10 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) trace_cpu_frequency(pstate * 100000, cpu->cpu); cpu->pstate.current_pstate = pstate; - wrmsrl(MSR_IA32_PERF_CTL, pstate << 8); + if (limits.no_turbo) + wrmsrl(MSR_IA32_PERF_CTL, BIT(32) | (pstate << 8)); + else + wrmsrl(MSR_IA32_PERF_CTL, pstate << 8); } @@ -432,8 +435,9 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu, struct sample *sample) { u64 core_pct; - core_pct = div64_u64(sample->aperf * 100, sample->mperf); - sample->freq = cpu->pstate.max_pstate * core_pct * 1000; + core_pct = div64_u64(int_tofp(sample->aperf * 100), + sample->mperf); + sample->freq = fp_toint(cpu->pstate.max_pstate * core_pct * 1000); sample->core_pct_busy = core_pct; } @@ -465,22 +469,19 @@ static inline void intel_pstate_set_sample_time(struct cpudata *cpu) mod_timer_pinned(&cpu->timer, jiffies + delay); } -static inline int intel_pstate_get_scaled_busy(struct cpudata *cpu) +static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu) { - int32_t busy_scaled; int32_t core_busy, max_pstate, current_pstate; - core_busy = int_tofp(cpu->samples[cpu->sample_ptr].core_pct_busy); + core_busy = cpu->samples[cpu->sample_ptr].core_pct_busy; max_pstate = int_tofp(cpu->pstate.max_pstate); current_pstate = int_tofp(cpu->pstate.current_pstate); - busy_scaled = mul_fp(core_busy, div_fp(max_pstate, current_pstate)); - - return fp_toint(busy_scaled); + return mul_fp(core_busy, div_fp(max_pstate, current_pstate)); } static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu) { - int busy_scaled; + int32_t busy_scaled; struct _pid *pid; signed int ctl = 0; int steps; @@ -523,6 +524,11 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = { ICPU(0x2a, default_policy), ICPU(0x2d, default_policy), ICPU(0x3a, default_policy), + ICPU(0x3c, default_policy), + ICPU(0x3e, default_policy), + ICPU(0x3f, default_policy), + ICPU(0x45, default_policy), + ICPU(0x46, default_policy), {} }; MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids); diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index 272a3ec35957..0314dde18a5d 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c @@ -275,11 +275,13 @@ static int __init eisa_request_resources(struct eisa_root_device *root, } if (slot) { + edev->res[i].name = NULL; edev->res[i].start = SLOT_ADDRESS(root, slot) + (i * 0x400); edev->res[i].end = edev->res[i].start + 0xff; edev->res[i].flags = IORESOURCE_IO; } else { + edev->res[i].name = NULL; edev->res[i].start = SLOT_ADDRESS(root, slot) + EISA_VENDOR_ID_OFFSET; edev->res[i].end = edev->res[i].start + 3; @@ -326,19 +328,20 @@ static int __init eisa_probe(struct eisa_root_device *root) return -ENOMEM; } - if (eisa_init_device(root, edev, 0)) { + if (eisa_request_resources(root, edev, 0)) { + dev_warn(root->dev, + "EISA: Cannot allocate resource for mainboard\n"); kfree(edev); if (!root->force_probe) - return -ENODEV; + return -EBUSY; goto force_probe; } - if (eisa_request_resources(root, edev, 0)) { - dev_warn(root->dev, - "EISA: Cannot allocate resource for mainboard\n"); + if (eisa_init_device(root, edev, 0)) { + eisa_release_resources(edev); kfree(edev); if (!root->force_probe) - return -EBUSY; + return -ENODEV; goto force_probe; } @@ -361,11 +364,6 @@ static int __init eisa_probe(struct eisa_root_device *root) continue; } - if (eisa_init_device(root, edev, i)) { - kfree(edev); - continue; - } - if (eisa_request_resources(root, edev, i)) { dev_warn(root->dev, "Cannot allocate resource for EISA slot %d\n", @@ -374,6 +372,12 @@ static int __init eisa_probe(struct eisa_root_device *root) continue; } + if (eisa_init_device(root, edev, i)) { + eisa_release_resources(edev); + kfree(edev); + continue; + } + if (edev->state == (EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED)) enabled_str = " (forced enabled)"; else if (edev->state == EISA_CONFIG_FORCED) diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 60685b21cc36..379a47ea99f6 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -273,8 +273,8 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc, sr07 |= 0x11; break; case 16: - sr07 |= 0xc1; - hdr = 0xc0; + sr07 |= 0x17; + hdr = 0xc1; break; case 24: sr07 |= 0x15; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index d9d7d675246a..ccfc63665e76 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1687,6 +1687,7 @@ out_gem_unload: intel_teardown_gmbus(dev); intel_teardown_mchbar(dev); + pm_qos_remove_request(&dev_priv->pm_qos); destroy_workqueue(dev_priv->wq); out_mtrrfree: if (dev_priv->mm.gtt_mtrr >= 0) { diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 130d1db27e28..fa2d15b16739 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -222,7 +222,7 @@ i915_pages_create_for_stolen(struct drm_device *dev, } sg = st->sgl; - sg->offset = offset; + sg->offset = 0; sg->length = size; sg_dma_address(sg) = (dma_addr_t)dev_priv->mm.stolen_base + offset; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b1a0cdba59e7..2d90f96c19d0 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1682,9 +1682,13 @@ * Please check the detailed lore in the commit message for for experimental * evidence. */ -#define PORTD_HOTPLUG_LIVE_STATUS (1 << 29) -#define PORTC_HOTPLUG_LIVE_STATUS (1 << 28) -#define PORTB_HOTPLUG_LIVE_STATUS (1 << 27) +#define PORTD_HOTPLUG_LIVE_STATUS_G4X (1 << 29) +#define PORTC_HOTPLUG_LIVE_STATUS_G4X (1 << 28) +#define PORTB_HOTPLUG_LIVE_STATUS_G4X (1 << 27) +/* VLV DP/HDMI bits again match Bspec */ +#define PORTD_HOTPLUG_LIVE_STATUS_VLV (1 << 27) +#define PORTC_HOTPLUG_LIVE_STATUS_VLV (1 << 28) +#define PORTB_HOTPLUG_LIVE_STATUS_VLV (1 << 29) #define PORTD_HOTPLUG_INT_STATUS (3 << 21) #define PORTC_HOTPLUG_INT_STATUS (3 << 19) #define PORTB_HOTPLUG_INT_STATUS (3 << 17) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 80feaec88d2b..cfd327c292ee 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2277,18 +2277,34 @@ g4x_dp_detect(struct intel_dp *intel_dp) return status; } - switch (intel_dig_port->port) { - case PORT_B: - bit = PORTB_HOTPLUG_LIVE_STATUS; - break; - case PORT_C: - bit = PORTC_HOTPLUG_LIVE_STATUS; - break; - case PORT_D: - bit = PORTD_HOTPLUG_LIVE_STATUS; - break; - default: - return connector_status_unknown; + if (IS_VALLEYVIEW(dev)) { + switch (intel_dig_port->port) { + case PORT_B: + bit = PORTB_HOTPLUG_LIVE_STATUS_VLV; + break; + case PORT_C: + bit = PORTC_HOTPLUG_LIVE_STATUS_VLV; + break; + case PORT_D: + bit = PORTD_HOTPLUG_LIVE_STATUS_VLV; + break; + default: + return connector_status_unknown; + } + } else { + switch (intel_dig_port->port) { + case PORT_B: + bit = PORTB_HOTPLUG_LIVE_STATUS_G4X; + break; + case PORT_C: + bit = PORTC_HOTPLUG_LIVE_STATUS_G4X; + break; + case PORT_D: + bit = PORTD_HOTPLUG_LIVE_STATUS_G4X; + break; + default: + return connector_status_unknown; + } } if ((I915_READ(PORT_HOTPLUG_STAT) & bit) == 0) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 48fe23e8d180..629527d205de 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1459,8 +1459,8 @@ intel_ring_alloc_seqno(struct intel_ring_buffer *ring) return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_request); } -static int __intel_ring_begin(struct intel_ring_buffer *ring, - int bytes) +static int __intel_ring_prepare(struct intel_ring_buffer *ring, + int bytes) { int ret; @@ -1476,7 +1476,6 @@ static int __intel_ring_begin(struct intel_ring_buffer *ring, return ret; } - ring->space -= bytes; return 0; } @@ -1491,12 +1490,17 @@ int intel_ring_begin(struct intel_ring_buffer *ring, if (ret) return ret; + ret = __intel_ring_prepare(ring, num_dwords * sizeof(uint32_t)); + if (ret) + return ret; + /* Preallocate the olr before touching the ring */ ret = intel_ring_alloc_seqno(ring); if (ret) return ret; - return __intel_ring_begin(ring, num_dwords * sizeof(uint32_t)); + ring->space -= num_dwords * sizeof(uint32_t); + return 0; } void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 99e07b688ea8..f6341e8622ee 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1477,11 +1477,11 @@ static int mga_vga_mode_valid(struct drm_connector *connector, (mga_vga_calculate_mode_bandwidth(mode, bpp) > (32700 * 1024))) { return MODE_BANDWIDTH; - } else if (mode->type == G200_EH && + } else if (mdev->type == G200_EH && (mga_vga_calculate_mode_bandwidth(mode, bpp) > (37500 * 1024))) { return MODE_BANDWIDTH; - } else if (mode->type == G200_ER && + } else if (mdev->type == G200_ER && (mga_vga_calculate_mode_bandwidth(mode, bpp) > (55000 * 1024))) { return MODE_BANDWIDTH; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 7ff10711a4d0..5a5f021d5863 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -788,25 +788,25 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) { struct nouveau_mem *node = old_mem->mm_node; - struct nouveau_bo *nvbo = nouveau_bo(bo); u64 length = (new_mem->num_pages << PAGE_SHIFT); u64 src_offset = node->vma[0].offset; u64 dst_offset = node->vma[1].offset; + int src_tiled = !!node->memtype; + int dst_tiled = !!((struct nouveau_mem *)new_mem->mm_node)->memtype; int ret; while (length) { u32 amount, stride, height; + ret = RING_SPACE(chan, 18 + 6 * (src_tiled + dst_tiled)); + if (ret) + return ret; + amount = min(length, (u64)(4 * 1024 * 1024)); stride = 16 * 4; height = amount / stride; - if (old_mem->mem_type == TTM_PL_VRAM && - nouveau_bo_tile_layout(nvbo)) { - ret = RING_SPACE(chan, 8); - if (ret) - return ret; - + if (src_tiled) { BEGIN_NV04(chan, NvSubCopy, 0x0200, 7); OUT_RING (chan, 0); OUT_RING (chan, 0); @@ -816,19 +816,10 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, OUT_RING (chan, 0); OUT_RING (chan, 0); } else { - ret = RING_SPACE(chan, 2); - if (ret) - return ret; - BEGIN_NV04(chan, NvSubCopy, 0x0200, 1); OUT_RING (chan, 1); } - if (new_mem->mem_type == TTM_PL_VRAM && - nouveau_bo_tile_layout(nvbo)) { - ret = RING_SPACE(chan, 8); - if (ret) - return ret; - + if (dst_tiled) { BEGIN_NV04(chan, NvSubCopy, 0x021c, 7); OUT_RING (chan, 0); OUT_RING (chan, 0); @@ -838,18 +829,10 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, OUT_RING (chan, 0); OUT_RING (chan, 0); } else { - ret = RING_SPACE(chan, 2); - if (ret) - return ret; - BEGIN_NV04(chan, NvSubCopy, 0x021c, 1); OUT_RING (chan, 1); } - ret = RING_SPACE(chan, 14); - if (ret) - return ret; - BEGIN_NV04(chan, NvSubCopy, 0x0238, 2); OUT_RING (chan, upper_32_bits(src_offset)); OUT_RING (chan, upper_32_bits(dst_offset)); diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 5285a90e9f59..50684dc6ffdf 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -938,11 +938,14 @@ static bool atombios_crtc_prepare_pll(struct drm_crtc *crtc, struct drm_display_ radeon_atombios_get_ppll_ss_info(rdev, &radeon_crtc->ss, ATOM_DP_SS_ID1); - } else + } else { radeon_crtc->ss_enabled = radeon_atombios_get_ppll_ss_info(rdev, &radeon_crtc->ss, ATOM_DP_SS_ID1); + } + /* disable spread spectrum on DCE3 DP */ + radeon_crtc->ss_enabled = false; } break; case ATOM_ENCODER_MODE_LVDS: diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 8b6b0ba6ae40..93e26339051d 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -3792,8 +3792,8 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev) WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); } - /* only one DAC on DCE6 */ - if (!ASIC_IS_DCE6(rdev)) + /* only one DAC on DCE5 */ + if (!ASIC_IS_DCE5(rdev)) WREG32(DACA_AUTODETECT_INT_CONTROL, 0); WREG32(DACB_AUTODETECT_INT_CONTROL, 0); diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index eb8ac315f92f..c7cac07f139b 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -967,7 +967,10 @@ static int evergreen_cs_track_check(struct radeon_cs_parser *p) if (track->cb_dirty) { tmp = track->cb_target_mask; for (i = 0; i < 8; i++) { - if ((tmp >> (i * 4)) & 0xF) { + u32 format = G_028C70_FORMAT(track->cb_color_info[i]); + + if (format != V_028C70_COLOR_INVALID && + (tmp >> (i * 4)) & 0xF) { /* at least one component is enabled */ if (track->cb_color_bo[i] == NULL) { dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n", diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 4438d1b09325..451d7886644c 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -1178,13 +1178,12 @@ void cayman_fence_ring_emit(struct radeon_device *rdev, { struct radeon_ring *ring = &rdev->ring[fence->ring]; u64 addr = rdev->fence_drv[fence->ring].gpu_addr; + u32 cp_coher_cntl = PACKET3_FULL_CACHE_ENA | PACKET3_TC_ACTION_ENA | + PACKET3_SH_ACTION_ENA; /* flush read cache over gart for this vmid */ - radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); - radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); - radeon_ring_write(ring, 0); radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); - radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA); + radeon_ring_write(ring, PACKET3_ENGINE_ME | cp_coher_cntl); radeon_ring_write(ring, 0xFFFFFFFF); radeon_ring_write(ring, 0); radeon_ring_write(ring, 10); /* poll interval */ @@ -1200,6 +1199,8 @@ void cayman_fence_ring_emit(struct radeon_device *rdev, void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) { struct radeon_ring *ring = &rdev->ring[ib->ring]; + u32 cp_coher_cntl = PACKET3_FULL_CACHE_ENA | PACKET3_TC_ACTION_ENA | + PACKET3_SH_ACTION_ENA; /* set to DX10/11 mode */ radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); @@ -1224,14 +1225,11 @@ void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) (ib->vm ? (ib->vm->id << 24) : 0)); /* flush read cache over gart for this vmid */ - radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); - radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); - radeon_ring_write(ring, ib->vm ? ib->vm->id : 0); radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); - radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA); + radeon_ring_write(ring, PACKET3_ENGINE_ME | cp_coher_cntl); radeon_ring_write(ring, 0xFFFFFFFF); radeon_ring_write(ring, 0); - radeon_ring_write(ring, 10); /* poll interval */ + radeon_ring_write(ring, ((ib->vm ? ib->vm->id : 0) << 24) | 10); /* poll interval */ } void cayman_uvd_semaphore_emit(struct radeon_device *rdev, diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index e226faf16fea..e49f7b456038 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h @@ -573,6 +573,7 @@ # define PACKET3_DB_ACTION_ENA (1 << 26) # define PACKET3_SH_ACTION_ENA (1 << 27) # define PACKET3_SX_ACTION_ENA (1 << 28) +# define PACKET3_ENGINE_ME (1 << 31) #define PACKET3_ME_INITIALIZE 0x44 #define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16) #define PACKET3_COND_WRITE 0x45 diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index f19620b472f5..1b8c3707bf42 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2957,14 +2957,17 @@ void r600_fence_ring_emit(struct radeon_device *rdev, struct radeon_fence *fence) { struct radeon_ring *ring = &rdev->ring[fence->ring]; + u32 cp_coher_cntl = PACKET3_TC_ACTION_ENA | PACKET3_VC_ACTION_ENA | + PACKET3_SH_ACTION_ENA; + + if (rdev->family >= CHIP_RV770) + cp_coher_cntl |= PACKET3_FULL_CACHE_ENA; if (rdev->wb.use_event) { u64 addr = rdev->fence_drv[fence->ring].gpu_addr; /* flush read cache over gart */ radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); - radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | - PACKET3_VC_ACTION_ENA | - PACKET3_SH_ACTION_ENA); + radeon_ring_write(ring, cp_coher_cntl); radeon_ring_write(ring, 0xFFFFFFFF); radeon_ring_write(ring, 0); radeon_ring_write(ring, 10); /* poll interval */ @@ -2978,9 +2981,7 @@ void r600_fence_ring_emit(struct radeon_device *rdev, } else { /* flush read cache over gart */ radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); - radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | - PACKET3_VC_ACTION_ENA | - PACKET3_SH_ACTION_ENA); + radeon_ring_write(ring, cp_coher_cntl); radeon_ring_write(ring, 0xFFFFFFFF); radeon_ring_write(ring, 0); radeon_ring_write(ring, 10); /* poll interval */ diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 01a3ec83f284..745e66eacd47 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -749,7 +749,10 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) } for (i = 0; i < 8; i++) { - if ((tmp >> (i * 4)) & 0xF) { + u32 format = G_0280A0_FORMAT(track->cb_color_info[i]); + + if (format != V_0280A0_COLOR_INVALID && + (tmp >> (i * 4)) & 0xF) { /* at least one component is enabled */ if (track->cb_color_bo[i] == NULL) { dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n", diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 2fd2241b6df9..eb28716e87fa 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -1283,6 +1283,7 @@ # define PACKET3_CP_DMA_CMD_DAIC (1 << 29) #define PACKET3_SURFACE_SYNC 0x43 # define PACKET3_CB0_DEST_BASE_ENA (1 << 6) +# define PACKET3_FULL_CACHE_ENA (1 << 20) /* r7xx+ only */ # define PACKET3_TC_ACTION_ENA (1 << 23) # define PACKET3_VC_ACTION_ENA (1 << 24) # define PACKET3_CB_ACTION_ENA (1 << 25) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 239a4074f122..efb06e34aed7 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -2926,6 +2926,10 @@ void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev) /* tell the bios not to handle mode switching */ bios_6_scratch |= ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH; + /* clear the vbios dpms state */ + if (ASIC_IS_DCE4(rdev)) + bios_2_scratch &= ~ATOM_S2_DEVICE_DPMS_STATE; + if (rdev->family >= CHIP_R600) { WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch); WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch); diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index fc60b74ee304..e24ca6ab96de 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -1020,6 +1020,9 @@ void radeon_i2c_destroy(struct radeon_i2c_chan *i2c) /* Add the default buses */ void radeon_i2c_init(struct radeon_device *rdev) { + if (radeon_hw_i2c) + DRM_INFO("hw_i2c forced on, you may experience display detection problems!\n"); + if (rdev->is_atom_bios) radeon_atombios_i2c_init(rdev); else diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 788c64cb4b47..469ba710b52f 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -561,8 +561,10 @@ void radeon_pm_resume(struct radeon_device *rdev) rdev->pm.current_clock_mode_index = 0; rdev->pm.current_sclk = rdev->pm.default_sclk; rdev->pm.current_mclk = rdev->pm.default_mclk; - rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; - rdev->pm.current_vddci = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.vddci; + if (rdev->pm.power_state) { + rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; + rdev->pm.current_vddci = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.vddci; + } if (rdev->pm.pm_method == PM_METHOD_DYNPM && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) { rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE; diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index bf14a6b89b59..3cf38ff09e70 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -4519,7 +4519,7 @@ static void si_disable_interrupt_state(struct radeon_device *rdev) } if (!ASIC_IS_NODCE(rdev)) { - WREG32(DACA_AUTODETECT_INT_CONTROL, 0); + WREG32(DAC_AUTODETECT_INT_CONTROL, 0); tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY; WREG32(DC_HPD1_INT_CONTROL, tmp); diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 108c8d2503c9..9652ed9ec639 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -394,7 +394,7 @@ # define GRPH_PFLIP_INT_MASK (1 << 0) # define GRPH_PFLIP_INT_TYPE (1 << 8) -#define DACA_AUTODETECT_INT_CONTROL 0x66c8 +#define DAC_AUTODETECT_INT_CONTROL 0x67c8 #define DC_HPD1_INT_STATUS 0x601c #define DC_HPD2_INT_STATUS 0x6028 diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 4faf02b3657d..49423e913459 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -108,6 +108,7 @@ config I2C_I801 Lynx Point-LP (PCH) Avoton (SOC) Wellsburg (PCH) + Coleto Creek (PCH) This driver can also be built as a module. If so, the module will be called i2c-i801. diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 3a6903f63913..4ebceed6bc66 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -58,6 +58,7 @@ Wellsburg (PCH) MS 0x8d7d 32 hard yes yes yes Wellsburg (PCH) MS 0x8d7e 32 hard yes yes yes Wellsburg (PCH) MS 0x8d7f 32 hard yes yes yes + Coleto Creek (PCH) 0x23b0 32 hard yes yes yes Features supported by this driver: Software PEC no @@ -169,6 +170,7 @@ #define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS 0x1e22 #define PCI_DEVICE_ID_INTEL_AVOTON_SMBUS 0x1f3c #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330 +#define PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS 0x23b0 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 #define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS 0x8d22 @@ -817,6 +819,7 @@ static DEFINE_PCI_DEVICE_TABLE(i801_ids) = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS0) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS) }, { 0, } }; diff --git a/drivers/infiniband/hw/qib/qib_ud.c b/drivers/infiniband/hw/qib/qib_ud.c index d6c7fe7f88d5..3ad651c3356c 100644 --- a/drivers/infiniband/hw/qib/qib_ud.c +++ b/drivers/infiniband/hw/qib/qib_ud.c @@ -57,13 +57,20 @@ static void qib_ud_loopback(struct qib_qp *sqp, struct qib_swqe *swqe) struct qib_sge *sge; struct ib_wc wc; u32 length; + enum ib_qp_type sqptype, dqptype; qp = qib_lookup_qpn(ibp, swqe->wr.wr.ud.remote_qpn); if (!qp) { ibp->n_pkt_drops++; return; } - if (qp->ibqp.qp_type != sqp->ibqp.qp_type || + + sqptype = sqp->ibqp.qp_type == IB_QPT_GSI ? + IB_QPT_UD : sqp->ibqp.qp_type; + dqptype = qp->ibqp.qp_type == IB_QPT_GSI ? + IB_QPT_UD : qp->ibqp.qp_type; + + if (dqptype != sqptype || !(ib_qib_state_ops[qp->state] & QIB_PROCESS_RECV_OK)) { ibp->n_pkt_drops++; goto drop; diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 25943a683d15..6771e3c94801 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -917,7 +917,7 @@ static void dma_pte_free_level(struct dmar_domain *domain, int level, /* If range covers entire pagetable, free it */ if (!(start_pfn > level_pfn || - last_pfn < level_pfn + level_size(level))) { + last_pfn < level_pfn + level_size(level) - 1)) { dma_clear_pte(pte); domain_flush_cache(domain, pte, sizeof(*pte)); free_pgtable_page(level_pte); diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index 3bfc8f1da9fe..29cff90096ad 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig @@ -176,8 +176,12 @@ config MD_FAULTY source "drivers/md/bcache/Kconfig" +config BLK_DEV_DM_BUILTIN + boolean + config BLK_DEV_DM tristate "Device mapper support" + select BLK_DEV_DM_BUILTIN ---help--- Device-mapper is a low level volume manager. It works by allowing people to specify mappings for ranges of logical sectors. Various diff --git a/drivers/md/Makefile b/drivers/md/Makefile index 1439fd4ad9b1..3591a7292381 100644 --- a/drivers/md/Makefile +++ b/drivers/md/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_MD_FAULTY) += faulty.o obj-$(CONFIG_BCACHE) += bcache/ obj-$(CONFIG_BLK_DEV_MD) += md-mod.o obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o +obj-$(CONFIG_BLK_DEV_DM_BUILTIN) += dm-builtin.o obj-$(CONFIG_DM_BUFIO) += dm-bufio.o obj-$(CONFIG_DM_BIO_PRISON) += dm-bio-prison.o obj-$(CONFIG_DM_CRYPT) += dm-crypt.o diff --git a/drivers/md/dm-builtin.c b/drivers/md/dm-builtin.c new file mode 100644 index 000000000000..6c9049c51b2b --- /dev/null +++ b/drivers/md/dm-builtin.c @@ -0,0 +1,48 @@ +#include "dm.h" + +/* + * The kobject release method must not be placed in the module itself, + * otherwise we are subject to module unload races. + * + * The release method is called when the last reference to the kobject is + * dropped. It may be called by any other kernel code that drops the last + * reference. + * + * The release method suffers from module unload race. We may prevent the + * module from being unloaded at the start of the release method (using + * increased module reference count or synchronizing against the release + * method), however there is no way to prevent the module from being + * unloaded at the end of the release method. + * + * If this code were placed in the dm module, the following race may + * happen: + * 1. Some other process takes a reference to dm kobject + * 2. The user issues ioctl function to unload the dm device + * 3. dm_sysfs_exit calls kobject_put, however the object is not released + * because of the other reference taken at step 1 + * 4. dm_sysfs_exit waits on the completion + * 5. The other process that took the reference in step 1 drops it, + * dm_kobject_release is called from this process + * 6. dm_kobject_release calls complete() + * 7. a reschedule happens before dm_kobject_release returns + * 8. dm_sysfs_exit continues, the dm device is unloaded, module reference + * count is decremented + * 9. The user unloads the dm module + * 10. The other process that was rescheduled in step 7 continues to run, + * it is now executing code in unloaded module, so it crashes + * + * Note that if the process that takes the foreign reference to dm kobject + * has a low priority and the system is sufficiently loaded with + * higher-priority processes that prevent the low-priority process from + * being scheduled long enough, this bug may really happen. + * + * In order to fix this module unload race, we place the release method + * into a helper code that is compiled directly into the kernel. + */ + +void dm_kobject_release(struct kobject *kobj) +{ + complete(dm_get_completion_from_kobject(kobj)); +} + +EXPORT_SYMBOL(dm_kobject_release); diff --git a/drivers/md/dm-sysfs.c b/drivers/md/dm-sysfs.c index 84d2b91e4efb..c62c5ab6aed5 100644 --- a/drivers/md/dm-sysfs.c +++ b/drivers/md/dm-sysfs.c @@ -86,6 +86,7 @@ static const struct sysfs_ops dm_sysfs_ops = { static struct kobj_type dm_ktype = { .sysfs_ops = &dm_sysfs_ops, .default_attrs = dm_attrs, + .release = dm_kobject_release, }; /* @@ -104,5 +105,7 @@ int dm_sysfs_init(struct mapped_device *md) */ void dm_sysfs_exit(struct mapped_device *md) { - kobject_put(dm_kobject(md)); + struct kobject *kobj = dm_kobject(md); + kobject_put(kobj); + wait_for_completion(dm_get_completion_from_kobject(kobj)); } diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index 60bce435f4fa..33ac3be2e836 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c @@ -1349,6 +1349,12 @@ dm_thin_id dm_thin_dev_id(struct dm_thin_device *td) return td->id; } +/* + * Check whether @time (of block creation) is older than @td's last snapshot. + * If so then the associated block is shared with the last snapshot device. + * Any block on a device created *after* the device last got snapshotted is + * necessarily not shared. + */ static bool __snapshotted_since(struct dm_thin_device *td, uint32_t time) { return td->snapshotted_time > time; @@ -1458,6 +1464,20 @@ int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block) return r; } +int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *result) +{ + int r; + uint32_t ref_count; + + down_read(&pmd->root_lock); + r = dm_sm_get_count(pmd->data_sm, b, &ref_count); + if (!r) + *result = (ref_count != 0); + up_read(&pmd->root_lock); + + return r; +} + bool dm_thin_changed_this_transaction(struct dm_thin_device *td) { int r; diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h index 845ebbe589a9..125c09444019 100644 --- a/drivers/md/dm-thin-metadata.h +++ b/drivers/md/dm-thin-metadata.h @@ -181,6 +181,8 @@ int dm_pool_get_data_block_size(struct dm_pool_metadata *pmd, sector_t *result); int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result); +int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *result); + /* * Returns -ENOSPC if the new size is too small and already allocated * blocks would be lost. diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index e36f81e282eb..73c76c565a4d 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -512,6 +512,7 @@ struct dm_thin_new_mapping { unsigned quiesced:1; unsigned prepared:1; unsigned pass_discard:1; + unsigned definitely_not_shared:1; struct thin_c *tc; dm_block_t virt_block; @@ -683,7 +684,15 @@ static void process_prepared_discard_passdown(struct dm_thin_new_mapping *m) cell_defer_no_holder(tc, m->cell2); if (m->pass_discard) - remap_and_issue(tc, m->bio, m->data_block); + if (m->definitely_not_shared) + remap_and_issue(tc, m->bio, m->data_block); + else { + bool used = false; + if (dm_pool_block_is_used(tc->pool->pmd, m->data_block, &used) || used) + bio_endio(m->bio, 0); + else + remap_and_issue(tc, m->bio, m->data_block); + } else bio_endio(m->bio, 0); @@ -751,13 +760,17 @@ static int ensure_next_mapping(struct pool *pool) static struct dm_thin_new_mapping *get_next_mapping(struct pool *pool) { - struct dm_thin_new_mapping *r = pool->next_mapping; + struct dm_thin_new_mapping *m = pool->next_mapping; BUG_ON(!pool->next_mapping); + memset(m, 0, sizeof(struct dm_thin_new_mapping)); + INIT_LIST_HEAD(&m->list); + m->bio = NULL; + pool->next_mapping = NULL; - return r; + return m; } static void schedule_copy(struct thin_c *tc, dm_block_t virt_block, @@ -769,15 +782,10 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block, struct pool *pool = tc->pool; struct dm_thin_new_mapping *m = get_next_mapping(pool); - INIT_LIST_HEAD(&m->list); - m->quiesced = 0; - m->prepared = 0; m->tc = tc; m->virt_block = virt_block; m->data_block = data_dest; m->cell = cell; - m->err = 0; - m->bio = NULL; if (!dm_deferred_set_add_work(pool->shared_read_ds, &m->list)) m->quiesced = 1; @@ -840,15 +848,12 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block, struct pool *pool = tc->pool; struct dm_thin_new_mapping *m = get_next_mapping(pool); - INIT_LIST_HEAD(&m->list); m->quiesced = 1; m->prepared = 0; m->tc = tc; m->virt_block = virt_block; m->data_block = data_block; m->cell = cell; - m->err = 0; - m->bio = NULL; /* * If the whole block of data is being overwritten or we are not @@ -1032,12 +1037,12 @@ static void process_discard(struct thin_c *tc, struct bio *bio) */ m = get_next_mapping(pool); m->tc = tc; - m->pass_discard = (!lookup_result.shared) && pool->pf.discard_passdown; + m->pass_discard = pool->pf.discard_passdown; + m->definitely_not_shared = !lookup_result.shared; m->virt_block = block; m->data_block = lookup_result.block; m->cell = cell; m->cell2 = cell2; - m->err = 0; m->bio = bio; if (!dm_deferred_set_add_work(pool->all_io_ds, &m->list)) { diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 1c13071a81be..204a59fd872f 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -184,8 +184,8 @@ struct mapped_device { /* forced geometry settings */ struct hd_geometry geometry; - /* sysfs handle */ - struct kobject kobj; + /* kobject and completion */ + struct dm_kobject_holder kobj_holder; /* zero-length flush that will be cloned and submitted to targets */ struct bio flush_bio; @@ -1904,6 +1904,7 @@ static struct mapped_device *alloc_dev(int minor) init_waitqueue_head(&md->wait); INIT_WORK(&md->work, dm_wq_work); init_waitqueue_head(&md->eventq); + init_completion(&md->kobj_holder.completion); md->disk->major = _major; md->disk->first_minor = minor; @@ -2735,20 +2736,14 @@ struct gendisk *dm_disk(struct mapped_device *md) struct kobject *dm_kobject(struct mapped_device *md) { - return &md->kobj; + return &md->kobj_holder.kobj; } -/* - * struct mapped_device should not be exported outside of dm.c - * so use this check to verify that kobj is part of md structure - */ struct mapped_device *dm_get_from_kobject(struct kobject *kobj) { struct mapped_device *md; - md = container_of(kobj, struct mapped_device, kobj); - if (&md->kobj != kobj) - return NULL; + md = container_of(kobj, struct mapped_device, kobj_holder.kobj); if (test_bit(DMF_FREEING, &md->flags) || dm_deleting_md(md)) diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 45b97da1bd06..9b3222f44835 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -15,6 +15,8 @@ #include <linux/list.h> #include <linux/blkdev.h> #include <linux/hdreg.h> +#include <linux/completion.h> +#include <linux/kobject.h> /* * Suspend feature flags @@ -125,12 +127,27 @@ void dm_interface_exit(void); /* * sysfs interface */ +struct dm_kobject_holder { + struct kobject kobj; + struct completion completion; +}; + +static inline struct completion *dm_get_completion_from_kobject(struct kobject *kobj) +{ + return &container_of(kobj, struct dm_kobject_holder, kobj)->completion; +} + int dm_sysfs_init(struct mapped_device *md); void dm_sysfs_exit(struct mapped_device *md); struct kobject *dm_kobject(struct mapped_device *md); struct mapped_device *dm_get_from_kobject(struct kobject *kobj); /* + * The kobject helper + */ +void dm_kobject_release(struct kobject *kobj); + +/* * Targets for linear and striped mappings */ int dm_linear_init(void); diff --git a/drivers/md/persistent-data/dm-space-map-common.c b/drivers/md/persistent-data/dm-space-map-common.c index 3e7a88d99eb0..0d240373ffab 100644 --- a/drivers/md/persistent-data/dm-space-map-common.c +++ b/drivers/md/persistent-data/dm-space-map-common.c @@ -245,6 +245,10 @@ int sm_ll_extend(struct ll_disk *ll, dm_block_t extra_blocks) return -EINVAL; } + /* + * We need to set this before the dm_tm_new_block() call below. + */ + ll->nr_blocks = nr_blocks; for (i = old_blocks; i < blocks; i++) { struct dm_block *b; struct disk_index_entry idx; @@ -252,6 +256,7 @@ int sm_ll_extend(struct ll_disk *ll, dm_block_t extra_blocks) r = dm_tm_new_block(ll->tm, &dm_sm_bitmap_validator, &b); if (r < 0) return r; + idx.blocknr = cpu_to_le64(dm_block_location(b)); r = dm_tm_unlock(ll->tm, b); @@ -266,7 +271,6 @@ int sm_ll_extend(struct ll_disk *ll, dm_block_t extra_blocks) return r; } - ll->nr_blocks = nr_blocks; return 0; } diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c index 58fc1eef7499..afb419e514bf 100644 --- a/drivers/md/persistent-data/dm-space-map-metadata.c +++ b/drivers/md/persistent-data/dm-space-map-metadata.c @@ -608,20 +608,38 @@ static int sm_metadata_extend(struct dm_space_map *sm, dm_block_t extra_blocks) * Flick into a mode where all blocks get allocated in the new area. */ smm->begin = old_len; - memcpy(&smm->sm, &bootstrap_ops, sizeof(smm->sm)); + memcpy(sm, &bootstrap_ops, sizeof(*sm)); /* * Extend. */ r = sm_ll_extend(&smm->ll, extra_blocks); + if (r) + goto out; /* - * Switch back to normal behaviour. + * We repeatedly increment then commit until the commit doesn't + * allocate any new blocks. */ - memcpy(&smm->sm, &ops, sizeof(smm->sm)); - for (i = old_len; !r && i < smm->begin; i++) - r = sm_ll_inc(&smm->ll, i, &ev); + do { + for (i = old_len; !r && i < smm->begin; i++) { + r = sm_ll_inc(&smm->ll, i, &ev); + if (r) + goto out; + } + old_len = smm->begin; + + r = sm_ll_commit(&smm->ll); + if (r) + goto out; + + } while (old_len != smm->begin); +out: + /* + * Switch back to normal behaviour. + */ + memcpy(sm, &ops, sizeof(*sm)); return r; } diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index a54182dd0e91..362de38a7d8e 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c @@ -157,15 +157,10 @@ static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg) return ret; } -static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) +static u16 __dib8000_read_word(struct dib8000_state *state, u16 reg) { u16 ret; - if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { - dprintk("could not acquire lock"); - return 0; - } - state->i2c_write_buffer[0] = reg >> 8; state->i2c_write_buffer[1] = reg & 0xff; @@ -183,6 +178,21 @@ static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) dprintk("i2c read error on %d", reg); ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; + + return ret; +} + +static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) +{ + u16 ret; + + if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { + dprintk("could not acquire lock"); + return 0; + } + + ret = __dib8000_read_word(state, reg); + mutex_unlock(&state->i2c_buffer_lock); return ret; @@ -192,8 +202,15 @@ static u32 dib8000_read32(struct dib8000_state *state, u16 reg) { u16 rw[2]; - rw[0] = dib8000_read_word(state, reg + 0); - rw[1] = dib8000_read_word(state, reg + 1); + if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { + dprintk("could not acquire lock"); + return 0; + } + + rw[0] = __dib8000_read_word(state, reg + 0); + rw[1] = __dib8000_read_word(state, reg + 1); + + mutex_unlock(&state->i2c_buffer_lock); return ((rw[0] << 16) | (rw[1])); } @@ -2445,7 +2462,8 @@ static int dib8000_autosearch_start(struct dvb_frontend *fe) if (state->revision == 0x8090) internal = dib8000_read32(state, 23) / 1000; - if (state->autosearch_state == AS_SEARCHING_FFT) { + if ((state->revision >= 0x8002) && + (state->autosearch_state == AS_SEARCHING_FFT)) { dib8000_write_word(state, 37, 0x0065); /* P_ctrl_pha_off_max default values */ dib8000_write_word(state, 116, 0x0000); /* P_ana_gain to 0 */ @@ -2481,7 +2499,8 @@ static int dib8000_autosearch_start(struct dvb_frontend *fe) dib8000_write_word(state, 770, (dib8000_read_word(state, 770) & 0xdfff) | (1 << 13)); /* P_restart_ccg = 1 */ dib8000_write_word(state, 770, (dib8000_read_word(state, 770) & 0xdfff) | (0 << 13)); /* P_restart_ccg = 0 */ dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x7ff) | (0 << 15) | (1 << 13)); /* P_restart_search = 0; */ - } else if (state->autosearch_state == AS_SEARCHING_GUARD) { + } else if ((state->revision >= 0x8002) && + (state->autosearch_state == AS_SEARCHING_GUARD)) { c->transmission_mode = TRANSMISSION_MODE_8K; c->guard_interval = GUARD_INTERVAL_1_8; c->inversion = 0; @@ -2583,7 +2602,8 @@ static int dib8000_autosearch_irq(struct dvb_frontend *fe) struct dib8000_state *state = fe->demodulator_priv; u16 irq_pending = dib8000_read_word(state, 1284); - if (state->autosearch_state == AS_SEARCHING_FFT) { + if ((state->revision >= 0x8002) && + (state->autosearch_state == AS_SEARCHING_FFT)) { if (irq_pending & 0x1) { dprintk("dib8000_autosearch_irq: max correlation result available"); return 3; diff --git a/drivers/media/dvb-frontends/m88rs2000.c b/drivers/media/dvb-frontends/m88rs2000.c index 4da5272075cb..02699c111019 100644 --- a/drivers/media/dvb-frontends/m88rs2000.c +++ b/drivers/media/dvb-frontends/m88rs2000.c @@ -110,28 +110,94 @@ static u8 m88rs2000_readreg(struct m88rs2000_state *state, u8 reg) return b1[0]; } +static u32 m88rs2000_get_mclk(struct dvb_frontend *fe) +{ + struct m88rs2000_state *state = fe->demodulator_priv; + u32 mclk; + u8 reg; + /* Must not be 0x00 or 0xff */ + reg = m88rs2000_readreg(state, 0x86); + if (!reg || reg == 0xff) + return 0; + + reg /= 2; + reg += 1; + + mclk = (u32)(reg * RS2000_FE_CRYSTAL_KHZ + 28 / 2) / 28; + + return mclk; +} + +static int m88rs2000_set_carrieroffset(struct dvb_frontend *fe, s16 offset) +{ + struct m88rs2000_state *state = fe->demodulator_priv; + u32 mclk; + s32 tmp; + u8 reg; + int ret; + + mclk = m88rs2000_get_mclk(fe); + if (!mclk) + return -EINVAL; + + tmp = (offset * 4096 + (s32)mclk / 2) / (s32)mclk; + if (tmp < 0) + tmp += 4096; + + /* Carrier Offset */ + ret = m88rs2000_writereg(state, 0x9c, (u8)(tmp >> 4)); + + reg = m88rs2000_readreg(state, 0x9d); + reg &= 0xf; + reg |= (u8)(tmp & 0xf) << 4; + + ret |= m88rs2000_writereg(state, 0x9d, reg); + + return ret; +} + static int m88rs2000_set_symbolrate(struct dvb_frontend *fe, u32 srate) { struct m88rs2000_state *state = fe->demodulator_priv; int ret; - u32 temp; + u64 temp; + u32 mclk; u8 b[3]; if ((srate < 1000000) || (srate > 45000000)) return -EINVAL; + mclk = m88rs2000_get_mclk(fe); + if (!mclk) + return -EINVAL; + temp = srate / 1000; - temp *= 11831; - temp /= 68; - temp -= 3; + temp *= 1 << 24; + + do_div(temp, mclk); b[0] = (u8) (temp >> 16) & 0xff; b[1] = (u8) (temp >> 8) & 0xff; b[2] = (u8) temp & 0xff; + ret = m88rs2000_writereg(state, 0x93, b[2]); ret |= m88rs2000_writereg(state, 0x94, b[1]); ret |= m88rs2000_writereg(state, 0x95, b[0]); + if (srate > 10000000) + ret |= m88rs2000_writereg(state, 0xa0, 0x20); + else + ret |= m88rs2000_writereg(state, 0xa0, 0x60); + + ret |= m88rs2000_writereg(state, 0xa1, 0xe0); + + if (srate > 12000000) + ret |= m88rs2000_writereg(state, 0xa3, 0x20); + else if (srate > 2800000) + ret |= m88rs2000_writereg(state, 0xa3, 0x98); + else + ret |= m88rs2000_writereg(state, 0xa3, 0x90); + deb_info("m88rs2000: m88rs2000_set_symbolrate\n"); return ret; } @@ -261,8 +327,6 @@ struct inittab m88rs2000_shutdown[] = { struct inittab fe_reset[] = { {DEMOD_WRITE, 0x00, 0x01}, - {DEMOD_WRITE, 0xf1, 0xbf}, - {DEMOD_WRITE, 0x00, 0x01}, {DEMOD_WRITE, 0x20, 0x81}, {DEMOD_WRITE, 0x21, 0x80}, {DEMOD_WRITE, 0x10, 0x33}, @@ -305,9 +369,6 @@ struct inittab fe_trigger[] = { {DEMOD_WRITE, 0x9b, 0x64}, {DEMOD_WRITE, 0x9e, 0x00}, {DEMOD_WRITE, 0x9f, 0xf8}, - {DEMOD_WRITE, 0xa0, 0x20}, - {DEMOD_WRITE, 0xa1, 0xe0}, - {DEMOD_WRITE, 0xa3, 0x38}, {DEMOD_WRITE, 0x98, 0xff}, {DEMOD_WRITE, 0xc0, 0x0f}, {DEMOD_WRITE, 0x89, 0x01}, @@ -540,9 +601,8 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe) struct dtv_frontend_properties *c = &fe->dtv_property_cache; fe_status_t status; int i, ret = 0; - s32 tmp; u32 tuner_freq; - u16 offset = 0; + s16 offset = 0; u8 reg; state->no_lock_count = 0; @@ -567,29 +627,26 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe) if (ret < 0) return -ENODEV; - offset = tuner_freq - c->frequency; - - /* calculate offset assuming 96000kHz*/ - tmp = offset; - tmp *= 65536; - - tmp = (2 * tmp + 96000) / (2 * 96000); - if (tmp < 0) - tmp += 65536; + offset = (s16)((s32)tuner_freq - c->frequency); - offset = tmp & 0xffff; + /* default mclk value 96.4285 * 2 * 1000 = 192857 */ + if (((c->frequency % 192857) >= (192857 - 3000)) || + (c->frequency % 192857) <= 3000) + ret = m88rs2000_writereg(state, 0x86, 0xc2); + else + ret = m88rs2000_writereg(state, 0x86, 0xc6); - ret = m88rs2000_writereg(state, 0x9a, 0x30); - /* Unknown usually 0xc6 sometimes 0xc1 */ - reg = m88rs2000_readreg(state, 0x86); - ret |= m88rs2000_writereg(state, 0x86, reg); - /* Offset lower nibble always 0 */ - ret |= m88rs2000_writereg(state, 0x9c, (offset >> 8)); - ret |= m88rs2000_writereg(state, 0x9d, offset & 0xf0); + ret |= m88rs2000_set_carrieroffset(fe, offset); + if (ret < 0) + return -ENODEV; + /* Reset demod by symbol rate */ + if (c->symbol_rate > 27500000) + ret = m88rs2000_writereg(state, 0xf1, 0xa4); + else + ret = m88rs2000_writereg(state, 0xf1, 0xbf); - /* Reset Demod */ - ret = m88rs2000_tab_set(state, fe_reset); + ret |= m88rs2000_tab_set(state, fe_reset); if (ret < 0) return -ENODEV; diff --git a/drivers/media/dvb-frontends/m88rs2000.h b/drivers/media/dvb-frontends/m88rs2000.h index 14ce31e76ae6..0a50ea90736b 100644 --- a/drivers/media/dvb-frontends/m88rs2000.h +++ b/drivers/media/dvb-frontends/m88rs2000.h @@ -53,6 +53,8 @@ static inline struct dvb_frontend *m88rs2000_attach( } #endif /* CONFIG_DVB_M88RS2000 */ +#define RS2000_FE_CRYSTAL_KHZ 27000 + enum { DEMOD_WRITE = 0x1, WRITE_DELAY = 0x10, diff --git a/drivers/media/dvb-frontends/nxt200x.c b/drivers/media/dvb-frontends/nxt200x.c index fbca9856313a..4bf057544607 100644 --- a/drivers/media/dvb-frontends/nxt200x.c +++ b/drivers/media/dvb-frontends/nxt200x.c @@ -40,7 +40,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt /* Max transfer size done by I2C transfer functions */ -#define MAX_XFER_SIZE 64 +#define MAX_XFER_SIZE 256 #define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw" #define NXT2004_DEFAULT_FIRMWARE "dvb-fe-nxt2004.fw" diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index d12faa691af8..961d7ff75427 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -177,21 +177,6 @@ unlock: mutex_unlock(&dev->mfc_mutex); } -static enum s5p_mfc_node_type s5p_mfc_get_node_type(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - - if (!vdev) { - mfc_err("failed to get video_device"); - return MFCNODE_INVALID; - } - if (vdev->index == 0) - return MFCNODE_DECODER; - else if (vdev->index == 1) - return MFCNODE_ENCODER; - return MFCNODE_INVALID; -} - static void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev) { mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT); @@ -701,6 +686,7 @@ irq_cleanup_hw: /* Open an MFC node */ static int s5p_mfc_open(struct file *file) { + struct video_device *vdev = video_devdata(file); struct s5p_mfc_dev *dev = video_drvdata(file); struct s5p_mfc_ctx *ctx = NULL; struct vb2_queue *q; @@ -738,7 +724,7 @@ static int s5p_mfc_open(struct file *file) /* Mark context as idle */ clear_work_bit_irqsave(ctx); dev->ctx[ctx->num] = ctx; - if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) { + if (vdev == dev->vfd_dec) { ctx->type = MFCINST_DECODER; ctx->c_ops = get_dec_codec_ops(); s5p_mfc_dec_init(ctx); @@ -748,7 +734,7 @@ static int s5p_mfc_open(struct file *file) mfc_err("Failed to setup mfc controls\n"); goto err_ctrls_setup; } - } else if (s5p_mfc_get_node_type(file) == MFCNODE_ENCODER) { + } else if (vdev == dev->vfd_enc) { ctx->type = MFCINST_ENCODER; ctx->c_ops = get_enc_codec_ops(); /* only for encoder */ @@ -793,10 +779,10 @@ static int s5p_mfc_open(struct file *file) q = &ctx->vq_dst; q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; q->drv_priv = &ctx->fh; - if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) { + if (vdev == dev->vfd_dec) { q->io_modes = VB2_MMAP; q->ops = get_dec_queue_ops(); - } else if (s5p_mfc_get_node_type(file) == MFCNODE_ENCODER) { + } else if (vdev == dev->vfd_enc) { q->io_modes = VB2_MMAP | VB2_USERPTR; q->ops = get_enc_queue_ops(); } else { @@ -815,10 +801,10 @@ static int s5p_mfc_open(struct file *file) q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; q->io_modes = VB2_MMAP; q->drv_priv = &ctx->fh; - if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) { + if (vdev == dev->vfd_dec) { q->io_modes = VB2_MMAP; q->ops = get_dec_queue_ops(); - } else if (s5p_mfc_get_node_type(file) == MFCNODE_ENCODER) { + } else if (vdev == dev->vfd_enc) { q->io_modes = VB2_MMAP | VB2_USERPTR; q->ops = get_enc_queue_ops(); } else { diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index ef4074cd5316..f804c1faa7ff 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -113,15 +113,6 @@ enum s5p_mfc_fmt_type { }; /** - * enum s5p_mfc_node_type - The type of an MFC device node. - */ -enum s5p_mfc_node_type { - MFCNODE_INVALID = -1, - MFCNODE_DECODER = 0, - MFCNODE_ENCODER = 1, -}; - -/** * enum s5p_mfc_inst_type - The type of an MFC instance. */ enum s5p_mfc_inst_type { diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c index 90cfa35ef6e6..eeab79bdd2aa 100644 --- a/drivers/media/usb/dvb-usb-v2/anysee.c +++ b/drivers/media/usb/dvb-usb-v2/anysee.c @@ -442,6 +442,7 @@ static struct cxd2820r_config anysee_cxd2820r_config = { * IOD[0] ZL10353 1=enabled * IOE[0] tuner 0=enabled * tuner is behind ZL10353 I2C-gate + * tuner is behind TDA10023 I2C-gate * * E7 TC VID=1c73 PID=861f HW=18 FW=0.7 AMTCI=0.5 "anysee-E7TC(LP)" * PCB: 508TC (rev0.6) @@ -956,7 +957,7 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap) if (fe && adap->fe[1]) { /* attach tuner for 2nd FE */ - fe = dvb_attach(dvb_pll_attach, adap->fe[0], + fe = dvb_attach(dvb_pll_attach, adap->fe[1], (0xc0 >> 1), &d->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A); } diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index 9f12f91d6296..4be5be34194f 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -51,6 +51,8 @@ * document number TBD : Lynx Point * document number TBD : Lynx Point-LP * document number TBD : Wellsburg + * document number TBD : Avoton SoC + * document number TBD : Coleto Creek */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -207,6 +209,8 @@ enum lpc_chipsets { LPC_LPT, /* Lynx Point */ LPC_LPT_LP, /* Lynx Point-LP */ LPC_WBG, /* Wellsburg */ + LPC_AVN, /* Avoton SoC */ + LPC_COLETO, /* Coleto Creek */ }; struct lpc_ich_info lpc_chipset_info[] = { @@ -491,6 +495,14 @@ struct lpc_ich_info lpc_chipset_info[] = { .name = "Wellsburg", .iTCO_version = 2, }, + [LPC_AVN] = { + .name = "Avoton SoC", + .iTCO_version = 1, + }, + [LPC_COLETO] = { + .name = "Coleto Creek", + .iTCO_version = 2, + }, }; /* @@ -704,6 +716,11 @@ static DEFINE_PCI_DEVICE_TABLE(lpc_ich_ids) = { { PCI_VDEVICE(INTEL, 0x8d5d), LPC_WBG}, { PCI_VDEVICE(INTEL, 0x8d5e), LPC_WBG}, { PCI_VDEVICE(INTEL, 0x8d5f), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x1f38), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x1f39), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x1f3a), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x1f3b), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x2390), LPC_COLETO}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE(pci, lpc_ich_ids); diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 4f98f8b38395..9cf08651d2bf 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1937,6 +1937,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) struct mmc_card *card = md->queue.card; struct mmc_host *host = card->host; unsigned long flags; + unsigned int cmd_flags = req ? req->cmd_flags : 0; #ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME if (mmc_bus_needs_resume(card->host)) @@ -1957,7 +1958,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) } mq->flags &= ~MMC_QUEUE_NEW_REQUEST; - if (req && req->cmd_flags & REQ_DISCARD) { + if (cmd_flags & REQ_DISCARD) { /* complete ongoing async transfer before issuing discard */ if (card->host->areq) mmc_blk_issue_rw_rq(mq, NULL); @@ -1966,7 +1967,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) ret = mmc_blk_issue_secdiscard_rq(mq, req); else ret = mmc_blk_issue_discard_rq(mq, req); - } else if (req && req->cmd_flags & REQ_FLUSH) { + } else if (cmd_flags & REQ_FLUSH) { /* complete ongoing async transfer before issuing flush */ if (card->host->areq) mmc_blk_issue_rw_rq(mq, NULL); @@ -1982,7 +1983,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) out: if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) || - (req && (req->cmd_flags & MMC_REQ_SPECIAL_MASK))) + (cmd_flags & MMC_REQ_SPECIAL_MASK)) /* * Release host when there are no more requests * and after special request(discard, flush) is done. diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index b5c95043f7ef..84b054b08462 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -1188,11 +1188,22 @@ static void atmci_start_request(struct atmel_mci *host, iflags |= ATMCI_CMDRDY; cmd = mrq->cmd; cmdflags = atmci_prepare_command(slot->mmc, cmd); - atmci_send_command(host, cmd, cmdflags); + + /* + * DMA transfer should be started before sending the command to avoid + * unexpected errors especially for read operations in SDIO mode. + * Unfortunately, in PDC mode, command has to be sent before starting + * the transfer. + */ + if (host->submit_data != &atmci_submit_data_dma) + atmci_send_command(host, cmd, cmdflags); if (data) host->submit_data(host, data); + if (host->submit_data == &atmci_submit_data_dma) + atmci_send_command(host, cmd, cmdflags); + if (mrq->stop) { host->stop_cmdr = atmci_prepare_command(slot->mmc, mrq->stop); host->stop_cmdr |= ATMCI_CMDR_STOP_XFER; diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 07e5784e5cd3..9896b636c4eb 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -676,7 +676,6 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat, ecc_stat >>= 4; } while (--no_subpages); - mtd->ecc_stats.corrected += ret; pr_debug("%d Symbol Correctable RS-ECC Error\n", ret); return ret; diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index f1cb706445c7..6ae046bdb263 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -34,11 +34,11 @@ #include <linux/interrupt.h> #include <linux/spinlock.h> #include <linux/platform_device.h> -#include <linux/mod_devicetable.h> #include <linux/log2.h> #include <linux/pm.h> #include <linux/of.h> #include <linux/of_platform.h> +#include <linux/dmi.h> /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ #include <asm-generic/rtc.h> @@ -377,6 +377,51 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) return 0; } +/* + * Do not disable RTC alarm on shutdown - workaround for b0rked BIOSes. + */ +static bool alarm_disable_quirk; + +static int __init set_alarm_disable_quirk(const struct dmi_system_id *id) +{ + alarm_disable_quirk = true; + pr_info("rtc-cmos: BIOS has alarm-disable quirk. "); + pr_info("RTC alarms disabled\n"); + return 0; +} + +static const struct dmi_system_id rtc_quirks[] __initconst = { + /* https://bugzilla.novell.com/show_bug.cgi?id=805740 */ + { + .callback = set_alarm_disable_quirk, + .ident = "IBM Truman", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "4852570"), + }, + }, + /* https://bugzilla.novell.com/show_bug.cgi?id=812592 */ + { + .callback = set_alarm_disable_quirk, + .ident = "Gigabyte GA-990XA-UD3", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, + "Gigabyte Technology Co., Ltd."), + DMI_MATCH(DMI_PRODUCT_NAME, "GA-990XA-UD3"), + }, + }, + /* http://permalink.gmane.org/gmane.linux.kernel/1604474 */ + { + .callback = set_alarm_disable_quirk, + .ident = "Toshiba Satellite L300", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L300"), + }, + }, + {} +}; + static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) { struct cmos_rtc *cmos = dev_get_drvdata(dev); @@ -385,6 +430,9 @@ static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) if (!is_valid_irq(cmos->irq)) return -EINVAL; + if (alarm_disable_quirk) + return 0; + spin_lock_irqsave(&rtc_lock, flags); if (enabled) @@ -1163,6 +1211,8 @@ static int __init cmos_init(void) platform_driver_registered = true; } + dmi_check_system(rtc_quirks); + if (retval == 0) return 0; diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index a4ec5f4ec817..cd716f4cd37f 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -180,8 +180,6 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first, transfer_list); } - len -= prepend_len; - init_completion(&bs->done); /* Fill in the Message control register */ diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 32b7bb111eb6..ca99ac9295cf 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -584,7 +584,9 @@ static void spi_pump_messages(struct kthread_work *work) ret = master->transfer_one_message(master, master->cur_msg); if (ret) { dev_err(&master->dev, - "failed to transfer one message from queue\n"); + "failed to transfer one message from queue: %d\n", ret); + master->cur_msg->status = ret; + spi_finalize_current_message(master); return; } } |